sfGuardAuth across multiple apps - symfony1

I've got 3 apps: Backend, Frontend and Members.
And I've got 2 credentials: Administrators and Members.
Administrators are imported by default but Members are created in the Backend.
When a Member is created, an event handler also inserts this Member as a sf_guard_user and of course, the proper relations in sf_guard_user_group and sf_guard_user_permission.
That's the boring part, now the fun:
Frontend is not secured, but Members is and using these credentials: [administrator, member].
According to all this, Members created in the Backend that also get inserted (correctly as far as I can tell) should be able to login to the Members secured app, since they get the member group/permission/credential.
This is not happenning, the only ones that can login to the Members app are the administrators, which is not wrong, but either is the fact that correctly created Member users can't login to it.
The error thrown by the guard is the classic: The username and/or password is invalid.
Now that I edit the error, the salt comes to mind: How would one emulate the inserting of the salt as the guard does it? Maybe that's what I'm not inserting correctly (or inserting at all) and thus the password invalid error (and in fact everythine else I've described is ok! omg)
And that's my problem.
Thanks in advance :)

[administrator, member] means both are required, I believe.
I think you want [[administrator, member]] for the credential requirement.
Also, yes, you will want to make sure you use a salt, and set the algo.
parent::_set('password', call_user_func_array($algorithm, array($salt.$password)));
Salt before password, as well.

Related

Migrating U2F to WebAuthn gem in Ruby, where to get the parameters for AuthenticatorAttestationResponse

I have a couple of questions about the WebAuthn gem and the use of U2fMigrator.
I hope someone can point me in the right direction about it.
I am in the step just after converting my old U2F credentials using U2fMigrator.
migrated_credential = WebAuthn::U2fMigrator.new(
app_id: my_domain,
certificate: u2f_registration.certificate,
key_handle: u2f_registration.key_handle,
public_key: u2f_registration.binary_public_key,
counter: u2f_registration.counter
)
The documentation says: ā€œU2fMigrator class quacks like WebAuthn::AuthenticatorAttestationResponseā€ but without verify implementation.
Does that mean I need to create an instance of this AuthenticatorAttestationResponse for authentication?
If so. Where I should get this data from?
assertion_response = WebAuthn::AuthenticatorAssertionResponse.new(
credential_id: '',
authenticator_data: '',
client_data_json: '',
signature: '',
)
I am guessing that will allow me to authenticate the new migrated credentials like this:
assertion_response.verify(
WebAuthn::Credential.options_for_get(:extensions => { appid: my_domain }).challenge,
allowed_creadentials: migrated_credential.credential,
rp_id: my_domain
)
And also, I am guessing I don't need to re-register these credentials yet.
I am following this documentation:
https://github.com/cedarcode/webauthn-ruby/blob/master/docs/u2f_migration.md
https://github.com/castle/ruby-u2f
https://github.com/cedarcode/webauthn-ruby/blob/master/README.md#authentication
UPDATE 1
I've found this cool explanation in this guide
I will dig into it and I'll post the solution if I can find it.
UPDATE 2
I've spent the whole week trying to get the authenticatorAssertionResponse
from
Unfortunately, I only get a message saying I don't have a key registered:
I'm passing through the extension and appid where the U2F credential was registered originally. I wonder if it stoped working now the deprecation is complete.
U2fMigrator is instantiated with data that's already stored in your database. Instances of it respond to the same methods as AuthenticatorAttestationResponse, except it misses a verify method since the data was already verified in the past. In other words: the migrator behaves nearly the same as a freshly WebAuthn registered authenticator and it is meant to be used as such.
Does that mean I need to create an instance of this
AuthenticatorAttestationResponse for authentication?
Yes. The AuthenticatorAttestationResponse is instantiated with browser data from the WebAuthn navigator.credentials.get call. This in itself is unrelated to the U2F migration question, except for the part where the data comes from for its verify method. This comes either from a migrator instance (in the "real time conversion" approach) or is retrieved from the database.
Hope that makes sense, PRs welcome to improve the docs!

DataSnap and Database Connection / Login

I am trying to work out the "right" way to establish a connection to my database from the server of my DataSnap application.
Each (most) of my tables in the database have fields (whose values are set via a trigger on insert and update) called Updated and Created (this is the current time stamp when the record is written) and updated_by and created_by which (should) contain the currently logged in user.
I want the user to 'login' from the client side such that these fields reflect the user who has logged in (and by extension, I'll get user authentication from the database, not just from the server). I can handle the authentication to the server itself from the client ok handling the OnUserAuthenticate and OnUserAuthorize events on the server. I am trying to then pass the credentials to my database so that the triggers can set the fields stated above correctly.
So what is the way to approach this scenario? I am wonder if the DSAuthProxyUser and DSAuthProxyPassword from the client can be used but I can't find much (any) documentation on how I would use that. Do I establish a new connection for every user who connects? This seems most logical to me. I'm not going to have a lot of concurrent users. Tops 30. Most likely 5-10. But what is the "normal" way this is done? I don't want to (hope I don't have to) pass in the username to each of my insert/updates to set the values in the tables.
I hope I have explained my situation clearly.
Thanks
I haven't used it yet, but it looks to me that the RDB$SET_CONTEXT() and RDB$GET_CONTEXT() introduced in Firebird 2 are what you need. Using these functions, you can set (and get) additional information specific to the user session (namespace USER_SESSION) or the current transaction (namespace USER_TRANSACTION). You can also retrieve additional system information for the current session (namespace SYSTEM), but that is probably not relevant for your case.
What you would need to do is call the RDB$SET_CONTEXT() method in that OnUserAuthorize event, eg using (as a query):
SELECT RDB$SET_CONTEXT('USER_SESSION', 'actualuser', '<name of user')
FROM RDB$DATABASE
Here 'actualuser' is the context variable we use. In your triggers you can then retrieve the name (assuming PSQL, with a declared variable actualuser)
actualuser = RDB$GET_CONTEXT('USER_SESSION', 'actualuser');
You can then use actualuser in the rest of your trigger. Just make sure you also account for the case where the context variable is not set (eg an administrator making direct changes to the database or something like that).
Firebird has the CURRENT_USER keyword which can be used in SQL.
The example below is based on http://www.firebirdsql.org/refdocs/langrefupd15-current_user.html
create trigger bi_customers for customers before insert as
begin
New.created_by = CURRENT_USER;
end
To have the user name for updates, simply declare a before update trigger like
create trigger bi_customers for customers before update as
begin
New.updated_by = CURRENT_USER;
end
This solution requires a 1:1 mapping of database users to external users. In the most simple implementation, it means that the DataSnap session authenticates the user credentials against the database.
In your description however, it seems to be a two step authentification (first against the DataSnap layer, then against the database). I am not sure how this can be done regarding safe password handling, and if you plan to have a separate user/password table only for the first authentication stage (DataSnap) and a user login mapping from DataSnap to database as some kind of 'decoupling'.

Rails POST parameter with identical route parameter

I have the following route:
post ':client_name/login' => 'auth#log_in'
Client side I have a form with the following fields:
username
password
and client_name
I was hoping that the form data would override the route data so that I could change the client name if needed. But it doesn't. Any chance there's a setting for accessing that? Or a way to directly access only the post data?
F.y.i.: I don't show that <input> tag unless the user puts in the wrong password first. In that case I provide it (already filled out with the value from the route). This is helpful mainly for internal users who might get a link from one of their clients, they can then log in with a special value for the client that gives them more universal access.
Alright, until someone gives me a better solution (and I don't believe there is no better solution) I'll change the name of the posted client name to :override_client_name.

How do you create a unique identifier for users for tracking purposes?

I would like to be able to add a user referal params on all invite links sent out from my site... example:
http://site.com/invited_by?=ajraux
How can I generate a code that is short like "ajraux" for all users on my site? Does it need to be a field in the database? Can it be created on the spot? How are web companies doing this?
Thanks
You could create random numbers and encode them in base-36, something simple like this:
rand(1e12).to_s(36)
Generate one for each user on first use and store it with the user. Add a unique constraint on your random token (in both your model and the database) and generate a new one if you get a uniqueness violation. You might want to log a warning somewhere that you'll see it if you need to try more than, say, five times to get a unique value; if you start getting a lot of warnings then bump that 1e12 up to 1e15 (or higher).
That would give you a random looking token attached to each user, the tokens would be URL-safe, they're quick and easy to generate, you shouldn't get that many collisions, and it will be easy to backtrack from a token to the user.
One way of doing this is to use the unique identifier of the user, say "id", that's in the database, but this is also dangerous because you are revealing too much about your database.
So you can add a twist to the previous situation and encrypt and decrypt the id so that when it's in the url it is encrypted and then when you receive it you can decrypt it and use it.
As cjapes said, using ID is not a good solution and mu is too short's answer is good for most cases. However if you have a site which offers vanity URLs, like about.me does then each user will have a permalink kind of column storing their vanity URL. You can just use the value from that column when building the URL.
On the receiving end you can do:
#referring_friend = User.find_by_permalink(params[:permalink])

LDAP through Ruby or Rails

I've been attempting to hook a Rails application up to ActiveDirectory. I'll be synchronizing data about users between AD and a database, currently MySQL (but may turn into SQL Server or PostgreSQL).
I've checked out activedirectory-ruby, and it looks really buggy (for a 1.0 release!?). It wraps Net::LDAP, so I tried using that instead, but it's really close to the actual syntax of LDAP, and I enjoyed the abstraction of ActiveDirectory-Ruby because of its ActiveRecord-like syntax.
Is there an elegant ORM-type tool for a directory server? Better yet, if there were some kind of scaffolding tool for LDAP (CRUD for users, groups, organizational units, and so on). Then I could quickly integrate that with my existing authentication code though Authlogic, and keep all of the data synchronized.
Here is sample code I use with the net-ldap gem to verify user logins from the ActiveDirectory server at my work:
require 'net/ldap' # gem install net-ldap
def name_for_login( email, password )
email = email[/\A\w+/].downcase # Throw out the domain, if it was there
email << "#mycompany.com" # I only check people in my company
ldap = Net::LDAP.new(
host: 'ldap.mycompany.com', # Thankfully this is a standard name
auth: { method: :simple, email: email, password:password }
)
if ldap.bind
# Yay, the login credentials were valid!
# Get the user's full name and return it
ldap.search(
base: "OU=Users,OU=Accounts,DC=mycompany,DC=com",
filter: Net::LDAP::Filter.eq( "mail", email ),
attributes: %w[ displayName ],
return_result:true
).first.displayName.first
end
end
The first.displayName.first code at the end looks a little goofy, and so might benefit from some explanation:
Net::LDAP#search always returns an array of results, even if you end up matching only one entry. The first call to first finds the first (and presumably only) entry that matched the email address.
The Net::LDAP::Entry returned by the search conveniently lets you access attributes via method name, so some_entry.displayName is the same as some_entry['displayName'].
Every attribute in a Net::LDAP::Entry is always an array of values, even when only one value is present. Although it might be silly to have a user with multiple "displayName" values, LDAP's generic nature means that it's possible. The final first invocation turns the array-of-one-string into just the string for the user's full name.
Have you tried looking at these:
http://saush.wordpress.com/2006/07/18/rubyrails-user-authentication-with-microsoft-active-directory/
http://xaop.com/blog/2008/06/17/simple-windows-active-directory-ldap-authentication-with-rails/
This is more anecdotal than a real answer...
I had a similar experience using Samba and OpenLDAP server. I couldn't find a library to really do what I wanted so I rolled my own helper classes.
I used ldapbrowser to see what fields Samba filled in when I created a user the "official" way and and basically duplicated that.
The only tricky/non-standard LDAP thing was the crazy password encryption we have:
userPass:
"{MD5}" + Base64.encode64(Digest::MD5.digest(pass))
sambaNTPassword:
OpenSSL::Digest::MD4.hexdigest(Iconv.iconv("UCS-2", "UTF-8", pass).join).upcase
For the def authenticate(user, pass) function I try to get LDAP to bind to the domain using their credentials, if I catch an exception then the login failed, otherwise let them in.
Sorry, cannot comment yet... perhaps someone can relocate this appropriately.
#Phrogz's solution works well, but bind_simple (inside bind) raises an Net::LDAP::LdapError exception due to auth[:username] not being set as shown here:
https://github.com/ruby-ldap/ruby-net-ldap/blob/master/lib/net/ldap.rb
The corrected replaces:
auth: { method: :simple, email: email, password:password }
with:
auth: { method: :simple, username: email, password:password }
I began using ruby-activedirectory, and even extended it/fixed a few things, hosting judy-activedirectory in Github.
Doing the next iteration, I've discovered ActiveLdap has a much better code base, and I'm seriously contemplating switching to it. Does anyone have personal experience with this?
Have you checked out thoughtbot's ldap-activerecord-gateway? It might be something for you to consider...
http://github.com/thoughtbot/ldap-activerecord-gateway/tree/master

Resources