Yesterday night I was hacking on a small side project with Rails 3.2 and omniauth. I will be offering multiple OAuth connections to my users but also want a simple email and password signup/login, so I decided to go with omnniauth and omniauth-identity.
Most tutorials on omniauth-identity use a separate Identity model, but I already have a User model to take care of a user’s details, and an Authentication model, to handle all the different OAuth connections, so I don’t want a new Identity model.
So how do we make it work?
Let’s first add the omniauth initializer in config/initializers. Add as many providers as you want.
As you can see we’re telling omniauth-identity that we don’t want its Identity model but that we’re instead going to use our User model. We’re also going to send the user to our own controller in case the registration fails (the lamba is a neat catch by Ryan Bates).
Now, let’s make the User model inherit from Omniauth Identity. Before doing that make sure you have a password_digest string field in the users table:
rails g migration add_password_digest_to_users password_digest:string
A user has many authentications, where we keep track of all the services he is using:
Now let’s create some helper methods for our login in application_controller, nothing fancy:
To have auth work, we have to set up the routes, again nothing special here:
So to have a user signup with identity, we’re going to send him to /signup and use our users controller’s new action:
Here we are creating a new user, but we’re also checking if there is a user stored in the omniauth.identify env variable, since it will store there failed registration attempts. Pretty cool.
Ok, so what are we displaying? A form that posts to /auth/identity/register with all the info required. If you use simple_form like I do, you have to use input_html and set the same values as the ones we added in the initializer in the fields hash.
So what happens when we send the POST? Well, here is the cool part of all of this.
Omniauth-identiy creates a new User for us in automatic, with all the right data.
Omniauth creates a new Authentication for us, with provider set as identity and uid set as the user_id our application is returning.
We then just have to associate the authentication to the user and we’re done.
Let’s see what our sessions_controller does. Comments are pretty exhaustive here:
And there it is. Omniauth with multiple providers and omniauth-identity on the main user model. I will be adding remember-me, activation emails and such in the future but this should cover the basics and help you understand what omniauth is doing in the background.
Useful articles I used to understand and served as the basis for all of this: