Olympus Docs
IntegrateBackends

Ruby on Rails integration

Authenticate via Olympus in a Rails backend

Use omniauth-oauth2 or directly the oauth2 gem.

Setup

Gemfile:

gem 'omniauth'
gem 'omniauth-oauth2'
gem 'jwt'

Middleware config

config/initializers/omniauth.rb:

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :oauth2, ENV['OLYMPUS_CLIENT_ID'], ENV['OLYMPUS_CLIENT_SECRET'],
    client_options: {
      site: ENV['OLYMPUS_ISSUER'],
      authorize_url: '/oauth2/auth',
      token_url: '/oauth2/token'
    },
    scope: 'openid profile email',
    pkce: true,
    name: 'olympus'
end

Callback controller

app/controllers/sessions_controller.rb:

class SessionsController < ApplicationController
  def create
    auth = request.env['omniauth.auth']
    # auth.credentials.token => access token
    # auth.info.email, etc.
    user = User.find_or_create_by(olympus_sub: auth.uid) do |u|
      u.email = auth.info.email
    end
    session[:user_id] = user.id
    redirect_to root_path
  end

  def destroy
    session.clear
    redirect_to ENV['OLYMPUS_LOGOUT_URL']
  end
end

config/routes.rb:

get '/auth/:provider/callback', to: 'sessions#create'
post '/logout', to: 'sessions#destroy'

Token introspection for APIs

If your Rails app also serves an API consumed by mobile / SPA clients:

class Api::BaseController < ActionController::API
  before_action :authenticate_token

  private

  def authenticate_token
    token = request.headers['Authorization']&.split(' ')&.last
    return render json: { error: 'unauthorized' }, status: 401 unless token

    introspect = HTTParty.post(
      "#{ENV['OLYMPUS_ISSUER']}/admin/oauth2/introspect",
      basic_auth: { username: ENV['HYDRA_ADMIN_USER'], password: ENV['HYDRA_ADMIN_PASS'] },
      body: { token: token }
    )

    if introspect['active']
      @current_user = User.find_by(olympus_sub: introspect['sub'])
    else
      render json: { error: 'inactive' }, status: 401
    end
  end
end

On this page