Devise and SAML Authentication with Ruby On Rails(Line Works)

                    Authenticating and Authorization(Line Works)

![Screen Shot 2018-02-07 at 23.22.32.png](https://qiita-image-store.s3.amazonaws.com/0/117479/c63bccb0-594f-88cd-1b43-1849f57e9fa3.png)

■日本語の記事↓
[Ruby on RailsでDevise・SAML認証（LINE WORKS)](https://qiita.com/tokotan/items/9340b70df064b8edc90c)

**■What is SAML?**
Security Assertion Markup Language (SAML) is an XML-based framework for authentication and authorization between two entities: a Service Provider and an Identity Provider. The Service Provider agrees to trust the Identity Provider to authenticate users. In return, the Identity provider generates an authentication assertion, which indicates that a user has been authenticated.

SAML is a standard single sign-on (SSO) format. Authentication information is exchanged through digitally signed XML documents. It's a complex single sign-on (SSO) implementation that enables seamless authentication, mostly between businesses and enterprises.
With SAML, you don't have to worry about typing in authentication credentials or remembering and resetting passwords.

**■What are the Benefits of SAML Authentication?**
There are following benefits of SAML authentication.
**● Standardization:** SAML is a standard format that allows seamless interoperability between systems, independent of implementation. It takes away the common problems associated with vendor and platform-specific architecture and implementation.
**● Improved User Experience:** Users can access multiple service providers by signing in just once, without additional authentication, allowing for a faster and better experience at each service provider. This eliminates password issues such as reset and recovery.
**● Increased Security:** Security is a key aspect of software development, and when it comes to enterprise applications, it is extremely important. SAML provides a single point of authentication, which happens at a secure identity provider. Then, SAML transfers the identity to service providers. This form of authentication ensures that credentials don't leave the firewall boundary.
**● Loose Coupling of Directories:** SAML doesn't require user information to be maintained and synchronized between directories.
**● Reduced Costs for Service Providers:** With SAML, you don't have to maintain account information accross multiple services. The identity provider bears this burden.

**■Why Organizations Use SAML?**
As organizations of all kinds move their infrastructure, services and data to the cloud, SAML provides a secure method of authenticating and authorizing users across an expanding universe of platforms, digital touchpoints and devices. SAML enables more robustly-connected systems by enabling easier access to Web applications for consumers.

SAML eliminates the need for multiple Web application passwords by enabling a token-based authentication exchange that takes place inside the IdP firewall between the IdP (who holds the user credentials) and the SP(Service Provider). During an “SP-initiated” SAML transaction, when a user requests access to an application, the SP automatically redirects them to the IdP, where the user is authenticated without ever passing personal information to the SP’s system.

SAML solves a key challenge by enabling single sign-on (SSO) functionality: allowing users to register or log in and be authorized across multiple properties with a single set of credentials for a set period of time. SAML also enables single logout functionality, ensuring that when users sign out of one site, they are automatically logged out of all other service providers owned by that company.

**■How does SAML Authentication Work?**
SAML SSO 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.

Let’s say: A user is logged into a system that acts as an identity provider. The user wants to log in to a remote application, such as a Smart-Flow application (the service provider). The following happens:
●  		The user accesses the Smart Flow application(https://smartflow.vebuin.com).
●  		The application identifies the user’s origin (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.
●  		The user either has an existing active browser session with the identity provider or establishes one by logging into the identity provider.
●  		The identity provider builds the authentication response in the form of an XML-document containing the user’s username or email address.
●  		The service provider, which already knows 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 and the user is provided with app access.

**■SAML SSO Flow**
![saml_transaction.gif](https://qiita-image-store.s3.amazonaws.com/0/117479/02ba9fed-6d84-f57f-f2a7-a3b49cf34bd1.gif)


**■SAML vs OAuth:**
OAuth is a somewhat newer standard than SAML, developed jointly by Google and Twitter beginning in 2006. It was developed in part to compensate for SAML's deficiencies on mobile platforms and is based on JSON rather than XML.

Other than SAML's less-than-stellar mobile support, what's the difference between the two? As we've seen, the SAML standard defines how providers can offer both authentication and authorization services. OAuth, on the other hand, only deals with authorization.

**■What do you need?**
To enable SAML functionality in your Rails apps, you need an Identity Provider. Currently i have Line works and okta.
here is the example of Line Works.
If you don’t have Line Works account, then you can do at Okta as well.
`https://www.okta.com/`
`http://blog.cloud66.com/adding-sso-to-your-rails-application-with-saml/`

I am assuming that you are familiar with Devise gem and also implemented in your app.
If you don’t implement yet, then please go through the below link.
`https://qiita.com/alokrawat050/items/5267e6ab0e274ad1188a`
`https://medium.com/@alokrawat050/devise-gem-tutorial-authenticate-a-user-by-user-id-and-email-ruby-on-rails-e25ae60ca437`


**■Let’s get started the SAML configurations**
First, we are going to make Devise work with SAML.
**1)** Add the devise same authenticate gem to your Gemfile  

```rb
gem 'devise_saml_authenticatable'
```

`refer https://github.com/apokalipto/devise_saml_authenticatable`

**2)** Add :saml_authenticatable to your user model user.rb(here model name is user.rb) :

```rb
class User < ApplicationRecord
  devise :saml_authenticatable, :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :authentication_keys => [:login]

  attr_accessor :login

  def login=(login)
    @login = login
  end

  def login
    @login || self.user_id || self.email
  end

  def self.find_for_database_authentication(warden_conditions)
    conditions = warden_conditions.dup
    if login = conditions.delete(:login)
      where(conditions.to_h).where(["user_id = :value OR email = :value", { :value => login.downcase }]).first
    else
      where(conditions.to_h).first
    end
  end

  def send_devise_notification(notification, *args)
    devise_mailer.send(notification, self, *args).deliver_later
  end
end
```

here I am using attr_accessor :login, why?
because user can login by user_id and as well as email. But if you don’t need then please ignore. You do not need to set in your application.

**3)** Add the following to your config/initializers/devise.rb file:

```rb
Devise.setup do |config|
……
……

Devise.setup do |config|  
      config.saml_create_user = false
      config.saml_update_user = true
      config.saml_default_user_key = :email
      config.saml_session_index_key = :session_index
      config.saml_use_subject = true
      config.idp_settings_adapter = nil
      config.saml_configure do |settings|
        settings.assertion_consumer_service_url     = "<your url>/users/saml/auth"
      settings.protocol_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
      settings.name_identifier_format             = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
      settings.issuer                             = "<your url>/users/saml/metadata"
      settings.authn_context                      = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
      settings.idp_slo_target_url                 = ""
      
      #line configuration
      settings.idp_sso_target_url                 = "<your SSO auth url>"
      settings.idp_cert_fingerprint               = '<your fingerprint of the certificate>'
      settings.idp_cert_fingerprint_algorithm     = 'http://www.w3.org/2000/09/xmldsig#sha256'
      end
    end
end
```

here you need to change the following settings:

`<your url>: http://localhost:3000`  #for development it’s a localhost, but you can set according to your development environment.`

`<your SSO auth url>`: #check the step no 4.2

`<your fingerprint of the certificate>` how you will generate the fingerprint, check the step no 8.

and in your **routes.rb** file,

```rb
Rails.application.routes.draw do
  root 'home#index'  
  devise_for :users, skip: :saml_authenticatable, controllers: {
    registrations: "user/registrations",
    sessions: "user/sessions",
    passwords: "user/passwords"
  }
  
  # opt-in saml_authenticatable
  devise_scope :user do
    scope "users", controller: 'saml_sessions' do
      get :new, path: "saml/sign_in", as: :new_user_sso_session
      post :create, path: "saml/auth", as: :user_sso_session
      get :destroy, path: "sign_out", as: :destroy_user_sso_session
      get :metadata, path: "saml/metadata", as: :metadata_user_sso_session
      match :idp_sign_out, path: "saml/idp_sign_out", via: [:get, :post]
    end
  end
end
```

**4)** you should have an account in Line Works.
https://developers.worksmobile.com/
click on Developer Console. Below is the setup guidelines.

**4.1** After successfully logged-in at Line Works Developer Console, go to Apps/SAML Apps.
![1.png](https://qiita-image-store.s3.amazonaws.com/0/117479/f6f07468-b9d7-e824-b398-5c35d8e2a193.png)

**4.2** now create your app, click on the add button and set the following fields and press next button.

**in the Application Info section,**

```
・Application Name: 
・Description: 
```

**in the Service Provider Info section,**

```
・ACS URL: http://localhost:3000/users/saml/auth
・SP issuer(Entity Id): http://localhost:3000/users/saml/metadata
```
![2.png](https://qiita-image-store.s3.amazonaws.com/0/117479/1eac6ccb-b70d-c516-527c-0bc74df6c8fb.png)

**4.3 now activate your application. Click on Adjust button and then select activate.**

- 1
![3.png](https://qiita-image-store.s3.amazonaws.com/0/117479/ec9d022f-7899-e20b-8cfc-76d6809ed289.png)

- 2
![4.png](https://qiita-image-store.s3.amazonaws.com/0/117479/5d186e93-8438-616d-3886-609247c17ea8.png)

- 3
![5.png](https://qiita-image-store.s3.amazonaws.com/0/117479/bebb1975-1cdb-682c-c008-7370cbfc845f.png)


**5)** if you are running your app in a development environment for ex, http://localhost:3000(here I used 3000 as the default Rails port, adjust according to your setup).
For production, make sure you use https and have it setup on your app and server.

**6)** Copy your SSO URL(Identity Provider Single Sign-On URL)  and paste its value as_ **idp_sso_target_url** _in **devise.rb**.

**7)** Now click on the Download Certificate button and save the certificate file.
![6.png](https://qiita-image-store.s3.amazonaws.com/0/117479/521610ca-39fe-b5b8-645f-df3054d9dd4e.png)


**8)** Run the following command to get the fingerprint of the certificate:

```
openssl x509 -text -noout -in ~/Downloads/<your file name> -fingerprint -sha256
```

`This assumes that you saved the certificate in ~/Downloads/<your file name>`
Copy the last line of the output,
SHA256 Fingerprint= . Copy the value for that and paste in idp_cert_fingerprint of your devise.rb file. 

It looks like this:

`59:10:LO:D0:9L:31:PO:AM:59:10:LO:D0:9L:31:PO:AM:59:10:LO:D0:9L:31:PO:AM:59:10:LO:D0:9L:31:PO:AM`

**9)** In your apps config directory, create a file called attribute-map.yml and put the following in there:

```yaml
    "urn:mace:dir:attribute-def:uid": “login”
    "urn:mace:dir:attribute-def:email": "email"
```

This tells Devise SAML what attributes returned from Id Provider map to which attribute of your User model.

**10)**. Now you are ready to test, use **/users/saml/sign_in** which will redirect to Line Works login page and then back to your app after authentication.

That’s it! 👏👏👏👏

thank you for taking your precious time to read.

Enjoy coding.:grinning: :grinning:

**Thanks & Best Regards,
Alok Rawat**