Home

Awesome

Doorkeeper::OpenidConnect

Build Status Code Climate Gem Version

:warning: This project is looking for maintainers, see this issue.

This library implements an OpenID Connect authentication provider for Rails applications on top of the Doorkeeper OAuth 2.0 framework.

OpenID Connect is a single-sign-on and identity layer with a growing list of server and client implementations. If you're looking for a client in Ruby check out omniauth_openid_connect.

Table of Contents

Status

The following parts of OpenID Connect Core 1.0 are currently supported:

In addition we also support most of OpenID Connect Discovery 1.0 for automatic configuration discovery.

Take a look at the DiscoveryController for more details on supported features.

Known Issues

Example Applications

Installation

Make sure your application is already set up with Doorkeeper.

Add this line to your application's Gemfile and run bundle install:

gem 'doorkeeper-openid_connect'

Run the installation generator to update routes and create the initializer:

rails generate doorkeeper:openid_connect:install

Generate a migration for Active Record (other ORMs are currently not supported):

rails generate doorkeeper:openid_connect:migration
rake db:migrate

If you're upgrading from an earlier version, check CHANGELOG.md for upgrade instructions.

Configuration

Make sure you've configured Doorkeeper before continuing.

Verify your settings in config/initializers/doorkeeper.rb:

The following settings are required in config/initializers/doorkeeper_openid_connect.rb:

The following settings are optional, but recommended for better client compatibility:

The following settings are optional:

Scopes

To perform authentication over OpenID Connect, an OAuth client needs to request the openid scope. This scope needs to be enabled using either optional_scopes in the global Doorkeeper configuration in config/initializers/doorkeeper.rb, or by adding it to any OAuth application's scope attribute.

Note that any application defining its own scopes won't inherit the scopes defined in the initializer, so you might have to update existing applications as well.

See Using Scopes in the Doorkeeper wiki for more information.

Claims

Claims can be defined in a claims block inside config/initializers/doorkeeper_openid_connect.rb:

Doorkeeper::OpenidConnect.configure do
  claims do
    claim :email do |resource_owner|
      resource_owner.email
    end

    claim :full_name do |resource_owner|
      "#{resource_owner.first_name} #{resource_owner.last_name}"
    end

    claim :preferred_username, scope: :openid do |resource_owner, scopes, access_token|
      # Pass the resource_owner's preferred_username if the application has
      # `profile` scope access. Otherwise, provide a more generic alternative.
      scopes.exists?(:profile) ? resource_owner.preferred_username : "summer-sun-9449"
    end

    claim :groups, response: [:id_token, :user_info] do |resource_owner|
      resource_owner.groups
    end
  end
end

Each claim block will be passed:

By default all custom claims are only returned from the UserInfo endpoint and not included in the ID token. You can optionally pass a response: keyword with one or both of the symbols :id_token or :user_info to specify where the claim should be returned.

You can also pass a scope: keyword argument on each claim to specify which OAuth scope should be required to access the claim. If you define any of the defined Standard Claims they will by default use their corresponding scopes (profile, email, address and phone), and any other claims will by default use the profile scope. Again, to use any of these scopes you need to enable them as described above.

Routes

The installation generator will update your config/routes.rb to define all required routes:

Rails.application.routes.draw do
  use_doorkeeper_openid_connect
  # your routes
end

This will mount the following routes:

GET   /oauth/userinfo
POST  /oauth/userinfo
GET   /oauth/discovery/keys
GET   /.well-known/openid-configuration
GET   /.well-known/webfinger

With the exception of the hard-coded /.well-known paths (see RFC 5785) you can customize routes in the same way as with Doorkeeper, please refer to this page on their wiki.

Nonces

To support clients who send nonces you have to tweak Doorkeeper's authorization view so the parameter is passed on.

If you don't already have custom templates, run this generator in your Rails application to add them:

rails generate doorkeeper:views

Then tweak the template as follows:

--- i/app/views/doorkeeper/authorizations/new.html.erb
+++ w/app/views/doorkeeper/authorizations/new.html.erb
@@ -26,6 +26,7 @@
       <%= hidden_field_tag :state, @pre_auth.state %>
       <%= hidden_field_tag :response_type, @pre_auth.response_type %>
       <%= hidden_field_tag :scope, @pre_auth.scope %>
+      <%= hidden_field_tag :nonce, @pre_auth.nonce %>
       <%= submit_tag t('doorkeeper.authorizations.buttons.authorize'), class: "btn btn-success btn-lg btn-block" %>
     <% end %>
     <%= form_tag oauth_authorization_path, method: :delete do %>
@@ -34,6 +35,7 @@
       <%= hidden_field_tag :state, @pre_auth.state %>
       <%= hidden_field_tag :response_type, @pre_auth.response_type %>
       <%= hidden_field_tag :scope, @pre_auth.scope %>
+      <%= hidden_field_tag :nonce, @pre_auth.nonce %>
       <%= submit_tag t('doorkeeper.authorizations.buttons.deny'), class: "btn btn-danger btn-lg btn-block" %>
     <% end %>
   </div>

Internationalization (I18n)

We use Rails locale files for error messages and scope descriptions, see config/locales/en.yml. You can override these by adding them to your own translations in config/locale.

Development

Run bundle install to setup all development dependencies.

To run all specs:

bundle exec rake spec

To generate and run migrations in the test application:

bundle exec rake migrate

To run the local engine server:

bundle exec rake server

By default, the latest Rails version is used. To use a specific version run:

rails=4.2.0 bundle update

License

Doorkeeper::OpenidConnect is released under the MIT License.

Sponsors

Initial development of this project was sponsored by PlayOn! Sports.