Skip to content
This repository was archived by the owner on Feb 6, 2024. It is now read-only.

Auth Token Login

Nils Caspar edited this page Mar 4, 2015 · 7 revisions

The Auth Token Login mechanism introduced in CASino 4.0.0 allows you to log in any user without presenting a login dialog. This can be used to automatically login a user after a completed sign up in an application independent from CASino.

Auth Token

Auth Tokens are essentially base64-encoded JSON documents with the following structure:

{
  "authenticator": "my_company_ldap", # identifier of the authenticator the user normally uses (as in cas.yml)
  "username": "example",              # username 
  "ticket": "ATT-1234"                # unique one-time Auth Token Ticket (see below)
}

Auth Token Ticket

To ensure that an Auth Token can only be used once, a unique one-time Auth Token Ticket is used. An Auth Token Ticket can be acquired by accessing /api/auth_token_tickets using a POST request. The (JSON) response from the server will have the following structure:

{
  "ticket": "ATT-1234" # unique one-time Auth Token Ticket
}

Auth Token Signature

Auth Tokens have to be signed in order to be valid. CASino checks the signature of an Auth Token based on the RSA public keys stored as config/auth_token_signers/*.pem.

Login

To login a user with an Auth Token, the user has to be redirect to /authTokenLogin with the following parameters:

Parameter Description Required
at base64-encoded Auth Token Yes
ats base64-encoded Auth Token Signature Yes
service Service to redirect to after login No

If the login succeeds, the user is automatically redirect to the service with a valid Service Ticket. If you do not specify a service, the user is instead redirected to CASino's session overview.

If the login fails for whatever reason, the user is redirect to the normal login form.

Authenticator

All official authenticators support Auth Token Login. If you are using a custom authenticator, it has to present a load_user_data(username) method. The method should return the user data in the same format as the validate(username, password) method. If no matching user is found, nil must be returned.

Example Code

  1. Generate a private/public key pair:

    openssl genrsa -out private.pem 4096
    openssl rsa -in private.pem -pubout > public.pem
    
  2. Place the public.pem in the config/auth_token_signers/ directory of your Rails application. You can change the name if desired, just make sure to keep the file extension .pem.

  3. The following Ruby example code can now be used to generate an Auth Token with valid signature:

     require 'base64'
     require 'cgi'
     require 'json'
     require 'net/http'
    
     class AuthTokenLoginGenerator
       def initialize(options = {})
         @options = options
       end
    
       def login_url(authenticator, username, service)
         data = {
           ticket: acquire_auth_token_ticket,
           username: username,
           authenticator: authenticator
         }.to_json
         signature = sign(data)
         url_for(data, signature, service)
       end
    
       private
       def acquire_auth_token_ticket
         uri = URI(@options[:base_uri])
         port = if uri.port
                  uri.port
                elsif uri.scheme == 'https'
                  443
                else
                  80
                end
         http = Net::HTTP.new(uri.host, port)
         http.use_ssl = uri.scheme == 'https'
         request = Net::HTTP::Post.new('/api/auth_token_tickets')
         request.set_form_data({})
         JSON.parse(http.request(request).body)['ticket']
       end
    
       def sign(data)
         digest = OpenSSL::Digest::SHA256.new
         private_key.sign(digest, data)
       end
    
       def encode(value)
         Base64.strict_encode64(value)
       end
    
       def url_for(data, signature, service)
         "#{@options[:base_uri]}/authTokenLogin?ats=#{CGI.escape(encode(signature))}&at=#{CGI.escape(encode(data))}&service=#{CGI.escape(service)}"
       end
    
       def private_key
         @private_key ||= OpenSSL::PKey::RSA.new File.read(@options[:sign_key_path])
       end
     end
    
     atlg = AuthTokenLoginGenerator.new(base_uri: 'http://casinoapp.dev', sign_key_path: 'private.pem')
     redirect_url = atlg.login_url('my_company_ldap', 'example', 'http://www.google.com/')
     puts "Redirect to #{redirect_url}"

Clone this wiki locally