Ruby OpenID Connect example
This example illistrates how the openid_connect gem (https://github.com/nov/openid_connect) can be used to implement the OpenID connect Authorization Code Flow. Due to the wide variety of Ruby frameworks it has not been possible to provide detail at every step.
Goal in this example
Create a wrapper ruby module using the openid_connect gem which will...
- Generate an authentication request
- Process the recieved (authentication) token
codeto obtain the users OpenID claims
You will then be able to use this module within you choosen ruby web framework, e.g Rails or Sinatra (http://rubyonrails.org/, http://www.sinatrarb.com/)
Instructions
Install the required
gem(how you do this will depend on your ruby framework) e.gRUBYgem install openid_connectCreate the
modulefile e.goa_oidc_example.rbRUBYmodule OpenAthensOIDCExample class Worker # # * +provider_uri+ - For OpenAthens this will be <code>https://connect.openathens.net</code> # * +client_id+ - Obtain from the OpenAthens publisher dashboard # * +secret+ - Obtain from the OpenAthens publisher dashboard # * +redirect_uri+ - This is where the user will be returned to after successful authentication. # You will need to implement this on your server (e.g <code>https://oidc-rp.example/redirect</code>) # def initialize(provider_uri, client_id, secret, redirect_uri) @provider_uri = provider_uri @client_id = client_id @secret = secret @redirect_uri = redirect_uri end # # * +nonce+ - Unique value associated with the request. Same value needs to be passed to the #redirect method (store in users session) # Returns the authentication URL. Redirect users to authenticate. # def auth_uri(nonce) authz_url = init_client.authorization_uri( scope: [:profile, :email], state: nonce, nonce: nonce ) end # # * +code+ - The code returned from the OP after successful user authentication. # This will be available via the <code>querystring</code> when the user is return to <code>redirect_uri</code>. # * +nonce+ - The same value use to call #auth_uri (e.g read from the user session - <code>session.delete(:nonce)</code>) # # Returns the userinfo <code>OpenIDConnect::ResponseObject::UserInfo</code>. # Use <code>userinfo.raw_attributes</code> to access all the OpenId claims returned from the OpenAthens connect service. # def redirect (code, nonce) client = init_client #What we are expecting. expected = {:client_id => @client_id, :issuer => discover.issuer, :nonce => nonce} #Get code from query string. client.authorization_code = code access_token = client.access_token! #Validate the access token. id_token = OpenIDConnect::ResponseObject::IdToken.decode access_token.id_token, discover.jwks id_token.verify! expected #Read userinfo user_info = access_token.userinfo! end private def init_client @client ||= OpenIDConnect::Client.new( identifier:@client_id, secret: @secret, redirect_uri: @redirect_uri, authorization_endpoint: discover.authorization_endpoint, token_endpoint: discover.token_endpoint, userinfo_endpoint: discover.userinfo_endpoint ) end def discover @disco ||= OpenIDConnect::Discovery::Provider::Config.discover! @provider_uri end end end- Test your set up by implementing two handlers (pages) on your ruby server. E.g:
login- This will invoke theauth_urimethod and then redirect the user.redirect- This will invoke theredirectmethod. On success you will be able to access theOpenID claimsvia theraw_attributesmethod on the returned object.