Doorkeeper support for OpenID Connect Client Initiated Backchannel Authentication Flow
This library implements the OpenID Connect Client-Initiated Backchannel Authentication Flow - Core 1.0 for Rails applications on top of the Doorkeeper OAuth 2.0 framework and Doorkeeper::OpenidConnect extention.
This is a OpenSource implementation of CIBA specification.
The following parts of OpenID Connect Client-Initiated Backchannel Authentication Flow - Core 1.0 are planned to be supported for v1.0:
- Inside CIBA: BackChannel Endpoint and APIs for POLL, PING and PUSH mode, Notification Endpoint
- Inside CIBA: Authentication using "urn:openid:params:grant-type:ciba" grant_type for POLL mode
Affected endpoints:
-
New endpoints:
- POST /backchannel/authorize --> authentication requests w/ possible parameters, returning parameters auth_req_id, expires_in and interval, or error response
- GET /backchannel/authinfo --> get auth info to show in authorization device (eg. binding message, auth req id status)
- POST /backchannel/complete --> completes the flow updating the consent status of request id.
- POST /backchannel/clientconfig --> change the client (application) configuration to CIBA: notification type (POLL, PING or PUSH) and set the notification endpoint for PING or PUSH.
-
Changed endpoints:
- POST /oauth/token --> token requests w/ grant_type urn:openid:params:grant-type:ciba and auth_req_id, returning access_token, token_type, refresh_token, expires_in and id_token, or error response
-
New Active Record tables:
- backchannel_auth_requests - current status of an authorization request id
- backchannel_auth_consent_history - history of consent (approve / disapprove).
-
Changed Active Record tables:
- oauth_applications - new columns ciba_notify_type and ciba_notify_endpoint (configuration for notify type)
- oauth_access_tokens - new column ciba_auth_req_id (relation with ciba request id <-> oauth2/OIDC token/JWT).
ps. auth_req_id --> "authentication request ID" (transaction identifier) issued from the backchannel authentication endpoint.
POLL FLOW:
+-------------+ +-------------------------------------------------------------------------+ | Consumption | | doorkeeper-ciba | | Device | | +---------------------+ +---------------------------+ | | | | | Inside CIBA spec | (3) | Outside CIBA spec | | | | (1) POST | | +---------------+ | Notify pending | +----------------------+ | | | | -------------------> | BackChannel | | consent approval | | Authorization Device | | | | | <-[auth_req_id]-(2)- | Authorize | ---[Auth Result ID]--> |- OID Auth | | | | | | | | | (4) | |- Consent Approval | | | | | | | +---------------+ <-- [Get Auth Info] -- +----------------------+ | | | | | | ------ auth info ---> | | | | | | | +------------|--------------+ | | | | | | (5) | | | | | | | [Auth Result ID] | | | | | | | | | | | | --------------------------------V------------+ | | | (6) POST | | +---------------+ (7) +--------------------+ | | | | -[auth_req_id]-----> | CIBA Token | --[Auth Result ID]--> | Update BackChannel | | | | | <-Error or token--| | Request/Reply | <-------------------- | Request Id Status | | | | | | | +---------------+ +--------------------+ | | | | | +------------------------------------------------------------------+ | +-------------+ +-------------------------------------------------------------------------+ --> BackChannel Authorize - /backchannel/authorize --> OID Auth - /oauth/authorize --> Get Auth Info /backchannel/authinfo --> Consent Aproval (or disaproval) - /backchannel/complete --> CIBA Token Request/Reply - /oauth/token w/ grant_type = urn:openid:params:grant-type:ciba --> Notify pending consent approval - Consuption device solution dependent (eg. via e-mail, SMS, etc) --> 6 and 7 repeat until it expires or receive the consent response, limited by a minimum trial interval (parameters returned by backchannel-authorize). --> Authorization Device will use a sample web application (currently in development)
- Features that will be planned in near future:
- [Outside CIBA: Sample Web consent channel]: The CIBA specification doesn´t define how the consent channel should be implemented. The idea is to develop a sample web application, protected by Open Id/Oauth2, for the user give the consent. The application will be accessed through a link found in a e-mail notification, an email that will be sent by the backchannel authorization endpoint (asking for consent). After the user fills in their credentials and confirms/refute consent, the approval status of the pending CIBA flow will be changed to approved/disapproved. The notes found in spec follow bellow:
- Suport for signed request parameters
- Support for user codes.
- "Mutual TLS" support - ref. mtls,ciba auth req and ciba signed auth req - validation / adaptations (client_id)
- Maybe a queue for PING and PUSH notifications, with some resilience (RabbitMQ, Redis or even in database, with retry, etc), instead synchronous remote calls inside APIs calls.
- N/A
- Seeds entry sample for test:
appciba = Doorkeeper::Application.create!( name: 'CIBA', redirect_uri: 'https://localhost:3000/someapp', uid: 'CIBAUID', secret: 'CIBASECRET', scopes: 'openid ciba', ciba_notify_type: 'POLL', # PING OR PUSH # ASYNC NOTIFY ENDPOINT IS MANDATORY FOR PING OR PUSH ciba_notify_endpoint: 'https://localhost:3000/backchannel/testcibacallback' ) puts " Client: #{appciba.name} Client ID: #{appciba.uid} Client Secret: #{appciba.secret} Redirect URI: #{appciba.redirect_uri} Scopes: #{appciba.scopes} ciba_notify_type: #{appciba.ciba_notify_type} ciba_notify_endpoint: #{appciba.ciba_notify_endpoint}"
- Sample SOAPUI project can be found in Scripts/IDP-soapui-project.xml
Make sure your application is already set up with Doorkeeper and Doorkeeper::OpenidConnect.
Add this line to your application's Gemfile
and run bundle install
:
gem 'doorkeeper-ciba', git: https://github.com/autoseg/doorkeeper-ciba, branch: 'main'
ps. you can exec "bundle add doorkeeper-ciba --git https://github.com/autoseg/doorkeeper-ciba --branch 'main'" also.
Run the installation generator to update routes and create the initializer:
rails generate doorkeeper:openid_connect:ciba:install
Generate a migration for Active Record (other ORMs are currently not supported):
rails generate doorkeeper:openid_connect:ciba:migration
rake db:migrate
After the installation process, an initialization file with configurable options will be created in config/initializers/doorkeeper_openid_connect_ciba.rb, edit as recommended in the comments.
Doorkeeper::OpenidConnect::Ciba.configure do # Expiration time for the req_id_token. # default_req_id_expiration 600 # Max Expiration time for the req_id_token (default 1 day). # max_req_id_expiration 86400 # Default minimum wait interval for token execution in poll mode #default_poll_interval 5 # Max bind message size # option :max_bind_message_size, default: 128 # mandatory configuration with the logic to validate the login_hint filled in both backchannel authentication and backchannel complete # must return the id of the user as uuid #resolve_user_identity do |login_hint| # user = User.find_by(email: login_hint, email_verified: true) # user.id unless user.nil? #end # mandatory configuration with the logic to get the e-mail of the user based on auth req id #resolve_email_by_auth_req_id do |auth_req_id| # user = User.select('users.email').joins("inner join backchannel_auth_requests authreq on users.id = authreq.identified_user_id").where("authreq.auth_req_id" => auth_req_id) # user.first.email if user.count > 0 #end # mandatory config : add new permission to grant type ciba Doorkeeper.configuration.grant_flows.append("urn:openid:params:grant-type:ciba") end
The installation generator will update your config/routes.rb
to define all required routes:
Rails.application.routes.draw do
use_doorkeeper_openid_connect
use_doorkeeper_openid_connect_ciba
# your custom routes here
end
This will mount the following routes:
POST /backchannel/authorize
GET /backchannel/authinfo
POST /backchannel/complete
POST /backchannel/clientconfig
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/locales
.
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
Doorkeeper::OpenidConnect::Ciba is released under the MIT License.
Initial development of this project was sponsored by TODO.