Skip to content

How To: Allow users to sign in with something other than their email address

Brian T edited this page Aug 8, 2018 · 13 revisions

If you don’t want to use email as a default field for sign in, you can specify another. We will use :username as the field name in these examples, but you can use any field.

To implement this, uncomment the following text in config/initializers/devise.rb file and specify the field you want to use during sign in, such as :username:

config.authentication_keys = [:username]

Another way is to change your model:

devise :database_authenticatable, :authentication_keys => [:username]

Then, add validations to your model:

validates :email, uniqueness: true
validates :username, uniqueness: true

Then, create a migration and migrate:

rails generate migration add_username_to_users username:string:uniq
rake db:migrate

Next, make sure you can set that field when you create and edit users. When using the strong parameters feature in newer versions of Rails, permit reading of that parameter in the controller with .permit(:username). Or if you’re using an older version of Rails, make the field accessible in your model with attr_accessible :username instead.

After this you can generate Devise views using the following command:

rails generate devise:views

And then you’ll need to modify the views in app/views/devise/sessions/new.html.erb and app/views/devise/registrations/new.html.erb to use the new form field.

Finally, you might need to change the error message that gets shown to the users if they provide incorrect credentials or when they are not found. You do this in config/locales/devise.en.yml. Look for the following:

invalid: 'Invalid email or password.'
not_found_in_database: 'Invalid email or password.'

and change it to this:

invalid: 'Invalid username or password.'
not_found_in_database: 'Invalid username or password.'

If you see

invalid: "Invalid %{authentication_keys} or password."
not_found_in_database: "Invalid %{authentication_keys} or password."

instead, you don’t need to change anything.

Note that if you aren’t using e-mail as your authentication key, then it may be the case that users can have multiple accounts with the same e-mail address. This will cause the “recoverable” module not to work well, as it will only include a link in the password reset e-mail to the first account for which it finds a matching e-mail. Here is a thread on the Google Group about how to implement adding all the accounts information into the password reset email.

Important note: If you use validatable module, define email_required? and email_changed?:

# app/models/model.rb
class Model < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable,
         :trackable, :lockable, :validatable

  def email_required?
    false
  end

  def email_changed?
    false
  end
  
  # use this instead of email_changed? for Rails = 5.1.x
  def will_save_change_to_email?
    false
  end
end

If you are using confirmable or recoverable module, you just need to define email_changed? to false.

Clone this wiki locally