Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?

Integrating omniauth-jwt with Devise in a Rails application

Following the pattern set forth by the https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview#google-oauth2-example

Add the gem

Gemfile

gem 'omniauth-jwt' #Note this is the modified version at https://github.com/jbarona/omniauth-jwt/tree/flexible-options

Add the following to the devise initializer to set up the strategy

config/initializers/devise.rb

Devise.setup do |config|
  config.omniauth :jwt, "SHARED_SECRET", {
    auth_url: 'https://example.com/blablabla',
    required_claims: ['iss', 'jti', 'nbf', 'exp', 'typ', 'aud', 'sub'],
    params_key: 'assertion',
    info_map: {'email' => 'mail', 'name' => 'cn'},
    uid_claim: 'mail',
    valid_within: 60,

    user_claims_key: 'https://aaf.edu.au/attributes',
    required_user_claims: ['mail', 'cn']
  }
end

Create a callback endpoint in

app/controllers/users/omniauth_callbacks_controller.rb

# Skips the CSRF protection for the jwt action so that the session is retained
# and the user_return_to value can be used to redirect the user back to the
# page they originally requested after login.
protect_from_forgery :except => :jwt

def jwt
  raw_info = env['omniauth.auth'].extra.raw_info

  #further validation of claims adapted from https://rapid.test.aaf.edu.au/
  token_valid = (raw_info['iss'] == 'https://rapid.test.aaf.edu.au' &&
    raw_info['aud'] == 'https://example.com' &&
    Time.now > Time.at(raw_info['nbf']) &&
    Time.now < Time.at(raw_info['exp']) )

  if token_valid
    @user = User.find_for_jwt_oauth(env["omniauth.auth"]) # application specific logic
    if @user
      flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "jwt"
      sign_in_and_redirect @user, :event => :authentication
    else
      redirect_to user_session_path, :alert => 'Invalid admin user'
    end
  else
    redirect_to user_session_path, :alert => 'Bad token'
  end
end

Update the Devise routes

config/routes.rb

devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }

Add the strategy to your user model

app/models/user.rb

:omniauthable, :omniauth_providers => [:jwt]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment