OpenID and Rails: Authentication 2.0

OpenID and Rails: Authentication 2.0

penID is a service, framework, and protocol that is revolutionizing the realm of user authentication and identity services. Started in 2004 by Brad Fitzpatrick, OpenID is now a mature framework supported by major Internet organizations such as AOL, Google, IBM, Microsoft, VeriSign, and Yahoo. It offers a distributed, reliable, and open way for web sites to authenticate their users and saves web developers from the need to write yet another piece of authentication code.

This article describes what OpenID is and how it can benefit your web site development. It provides an example by demonstrating OpenID integration with the Ruby on Rails 2.0 framework.

What You Need
Ruby version 1.8.4 or later (1.8.6 recommended)
RubyGems (version 1.0.1 recommended)
Rails 2.0.2
MySQL
ruby-openid library

One Web-Wide Identity for the User
Authentication in web applications is the process of verifying someone’s identity and confirming that the user accessing the application really is who he claims to be. The most popular method of authentication is using a username and password: the username declares the user’s identity, while the password represents the verification token that ensures that only its holder can claim the identity of the associated username. The vast majority of web sites that need to verify their users’ identities adopt this form of authentication, each one implementing its own login or verification component.

Unfortunately, the username and password combination leads to extreme fragmentation of user credentials: users end up having tens of usernames and passwords for multiple sites (bank account, e-mail, blog, company web site, etc.). OpenID aims to solve this fragmentation once and for all. As stated on its web site, OpenID offers a way to define “a single digital identity across the Internet,” eliminating the need for multiple usernames across different web sites. OpenID keeps a user’s credentials in a single place, where other web sites can query them whenever they need to verify that user’s identity.

The OpenID service encompasses a few different entities that interact with each other:

  • An OpenID provider stores user credentials and exposes a standard API that other web sites can query to authenticate users. Popular free providers are myOpenID and VeriSign.
  • A relying party is a web site that wants to verify a user’s identity.
  • The end user is the person trying to authenticate him- or herself on the web site.

In the OpenID world, a user is uniquely identified by an OpenID identifier, which generally is a plain URL (think of it as the person’s unique username). The OpenID identifier usually points to the provider that is storing the user’s credentials. An example is yourname.myopenid.com.

Figure 1 and Figure 2 illustrate the differences between a traditional authentication scheme and the OpenID one, respectively.


Figure 1. A Traditional Authentication Scheme: The user has different credentials for each web site.
 
Figure 2. The OpenID Authentication Scheme: The user has only one set of credentials, shared among different web sites.

As the figures illustrate, the OpenID authentication flow is a bit different from traditional database-based authentication. OpenID authentication can be summarized in the following steps:

Figure 3. The OpenID Authentication Flow: The user has different credentials for each web site.
  1. A user wants to authenticate himself on a web site.
  2. The user provides his OpenID identifier to the web site.
  3. The web site translates the identifier into a canonical URL (such as http://yourname.myopenid.com).
  4. The web site redirects the browser to the generated URL, where the user can authenticate himself against the OpenID provider.
  5. The OpenID provider authenticates the user, either with a traditional method (username and password) or with more advanced techniques, such as certificate exchange.
  6. If successful, the OpenID provider redirects the browser back to the originating web site, along with the verified user credentials.
  7. The web site uses the credentials to identify the user and forwards him to its services.
  8. If unsuccessful, the OpenID provider redirects the browser back to the originating web site, along with an error key that the web site can use to handle the situation.

To guarantee security and prevent identity spoofing, the web site and the OpenID provider perform some extra steps. However, web developers who use the OpenID client library don’t need to get into these details, because the library handles them all transparently (the OpenID client library is used for the example in the section to follow).

The latest version of the OpenID specifications (Version 2.0) allows for further complexity by introducing the concept of provider discovery. You don’t need to delve into these details to be able to integrate your web site properly with OpenID. Figure 3 shows a schematic of the above sequence.

Connect Ruby to OpenID
The example for making web applications compatible with OpenID involves a traditional web site built upon Ruby on Rails 2.0. In following this example, you first will create a basic application and then improve it by adding credentials checking and user login. The basic application will be a basic web-based to-do list. It is purposefully simple, so that you can focus on the OpenID integration.

Make sure you have a locally running MySQL instance. Connect to it and create a development database by issuing the following command:

create database openid_development ;

The database will contain both the data used by your application and the additional tables required to interact with OpenID providers. Open a terminal and create an empty Rails application with this command:

# rails -d mysql openid

Next, verify that everything is working correctly by running the script/server command and accessing the application on http://localhost:3000/.

Create the basic scaffolding that will manage your to-do items by asking Rails to generate it. Each to-do item will have an owner (identified by a name and an email), a start and end date, and a description:

# script/generate scaffold Todo   person:string email:string start:date end:date description:text# rake db:migrate

Even though it is extremely simple, your sample application now handles to-do lists perfectly. It is now time to integrate it with OpenID, which will allow you to:

  • Provide a login screen for the application
  • Enrich the to-do creation page by reusing some of the credentials received by the OpenID provider

First, install the ruby-openid library. This library contains all the client code necessary for the interaction between your application and remote OpenID providers. You can use rubygems to install it:

# sudo gem install ruby-openid

If you inspect the installed gems, you will see something like this, depending on the version of the library installed (different versions make no difference for the purpose of this article):

# gem list --localruby-openid (2.0.4, 1.1.4)ruby-yadis (0.3.4)...rails (2.0.2)... other installed gems ...

The next step is to install the openid_authentication plugin, integrates Rails with the newly installed ruby-openid library. Since this plugin requires some database tables to work properly, you’ll also have to run rake to perform the required migrations:

# script/plugin install open_id_authentication# rake open_id_authentication:db:create# rake db:migrate

Add Some Intelligence to Your Authentication System
Now that all the pieces are in place, it is time to start modifying the application code. Open the file app/controllers/application.rb and add the following authorize method:

def authorize  unless session[:user_id]    flash[:notice] = "Please log in"    # save the URL the user requested so we can hop back to it    # after login    session[:jumpto] = request.parameters    redirect_to(:controller => "/login", :action => "index")  endend

This method will intercept all the users’ requests for actions that cannot be performed without valid credentials and redirect them to the login screen. By storing the request parameters into the session :jumpto symbol, this method also guarantees that, immediately after login, the user will be forwarded to the URL that he initially requested.

You now have to modify the todos_controller.rb that was created during the previous scaffolding. Add the before_filter as follows:

class TodosController < ApplicationController  before_filter :authorize,     :only => [ :new , :edit, :create, :update, :destroy]     ... rest of the controller as before ...end 

This ensures that all the actions that create or modify a to-do item are accessed only after a successful login.

You can now move to the core of the login mechanism by implementing the login controller. On a terminal, launch this:

# script/generate controller login

Open the generated app/controllers/login_controller.rb file, and edit it so that it matches the contents of Listing 1. This controller contains all the magic, so take a close look at it.

The index method either redirects the user to the web site main page (http://localhost:3000/todos) if he already performed login, or forwards him to the login page (http://localhost:3000/login). The view for the login page is still missing, so create the file app/views/login/index.html.erb with these contents:

<% if flash[:error] -%>  <%= flash[:error] %><% end -%><% form_tag :controller => "login" , :action => "login" do |f| -%>    <%= text_field_tag :openid_url -%>  <%= submit_tag "Login" -%><% end -%>

As you can see, instead of the traditional username and password fields, there is now only one text field, which will accept the user’s OpenID identifier. The label openid_url is a conventional one that will allow the browser to remember the user’s OpenID identifier across different OpenID-enabled web sites.

Moving on, the login and logout methods, respectively, are responsible for handling the login process and for cleaning the session of all the user’s data once he logs out of your application. The using_open_id? function belongs to the ruby-openid library, and it detects whether the user is initiating or finalizing a login. Remember that, as described in Figure 3, the login process involves two calls to your web site: the first containing the OpenID identifier to initiate the login process and the second containing the user credentials as returned by the OpenID provider. Therefore, the login method ends up being called twice and the using_open_id? function detects both occurrences (more on this later).

The authenticate function contains the bulk of the authentication logic. It delegates to the authenticate_with_open_id function within the ruby-openid library. This function accepts a block that will execute once the login completes (either successfully or not)–that is, after the second call back to the web site. The block accepts three parameters:

  • The result object defines the effectiveness of the login process. It contains methods to investigate the various possible failures (user has canceled login, OpenID provider unavailable, etc.).
  • The identity_url object contains the user OpenID identifier.
  • The registration object contains additional information about the user, according to the Simple Registration Extension for OpenID (SREG) specification.

The Simple Registration Extension is an add-on to the OpenID specification that allows providers and web sites to exchange additional information about the users. This may include the user’s e-mail, real name, date of birth, and other personal data. To respect the user’s privacy, each user can instruct the OpenID provider not to disclose this kind of information. In the previous example, you used the :required directive (as opposed to the :optional one) to require a nickname and email address along with the user’s credentials.

SREG is another way in which OpenID improves the authentication experience when compared with traditional mechanisms, where each web site would require the user to complete a registration form, specifying again and again his personal data to each interested third party.

Lastly, the authenticate method stores all the user data into the :user_id session variable and redirects the user to the originally requested page with the redirect_to(:jumpto) statement.

As you already know, the login method will be called twice–the second time being a redirect instructed from the OpenID provider to the user browser. In order for this to work, you have to perform two last steps. First, you have to define an appropriate route in the routes.rb configuration file, as follow (notice that you’re using a named route):

map.openid "login",   :controller => "login" ,   :requirements => { :method => :get }

Next, you have to reference such a named route in the root_url method of the login controller, as follows:

def root_url  openid_urlend

This guarantees to the OpenID provider that the URL the user will be redirected to after the login belongs to the same domain (trusted root) as that from which the login request originated.

After this last step, your application now accepts only properly authenticated and identified users. You can use the additional information to improve the user experience. For example, you can enable your web site to pre-enter the user’s name and email address when he creates a new to-do item. Open again the todos_controller.rb file and modify the new method as follows:

def new  @todo = Todo.new  @todo.person = session[:user_id].nickname  @todo.email = session[:user_id].email  respond_to do |format|    format.html # new.html.erb    format.xml  { render :xml => @todo }  endend

Much More to Explore
If you have any previous experience with Rails, you may have noticed that the described implementation didn’t use any of the existing traditional authentication frameworks (that is, either restful_authentication or act_as_authenticated). This is again an indication that OpenID authentication does not depend on any previously established authentication logic.

In addition, if you want to avoid the dependency on the Rails open_id_authentication plugin or you need greater flexibility, you can access the ruby-openid library directly. Listing 2 shows an alternative (and longer) login controller that uses the ruby-openid function calls and public classes directly. To differentiate it even further, it uses the filesystem (instead of the database used up to this point) to store the temporary data required throughout the handshaking between your application and the OpenID provider.

The advantages of the OpenID service are clear: less code duplication, complexity, and maintenance overhead for the developer and a more coherent web experience for the user. However, this article went through only the very superficial layers of the OpenID universe, leaving a lot of other features open to exploration. These include the new OpenID 2.0 specification, the service discovery and delegation mechanisms, the Extensible Resource Descriptor Sequence (XRDS) format, stateless relying parties, and many others.

Also, many parts of the ruby-openid library were not explored. For example, it also supports setting up a Rails OpenID provider, instead of just the client library for a relying party as described in the article. Thanks to the openness of the OpenID initiative, you can further explore the service in as much details as you may need.

devx-admin

devx-admin

Share the Post:
Global Layoffs

Tech Layoffs Are Getting Worse Globally

Since the start of 2023, the global technology sector has experienced a significant rise in layoffs, with over 236,000 workers being let go by 1,019

FinTech Leadership

Terry Clune’s Fintech Empire

Over the past 30 years, Terry Clune has built a remarkable business empire, with CluneTech at the helm. The CEO and Founder has successfully created

The Role Of AI Within A Web Design Agency?

In the digital age, the role of Artificial Intelligence (AI) in web design is rapidly evolving, transitioning from a futuristic concept to practical tools used

Generative AI Revolution

Is Generative AI the Next Internet?

The increasing demand for Generative AI models has led to a surge in its adoption across diverse sectors, with healthcare, automotive, and financial services being

Global Layoffs

Tech Layoffs Are Getting Worse Globally

Since the start of 2023, the global technology sector has experienced a significant rise in layoffs, with over 236,000 workers being let go by 1,019 tech firms, as per data

Huawei Electric Dazzle

Huawei Dazzles with Electric Vehicles and Wireless Earbuds

During a prominent unveiling event, Huawei, the Chinese telecommunications powerhouse, kept quiet about its enigmatic new 5G phone and alleged cutting-edge chip development. Instead, Huawei astounded the audience by presenting

FinTech Leadership

Terry Clune’s Fintech Empire

Over the past 30 years, Terry Clune has built a remarkable business empire, with CluneTech at the helm. The CEO and Founder has successfully created eight fintech firms, attracting renowned

The Role Of AI Within A Web Design Agency?

In the digital age, the role of Artificial Intelligence (AI) in web design is rapidly evolving, transitioning from a futuristic concept to practical tools used in design, coding, content writing

Generative AI Revolution

Is Generative AI the Next Internet?

The increasing demand for Generative AI models has led to a surge in its adoption across diverse sectors, with healthcare, automotive, and financial services being among the top beneficiaries. These

Microsoft Laptop

The New Surface Laptop Studio 2 Is Nuts

The Surface Laptop Studio 2 is a dynamic and robust all-in-one laptop designed for creators and professionals alike. It features a 14.4″ touchscreen and a cutting-edge design that is over

5G Innovations

GPU-Accelerated 5G in Japan

NTT DOCOMO, a global telecommunications giant, is set to break new ground in the industry as it prepares to launch a GPU-accelerated 5G network in Japan. This innovative approach will

AI Ethics

AI Journalism: Balancing Integrity and Innovation

An op-ed, produced using Microsoft’s Bing Chat AI software, recently appeared in the St. Louis Post-Dispatch, discussing the potential concerns surrounding the employment of artificial intelligence (AI) in journalism. These

Savings Extravaganza

Big Deal Days Extravaganza

The highly awaited Big Deal Days event for October 2023 is nearly here, scheduled for the 10th and 11th. Similar to the previous year, this autumn sale has already created

Cisco Splunk Deal

Cisco Splunk Deal Sparks Tech Acquisition Frenzy

Cisco’s recent massive purchase of Splunk, an AI-powered cybersecurity firm, for $28 billion signals a potential boost in tech deals after a year of subdued mergers and acquisitions in the

Iran Drone Expansion

Iran’s Jet-Propelled Drone Reshapes Power Balance

Iran has recently unveiled a jet-propelled variant of its Shahed series drone, marking a significant advancement in the nation’s drone technology. The new drone is poised to reshape the regional

Solar Geoengineering

Did the Overshoot Commission Shoot Down Geoengineering?

The Overshoot Commission has recently released a comprehensive report that discusses the controversial topic of Solar Geoengineering, also known as Solar Radiation Modification (SRM). The Commission’s primary objective is to

Remote Learning

Revolutionizing Remote Learning for Success

School districts are preparing to reveal a substantial technological upgrade designed to significantly improve remote learning experiences for both educators and students amid the ongoing pandemic. This major investment, which

Revolutionary SABERS Transforming

SABERS Batteries Transforming Industries

Scientists John Connell and Yi Lin from NASA’s Solid-state Architecture Batteries for Enhanced Rechargeability and Safety (SABERS) project are working on experimental solid-state battery packs that could dramatically change the

Build a Website

How Much Does It Cost to Build a Website?

Are you wondering how much it costs to build a website? The approximated cost is based on several factors, including which add-ons and platforms you choose. For example, a self-hosted

Battery Investments

Battery Startups Attract Billion-Dollar Investments

In recent times, battery startups have experienced a significant boost in investments, with three businesses obtaining over $1 billion in funding within the last month. French company Verkor amassed $2.1

Copilot Revolution

Microsoft Copilot: A Suit of AI Features

Microsoft’s latest offering, Microsoft Copilot, aims to revolutionize the way we interact with technology. By integrating various AI capabilities, this all-in-one tool provides users with an improved experience that not

AI Girlfriend Craze

AI Girlfriend Craze Threatens Relationships

The surge in virtual AI girlfriends’ popularity is playing a role in the escalating issue of loneliness among young males, and this could have serious repercussions for America’s future. A

AIOps Innovations

Senser is Changing AIOps

Senser, an AIOps platform based in Tel Aviv, has introduced its groundbreaking AI-powered observability solution to support developers and operations teams in promptly pinpointing the root causes of service disruptions

Bebop Charging Stations

Check Out The New Bebob Battery Charging Stations

Bebob has introduced new 4- and 8-channel battery charging stations primarily aimed at rental companies, providing a convenient solution for clients with a large quantity of batteries. These wall-mountable and

Malyasian Networks

Malaysia’s Dual 5G Network Growth

On Wednesday, Malaysia’s Prime Minister Anwar Ibrahim announced the country’s plan to implement a dual 5G network strategy. This move is designed to achieve a more equitable incorporation of both

Advanced Drones Race

Pentagon’s Bold Race for Advanced Drones

The Pentagon has recently unveiled its ambitious strategy to acquire thousands of sophisticated drones within the next two years. This decision comes in response to Russia’s rapid utilization of airborne

Important Updates

You Need to See the New Microsoft Updates

Microsoft has recently announced a series of new features and updates across their applications, including Outlook, Microsoft Teams, and SharePoint. These new developments are centered around improving user experience, streamlining

Price Wars

Inside Hyundai and Kia’s Price Wars

South Korean automakers Hyundai and Kia are cutting the prices on a number of their electric vehicles (EVs) in response to growing price competition within the South Korean market. Many