Rails log in form case-sensitivity - ruby-on-rails

How would I make a log in form case-insensitive? An example would be a user who signs up with the username "Ralph" can log in after registering using either "Ralph" or "ralph", but store the username as "Ralph" for use with things like friendly_id and views?
It'd be nice if there was a way to do this that wasn't database specific, but implemented in ruby.

Store the username however they give it to you, but call downcase on the string before passing it into whatever method you are authenticating with.

Related

How can I to code in base64 a pass field on Ruby on Rails?

I want to send a field which I add in a form in order to create user using the devise gem. These field is the password to access SVN so I don't want store it in a plain text and obviously, I cannot code it with an only one way algorithm. I thought about coding it in base 64, but I don't know how can I do it in the form field or in devise gem. This is my form field:
<%= password_field_tag :pass, type:"password", name:"user[XXXX_password]", id:"XXXX_password" %>
Can I send the field codified with Base64.encode() or similar?
Any suggestion?
Thanks
EDIT:
I will try to explain it better:
I store the data the user (mail, pass ...) but, additionally I have added two fields: user and password of subversion.
Obviously, the devise password is encrypted, but the subversion password field can not be encrypted in a single way because when passed to subversion it would not recognize it.
By reading the comments your issue on how to store the password. A general rule of thumb is to indeed encrypt it and apply the same function when the user logs in, comparing the value the user sends with the value you have in your database.
Passwords should NEVER be stored in plain text in the database, instead, store a hash of the original information.
You could use PBKDF2 (Ruby gem), or base64.
If you're using devise, the gem should take care of storing the secret for you if you set your user model correctly. Have a look at this
I don't know how this answers your question as it touches lots of core concepts, but if you could be more specific I'd be glad to expand it.

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.

Migrating existing user model to Devise

I'm trying to migrate a legacy app to Rails 3 and change the authentication to use Devise. I've created the model and migrations and imported all the user data.
I don't plan to migrate the passwords over as the existing scheme is not one we'd like to use going forward, but I want to be able to present users with a simple experience.
Ideally I'd like to catch a login error and then check the password with the legacy field and then update the Devise password with it if it matches.
I can see that Warden gives me a callback that can trap errors so I expect I can trap a login error.
However because all the passwords (in Devise) are blank I get errors relating to the hash as the encrypted_password fields are empty.
Is there a way I can update all the user accounts with a random password?
I've seen in Devise::Models::DatabaseAuthenticatable that there is a method 'password=' but if I call that, e.g. in rails console for the app:
User.find(1).password=('new')
=> "new"
I just get the same plain text string back ('new') and saving the user record post this doesn't populate the encrypted_password field.
I've searched around but can't seem to be able to find it. Any suggestions much appreciated!
Ok just in case anyone else is as cloth headed as I have been the last 24 hours, here's how you set the password:
user = User.find(id)
user.password = 'new-password'
user.save
Simple really :)

Generate temporary URL to reset password

I am looking to implement a Forgot Password feature on my website. I like the option where an email containing a temporary one-time use URL that expires after some time is sent to the user.
I have looked at the following pages to get these ideas but I am not sure how to implement this using ASP.NET and C#. As one of the users indicated, if I can implement this without storing this information inside the database, that will be ideal. Please advise.
Password reset by emailing temporary passwords
Thanks.
Probably the easiest way is going to be to modify your users table to add 2 extra columns, OR if you don't want to modify the existing table you could add a new dependent table called "UserPasswordReset" or something like that. The columns are like this:
PasswordResetToken UNIQUEIDENTIFIER,
PasswordResetExpiration DATETIME
If you go with the additional table route, you could do also add the UserID column, make it a primary key and a foriegn key reference back to your users table. A UNIQUE constraint would also be recommended. Then you simply use a Guid in your asp.net application as the token.
The flow could be something like this:
User requests password reset for their account
You insert a new record in the table (or update their user record) by setting the PasswordResetExpiration to a date in the future (DateTime.Now.AddDays(1)), and set the token to Guid.NewGuid()
Email the user a link to your ResetPassword.aspx page with the guid in the query string (http://www.yoursite.com/ResetPassword.aspx?token=Guid-here)
Use the ResetPassword.aspx page to validate the token and expiration fields. (I.E. Make sure DateTime.Now < PasswordResetExpiration)
Provide a simple form that allows the user to reset this password.
I know you wanted to avoid modifying the database, but it really is probably the simplest method.
#Alex
You can also use System.Security.Cryptography classes in .NET for the hash algorithms. For example:
using System.Security.Cryptography;
...
var hash = SHA256CryptoServiceProvider.Create().ComputeHash(myTokenToHash);
...
Here, the System.Guid class in your friend, as it will generate a unique (well, unique enough) 128-bit number:
Generate a new Guid ( System.Guid.NewGuid() )
Store that Guid somewhere (Application object maybe?)
Send a custom URL in an email with that Guid
When the user hits the site, make them enter the password you sent in the email
If the passwords match, go ahead and force them to enter a new password
I used a Hashing Class to create unique automatic logins made up of the current date/time and the users email address:
string strNow = DateTime.Now.ToString();
string strHash = strNow + strEmail;
strHash = Hash.GetHash(strHash, Hash.HashType.SHA1);
get the Hash Class from: http://www.developerfusion.com/code/4601/create-hashes-md5-sha1-sha256-sha384-sha512/
Then just take it from the URL using:
if (Request.QueryString["hash"] != null)
{
//extract Hash from the URL
string strHash = Request.QueryString["hash"];
}
I would definitely include the database in this process. Once a reset is requested, it's a good idea to indicate that the account is locked out.
For example, if you are changing your pw because you think your account may have been compromised, you definitely don't want it to remain accessible while you go about the change process.
Also, inclusion of "real" information in the reset token could be decoded if someone really wants it and has the horsepower. It would be safer to generate a random string, save it in the db in the row for that user, and then key back to it when the link is clicked.
This gives you two things:
1) There's nothing to decrypt, and therefore nothing of value can be gained from it.
2) The presence of the token in the user record indicates that reset is in progress and the account should be treated as locked out.
The goal of sending some data|string to user email is validation of account owner. Please care about some points:
Avoid sending important information in reset or activate link.
It's best way to store unique string data conjunction with user
account and send it as that link. but be aware if you send just one
section as link to user email and just check it in page, your
application may be in dangerous by brute-force or dictionary
attacker. It's enough to check a list of string to find some links
and change password. I know that has a little chance, but not zero.
Result:
I think it's better if you
combine user email with string link then encrypt them
(not hash because hashed value can't be reverse) and send to user
email.
User click and your page get the encrypted value.
decrypt value.
extract user email.
find email in database.
compare string from received link with other one attached to user
email in database.
Good luck.
I'd use a hash code to validate details in the password reset url. This can all be done without writing anything to the DB or sending any privileged info to an attaker.
To briefly explain normal password salt and hashing; say the salt is 1111 and the pasword is password, you'd concatenate the two and hash the string 1111password, say this gives you a hash of 9999, you'd then store the original salt 1111 and hash 9999 in your user record.
When you are validating a password you use the stored salt, concatenate the password attempt, hash it and compare with the stored hash. For example asecret becomes 1111asecret but hashes to 8888. This doesn't match the original hash so the password match fails.
Of course the salt and hash would normally be properly generated and calculated with established crypto libraries (don't invent your own!).
For the password reset URL I'd put in the unique identifier for the user, i.e. email address, the date the request is made, and a new hash. This hash would be generated from those details concatenated together plus the salt and hash already stored for the user.
For example:
Email: user#example.com
Request Date: 2014-07-17
Salt: 1111
Hash: 9999
Generate a new hash of those concatenated, i.e. 'user#example.com2014-07-1711119999', say this gives a hash of 7777.
The URL I then generate would then have the email, request date and the new hash:
https:\\www.example.com\ResetPassword?email=user#example.com&requestdate=2014-07-17&hash=7777
The server will combine the email and supplied date with it's salt and hash and confirm the hash it generated is the same as the supplied one. If this is Ok then it will show the reset form with the same three parameters hidden behind it, otherwise an error. These get resubmitted and rechecked when the new password is entered to prevent that form being spoofed.
The email address needs to be supplied to make the request and it is only sent out in an email to the same address. the date is hardly priveleged info and the hash is not reversible so gives nothing anyway. Nothing has been written to the database and any tampering with the parameters causes the hash to fail and the URL to report an error.
There is an issues with this approach. A safe hash makes the token really long. Either you integrate the salt into the hash itself (makes it about 20 charactes longer), or you store this unique salt in the database. If you store the salt in the database, you could as well store a random token which is not derrived from any existing
Depending on your needs, you could encrypt information, in a format similar to the following format
(UserId)-(ExpireDate)
Encrypt the data, make that the link, then decrypt the data and take action from there...
Crude, but most likely usable, and not requiring DB usage

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