SamlCamel - (not production ready)

About

SamlCamel is a SAML gem/engine built off of the OneLogin ruby-saml gem. It is intended to provide Rails applications with capability to generate and consume SAML requests and responses. The gem is optimized to integrate with the Duke University Identity Provider, but can be used to integrate with other Identity Provider. Additional Information about integrating with the Duke IDP can be found here https://authentication.oit.duke.edu/manager/docs

Terminology within the context of the gem

  • Identity Provider (IDP): This is the system providing the authentication Service and provides user credentials.
  • Service Provider (SP): This is the system that sends authentication requests and consumes attributes from the response. SamlCamel is the SP in SAML integrations.
  • Entity ID: A unique identifier for your SP. It usually takes the form of a url but does not have to resolve. The entity id is not used for routing in any way, only for identification to the IDP. Example: https://my-site.com/does/not/resolve
  • Assertion Consumer Service (ACS): the endpoint of the SP where the IDP should send the response. The is part of the SamlCamel gem. Example: /saml/consumeSaml

Installation

Add this line to your application's Gemfile:

  gem 'saml_camel'

And then execute:

$ bundle

Usage

IMPORTANT: This step enables security features and is required to use the gem!

  1. in your environments config (config/development.rb for example) ensure that you have caching configured as follows

NOTE: use the cache_store most appropriate for your situation. It may make more sense to use a file store, or a redis server

  config.action_controller.perform_caching = true
  config.cache_store = :memory_store
  1. run rake saml_camel:generate_saml to generate metadata files for each environment. you can also specify a custom environment like this rake saml_camel:generate_saml environment=acceptance

Note: these steps will use development as an example, if you use separate metadata per environment, you will repeat each step for your chosen environment

  1. from the root of your app open saml/development/settings.json and specify an entity ID of your choice. this is a unique identifier used by the Identity Provider(idp) to recognize your app. Typically it should take the form of a url, however note that it is just an identifier and does not have to resolve (e.g. https://my-app-name/not/a/real/route)

  2. Go to https://authentication.oit.duke.edu/manager/register/sp and register your metadata with the identity provider. You will need the values from saml/development/settings.json in addition to the saml/development/saml_certificate.crt

  • copy the entity_id you chose in the settings.json file and paste it into the "Entity Field"
  • fill out functional purpose, responsible dept, function owner dept, and audience with information relevant to your application
  • copy the cert from saml/development/saml_certificate.crt and paste it into the Certificate Field
  • copy the acs value and paste it into the Location field in the Assertion Consumer Service box
    • note that the default host value for ACS is http://locahost:3000 which is the default rails s host. If you're using a different host (such as in production or using docker) you will want to replace the host value with what is relevent for your situation(e.g. https://my-app.duke.edu/saml/consumeSaml), but keep the path /saml/consumeSaml
  1. In your app mount the engine in config/routes.rb

    mount SamlCamel::Engine, at: "/saml"
    
  2. now simply provide the saml_protect method in your controllers (via before_action) to protect paths

    class DashboardController < ApplicationController
    before_action :saml_protect, except: [:home]
    
    def home
    end
    
    def index
    end
    end
    
  3. to logout simply make a post to localhost:3000/saml/logout. This will kill the local saml session, and the session with the identity provider.

  4. response attributes found in session[:saml_attributes] note that the session can not store over the 4 kilobyte limit. Keep this in mind in the use case of requesting a significant amount of attributes

  5. It is recommended to set config.force_ssl = true in the config/environments/production.rb file for security

  6. Logging is turned on by default. Logging is configured in saml/development/settings.json. To utilize logging saml_logging should be set to true (default), and primary_id must have a value. primary_id is the saml attribute you consider to be a primary identifier for a user

  7. Users can go to http://localhost:3000/saml/attributes to view attributes being passed through

Example settings.json

{
  "_comment": "note you will need to restart the application when you make changes to this file",
  "settings": {
    "acs": "http://localhost:3000/saml/consumeSaml",
    "entity_id": "https://samlCamel.com/doesNotResolve",
    "sso_url": "https://shib.oit.duke.edu/idp/profile/SAML2/Redirect/SSO",
    "logout_return_url": "http://localhost:3000",
    "primary_id": "eduPersonPrincipalName",
    "sp_session_timeout": 1,
    "sp_session_lifetime": 8,
    "saml_logging": true
  },
  "attribute_map": {
    "urn:oid:1.3.6.1.4.1.5923.1.1.1.9": "eduPersonScopedAffiliation",
    "urn:oid:1.3.6.1.4.1.5923.1.1.1.6": "eduPersonPrincipalName",
    "urn:oid:2.5.4.3": "cn",
    "urn:oid:0.9.2342.19200300.100.1.1": "uid",
    "urn:oid:0.9.2342.19200300.100.1.3": "mail",
    "urn:oid:1.3.6.1.4.1.5923.1.1.1.5": "eduPersonPrimaryAffiliation",
    "urn:oid:2.16.840.1.113730.3.1.241": "displayName",
    "urn:mace:duke.edu:idms:unique-id": "duDukeID",
    "urn:mace:duke.edu:idms:dku-id": "dku-id",
    "urn:oid:1.3.6.1.4.1.5923.1.5.1.1": "isMemberOf",
    "urn:oid:2.5.4.42": "givenName",
    "urn:oid:2.5.4.4": "sn",
    "urn:oid:2.5.4.11": "ou",
    "urn:oid:1.3.6.1.4.1.5923.1.1.1.1": "eduPersonAffiliation",
    "urn:oid:2.5.4.20": "telephoneNumber",
    "urn:oid:2.5.4.12": "title",
    "urn:mace:duke.edu:idms:middle-name1": "duMiddleName1",
    "urn:mace:duke.edu:idms:proxy-token": "duProxyToken"
  }
}

License

The gem is available as open source under the terms of the MIT License.