OmniAuth for external authentication with rails
Omniauth is a pretty simple solution if you want your users to authenticate using oauth and openid providers. Its based on the principle that
Every authentication system can essentially be boiled down into two "phases".
- Request phase : we request information from the user that is necessary to complete authentication. This information may be POSTed to a URL or performed externally through an authentication process such as OpenID.
- Callback phase : In the Callback Phase, we receive an authenticated unique identifier that can differentiate this user from other users of the same authentication system. Additionally, we may provide user information that can be automatically harvested by the application to fill in the details of the authenticating user.
Omniauth doesn't handle your session, it mainly focuses on bringing you the required data from the provider and its upto you to manage the session. You can use any authentication system in rails to do that e.g devise, restful_authentication, authlogic etc. OmniAuth is the best solution for seamless integration of multiple authentication providers.
User is sent to /auth/:provider (provider can be twitter, facebook or any other), where he authenticates using the provider, and he returns to the callback url which is always /auth/:provider/callback. You just have to map /auth/:provider/callback to a controller action, where you get the response data in a hash.
Include config.gem "omniauth" in your environment.rb file and run rake gems:install. You might get "libxml" missing, for that you should do apt-get for libxslt-dev and libxml3-dev. This should install omniauth.
Create config/initializers/omniauth.rb. You can choose from the list of providers
Generate the Authorization model.
script/generate model authorization provider:string uid:string user_id:integer rake db:migrate
This is how your model should look like. In the authorization model, we are storing the provider, unique id of the user within the provider and the user_id. The combination of provider and the uid is always unique.
Create a route for the callback url. In the "create" method of authorization controller we handle the data received from provider. (you can handle this in any controller, action). If the user denies giving access to his information, it will be routed back to /auth/failure. So make sure you have defined a path for that as well.
map.callback "/auth/:provider/callback", :controller => "authorizations", :action => "create" map.failure "/auth/failure", :controller => "authorizations", :action => "failure"
In the authorization controller define the "create", "failure" and "destroy" methods.
The current_user method used above returns the user in the current session. The create method does the job of
- Collecting the information sent by the provider (which is available in request.env['rack.auth'])
- Checks if the user has already authorized using the provider. If he has not and is logged in, it will associate the provider with users current account.
- It will create a new account if the user is registering for the first time with oauth and openid providers
You need a few methods in the authorization model to find and create authorizations.
In the user model