Doorkeeper::OpenidConnect::Ciba
November 24, 2021 · View on GitHub
Doorkeeper::OpenidConnect::Ciba
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.
Table of Contents
Status
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.
Known Issues
- N/A
Example Applications
- 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
Installation
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
Configuration
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
Routes
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
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/locales.
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::Ciba is released under the MIT License.
Author
Sponsors
Initial development of this project was sponsored by TODO.