Rails engine for OpenID Connect Session Management
Assumes the use of OmniAuth and the omniauth-openid-connect
strategy.
If not present yet add the following gem:
gem 'omniauth-openid-connect', git: 'https://github.com/jjbohn/omniauth-openid-connect.git', branch: 'master'
You have to do 5 steps to enable session management in your application:
- Mount the engine.
- Configure lobby_boy.
- Render lobby_boy's iframes partial in your layout.
- Call lobby_boy's
SessionHelper#confirm_login!
when the user is logged in. - Call lobby_boy's
SessionHelper#logout_at_op!
when the user logs out. - (optional) Implement the end_session_endpoint to be used by lobby_boys Javascript.
The following sections will describe those steps in more detail.
To mount the engine into your application add the following to your config/routes.rb
:
require 'lobby_boy'
Rails.application.routes.draw do
mount LobbyBoy::Engine, at: '/'
end
The are two sections to be configured:
client
This refers to your application which is an OpenID Connect client.
All lobby_boy needs to know about it is its host
and end_session_endpoint
(i.e. logout URL).
For instance:
LobbyBoy.configure_client! host: "https://myapp.com",
end_session_endpoint: '/logout'
provider
The OpenIDConnect provider has to support Session Management too. The essential details
required for the provider are its name
(its strategy being available under /auth/$name
)
and the identifier
under which your client is registered at the provider.
If the provider supports discovery this is everything. If not you will also have to configure
the issuer
, end_session_endpoint
and check_session_iframe
.
For instance for Concierge which does not support discovery yet:
LobbyBoy.configure_provider! name: 'concierge',
client_id: 'openproject',
issuer: 'https://concierge.openproject.com',
end_session_endpoint: '/session/end',
check_session_iframe: '/session/check']
Session Management requires two iframes, the relying party iframe and the OpenIDConnect provider iframe,
to be rendered at all times, on every page.
In a standard rails application you would do this by inserting the following line into
app/views/layouts/application.html.erb
:
<%= render 'lobby_boy/iframes' %>
The #confirm_login!
helper stores the logged-in user's ID token in the session
and sets the oidc_rp_state
cookie. Which means that this helper has to be called
in the context of the final action handling the user's login.
Another thing the login must do is to redirect the user to the omniauth origin. It should do that already if implemented correctly.
For instance:
class SessionController < ApplicationController
include LobbyBoy::SessionHelper
def login
# existing logic:
# ...
confirm_login!
redirect_to(request.env['omniauth.origin'] || default_url)
end
end
When the user logs out of the application they should also be logged out of the
OpenID Connect provider. To do that call the #logout_at_op!
helper in your existing logout action.
The helper will redirect the user to the provider's logout endpoint to log them out globally.
You can pass a return URL to which the provider will send the user after the logout.
For instance:
class SessionController < ApplicationController
def logout
# The helper will return false and do nothing the provider's
# end_session_endpoint is not configured.
unless logout_at_op! root_url
redirect_to root_url
end
end
end
The Javascript of lobby_boy may logout the user via AJAX request when it realizes that the use has been logged out at the OpenID Connect provider. To reduce traffic you may want to implement a separate logout endpoint for this which only renders a small 'OK' response as opposed to a fully-fledged HTML page.
For instance:
class SessionController < ApplicationController
def ajax_logout
logout_user!
render text: 'logged out'
end
end