Forums/API

SAML toolkit for Ruby on Rails

Christian Pedersen
posted this on May 03 09:32

Security Assertion Markup Language (SAML) is a standard for logging users into applications based on their session in another context. This has significant advantages over logging in using a username/password: no need to type in credentials, no need to remember and renew password, no weak passwords etc.

Most companies already know the identity of users because they are logged into their Active Directory domain or intranet. It is natural to use this information to log users into other applications as well such as web-based application, and one of the more elegant ways of doing this by using SAML.

SAML is very powerful and flexible, but the specification can be quite a handful. Now OneLogin is releasing this SAML toolkit for Rails applications to enable you to integrate SAML in days instead of months. We’ve filtered the signal from the noise and come up with a simple setup that will work for most applications out there.

How SAML SSO works

SAML single sign-on works by transferring the user's identity from one place (the identity provider) to another (the service provider). This is done through an exchange of digitally signed XML documents. Consider the following scenario: A user is logged into a system, which acts as an identity provider. The user would like to log in to a remote application such as a support application or accounting application (i.e. the service provider). The following happens:

  1. The users clicks on the link to the application, either on the corporate intranet, a bookmark or similar and the application loads.
  2. The application identifies the user origin (either by application subdomain, user IP address or similar) and redirects the user back to the identity provider, asking for authentication. This is the authentication request.
  3. The user either has a session with the identity provider already, or established one by logging into the identity provider.
  4. The identity provider builds the authentication response in the form of a XML-document containing the user's username or email-address, signs it using a X.509 certificate and posts this information to the service provider.
  5. The service provider (which already knowns the identity provider and has a certificate fingerprint) retrieves the authentication response and validates it using the certificate fingerprint. The identity of the user is established.

How to implement SAML in your app

Download the toolkit from github.com/onelogin/ruby-saml. Also install the XMLCanonicalizer-1.0.1 gem.

The lib-folder contains the files you’ll copy into your Rails application. But first, have a look at the sample application in the folder samples. It’s a ready-to-run SAML relying party (or service provider). The saml_controller.rb file contains all the logic needed for authenticating using SAML:

require 'onelogin/saml'

class SamlController < ApplicationController
  skip_before_filter :verify_authenticity_token, :only => [:consume]  

  def index
    # insert identity provider discovery logic here
    settings = Account.get_saml_settings
    request = Onelogin::Saml::Authrequest.new
    redirect_to(request.create(settings))
  end

  def consume
    response = Onelogin::Saml::Response.new(params[:SAMLResponse])

    # insert identity provider discovery logic here
    response.settings = Account.get_saml_settings

    logger.info "NAMEID: #{response.name_id}"

    if response.is_valid?
      session[:userid] = response.name_id
      redirect_to :action => :complete
    else
      redirect_to :action => :fail
    end
  end
end

The index action initiates the SAML exchange. In order to know where to redirect the user with the authentication request, we need to establish the user's identity provider affinity. This depends on your application. Perhaps accounts have dedicated subdomain name (e.g. mycompany.accountingapp.com) or SAML-authentication for accounts is limited to certain IP-ranges. In those situations, you need to look up account information based on whatever information you already have about the user.

The consume action receives the SAML assertion. Again, you need to know the identity provider to which the user belongs, but now you get a clue, since the username or email address in the SAML assertion - use response.nameid to retrieve it. Next you’ll use this information to retrieve the identity provider information, and after that, you can verify that the SAML assertion is actually from the identity provider configured on the account.

What needs to be configured

In the example above, SAML settings are retrieved using the get_saml_settings method on the account object. This example is generic, and get_saml_settings doesn’t take any parameters. You’ll need to add your own information here (subdomain, ip_address) when fetching the account, and hence SAML settings.

The following information needs to be available on the account:

assertion_consumer_service_url
The URL at which the SAML assertion should be received. In this example "http://localhost:3000/saml/consume" would be correct.

issuer
The name of your application. Some identity providers might need this to establish the identity of the service provider requesting the login.

idp_sso_target_url
The URL to which the authentication request should be sent. This would be on the identity provider.

idp_cert_fingerprint
The certificate fingerprint, e.g. "90:CC:16:F0:8D:A6:D1:C6:BB:27:2D:BA:93:80:1A:1F:16:8E:4E:08". This is provided from the identity provider when setting up the relationship.

name_identifier_format
Describes the format of the username required by this application. If you need the email address, use "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress". See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf section 8.3 for other options. Note that the identity provider might not support all options.

Source code

The source code is open source and can be downloaded from http://github.com/onelogin/ruby-saml. The code also contains a sample application that you can use for testing. 

Testing

You can easily test your own application using the generic OneLogin SAML Test app, which you can add to your OneLogin account under Find Apps.