Until last week, GlitterGallery used devise under the hood for it’s traditional authentication system. This week, I replaced that with one based on OpenID. This post covers the strategy I followed. If you’re looking forward to setting up an only-OpenID based authentication solution on your Rails application, I recommend reading this because from my experience, the available documentation is quite old and limited.
remove existing authentication system completely
If your app has no authentication at the moment, you may skip this section. If your application uses devise for authentication, check out this thread to remove devise. I don’t have experience with other auth systems, but my guess would be that removing authlogic and others should be similar.
add the new dependencies
gem 'ruby-openid' gem 'open_id_authentication'
Now run bundle from inside your app directory:
$ bundle install
add a sessions controller
The idea is that every time a user logs in to our application, we start a new session. To cover that logic, here’s what we’ll begin with:
class SessionsController < ApplicationController def new # spits out a login form to start session end def create # contains the logic for handling the stuff # obtained from the login process end def destroy # contains the logic for destroying the user # session (logout) end end
add a sessions resource to routes
We’ll now add a singleton resource to the application routes (config/routes.rb). Notice that we skip the edit functionality because we don’t need it:
resource :session, only: [:new, :create, :destroy]
add a view for the login form for new sessions
Note that I haven’t added any fancy formatting here. OpenID recommends additional formatting guidelines, so you might want to read through this.
<%= form_tag(session_url) do %> <%= text_field_tag "openid_identifier" %> <%= submit_tag 'Sign in' %> <% end %>
create a user model
If you already have one, you’ll have to add an accessible attribute field for the identity url:
Also remember to ensure that you have performed a migration to add an identity_url column to the user’s table.
create the login logic
Alright, here comes the fun part. Here’s what I did to create the session once a user has entered his OpenID url on the login.
def create authenticate_with_open_id do |result, identity_url| if result.successful? # FIXME - needs normalizing before # checking for the identity_url unless user = User.find_by_identity_url(identity_url) user = User.create(identity_url: identity_url) end sign_in user else render 'new' end end end
#FIXME – Before you save the identity_url into the User model, it’s good to normalize it, so all identity_url’s are consistent. For example, (http://sarupbanskota.id.fedoraproject.org) and (sarupbanskota.id.fedoraproject.org) shouldn’t be treated as two different urls. I’ll show how, soon.
add helper methods
Now we’ll have to write helper methods to facilitate the sign_in. How you do it depends on your plan, here’s how I did:
module SessionsHelper def sign_in(user) cookies.permanent[:remember_token] = user.remember_token self.current_user = user redirect_to dashboard_url end def current_user=(user) @current_user = user end def current_user @current_user ||= User.find_by_remember_token(cookies[:remember_token]) end def signed_in? !current_user.nil? end def logout self.current_user= nil delete.cookies[:remember_token] end end
create the signout logic
This is pretty straightforward. If you signed in following my process, then signing out is just a matter of clearing the permanent cookie.
def destroy logout redirect_to root_url end
def logout self.current_user= nil cookies.delete(:remember_token) end
include the helper in the application controller
Finally, don’t remember to include the helper method in the ApplicationController (app/controllers/application_controller.rb).
With this, you pretty much have a neat OpenID system running. Of course, there’s a lot that can be added to this in the form of SReg extensions, but my goal was to keep the process simple.
Cheers! Remember to share feedback and as if you run into problems!