CIBA request handler SPI
1. Overview
For deployments that handle back-channel authorisation requests from clients the Connect2id server provides an interface to invoke the native IdP app where the user is authenticated and authorises the requests.
For CIBA requests that use a login_hint
, such as an email address or
telephone number to indicate the user identity, the Connect2id server provides
a resolver interface and a
webhook plugin.
Connect2id server introduced support for CIBA in v18.0.
2. Login hint resolver SPI
In order to process CIBA requests with a
login_hint
, the Connect2id server needs to resolve the supplied hint to a
valid subject (end-user) identifier. Commonly used login hints are email
addresses, telephone numbers and usernames.
Example login hints:
Plain | Structured |
---|---|
alice@example.com | email:alice@example.com |
+1 202-555-0173 | tel:+12025550173 |
alice | username:alice |
The Connect2id server comes with a plugin interface (SPI) to resolve login hints.
2.1 Available implementations
2.1.1 Web-based login hint resolver
This plugin calls a web service to determine the subject identifier for a
login_hint
.
The web service interface is simple – a single HTTP POST, using JSON to convey the request and response parameters.
Git repo | https://bitbucket.org/connect2id/grant-handlers |
---|
2.1.1.1 Configuration
The Connect2id server is shipped with a base configuration for the web-based
login hint resolver located in WEB-INF/loginHintResolverWebAPI.properties
. It
can be replaced or overridden with Java system properties.
Content of the shipped resolver configuration file, with explanation of the properties:
# Enables / disables the login hint resolver. Disabled (false) by default.
op.loginHintResolver.webAPI.enable=false
# The endpoint URL of the web API.
op.loginHintResolver.webAPI.url=
# Access token of type Bearer for the web API.
op.loginHintResolver.webAPI.apiAccessToken=
# The HTTP connect timeout, in milliseconds. The default value is zero, implies
# none or determined by the underlying HTTP client.
op.loginHintResolver.webAPI.connectTimeout=250
# The HTTP response read timeout, in milliseconds. The default value is zero,
# implies none or determined by the underlying HTTP client.
op.loginHintResolver.webAPI.readTimeout=500
To set up the resolver the following minimal configuration must be provided:
- Enabling the resolver.
- The URL of the web service.
- A long-lived bearer token to access the web service.
Example minimal configuration:
op.loginHintResolver.webAPI.enable=true
op.loginHintResolver.webAPI.url=https://idp.example.com/login-hint-resolver
op.loginHintResolver.webAPI.apiAccessToken=ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
To verify the resolver loading and configuration check the server
logs for lines with the OP6740
and LHRxxxx
identifiers.
Example logged configuration:
INFO MAIN [main] [OP6740] Loaded com.nimbusds.openid.connect.provider.spi.subjects.LoginHintResolver: class=com.nimbusds.openid.connect.provider.spi.impl.subjects.LoginHintResolverDelegator enabled=true
INFO MAIN [main] [LHR0001] Login hint resolver: Endpoint URL: http://localhost:45057
INFO MAIN [main] [LHR0002] Login hint resolver: HTTP connect timeout: 500 ms
INFO MAIN [main] [LHR0003] Login hint resolver: HTTP read timeout: 1000 ms
2.2 How to develop your own resolver
First, read our general guide for developing, annotating and packaging an SPI-based plugin.
The resolver must implement the LoginHintResolver SPI defined in the Connect2id server SDK:
Git repo | https://bitbucket.org/connect2id/server-sdk |
---|
If the resolver cannot determine a subject identifier for the login hint, it
throws a
LoginHintResolveException.
The exception message is logged internally and not
conveyed to the client.
If the Connect2id server detects an SPI implementation at startup it will log
its loading under OP6740
:
INFO MAIN [main] [OP6740] Loaded com.nimbusds.openid.connect.provider.spi.subjects.LoginHintResolver: class=com.nimbusds.openid.connect.provider.spi.impl.subjects.LoginHintResolverDelegator enabled=true
Note, the Connect2id server can load multiple login hint resolvers at startup, but only one may be enabled.
3. CIBA request handler SPI
When the subject (end-user) ID for a CIBA request is successfully resolved, the native IdP app of the user is invoked to authorise the request. Depending on the CIBA context and risk, the user may be required to re-authenticate as well.
The Connect2id server comes with a plugin interface (SPI) to trigger the necessary actions to locate the user’s IdP app instance(s) and prompt the user to authorise the request.
Features of the request handler SPI:
- Provides access to the CIBA request parameters,
such as
scope
andacr_values
. Additional parameters, such asauthorization_details
when RAR is used, are also included. - Provides the subject identifier resolved from the hint.
- Indicates the expiration time of the request.
- Supplies context, such as the client metadata and the type of hint used, which are needed to make security and risk decisions, and for the presentation of the authorisation prompt in the IdP app.
The Connect2id server performs the following processing prior to invoking the SPI:
- Authenticates the client and ensures it’s authorised to make CIBA requests.
- If the CIBA request is signed, validates the JWT and extracts the request parameters.
- Ensures the client is allowed to use the type of hint it submitted -
login_hint_token
,id_token_hint
orlogin_hint
. - Resolves the hint subject. For a
login_hint_token
also the linked native IdP app session. - Ensures the
binding_message
, if any, matches the configured legal pattern. - Ensures a
user_code
is submitted if required for the client.
3.1 Available implementations
Connect2id is working on a plugin that places the pre-processed CIBA requests into a queue which native IdP apps or an IdP backend service can poll at a web endpoint. IdP apps that have established a user session access the pending requests for the user by presenting their session ID.
3.2. How to develop your own handler
First, read our general guide for developing, annotating and packaging an SPI-based plugin.
The handler must implement the CIBARequestHandler SPI defined in the Connect2id server SDK:
Git repo | https://bitbucket.org/connect2id/server-sdk |
---|
If the Connect2id server detects an SPI implementation it will log its loading
under OP6750
.
INFO main MAIN - [OP6750] Loaded com.nimbusds.openid.connect.provider.spi.xdevice.CIBARequestHandler: class=com.example.ciba.RequestDispatcher enabled=true
Note, the Connect2id server can load multiple CIBA request handlers at startup, but only one may be enabled.
4. CIBA sessions web API
Successful CIBA authorisations are posted to a Connect2id server endpoint to continue the CIBA flow. The submission requires the callback token obtained via the CIBA request handler SPI and typically references the session ID of the native IdP app where the user is authenticated and authorised the CIBA request.
If the CIBA request is not authorised, for example because the user denied the request, the request is simply left to expire.
4.1 Web API overview
Resources | |
---|---|
Representations | Errors |
4.2 Resources
4.2.1 /ciba-sessions/rest/v1/authorize
4.2.1.1 POST
Submits a CIBA authorisation to the Connect2id server.
Header parameters:
-
Authorization Must specify the callback token provided by the CIBA request handler SPI.
-
Content-Type Must be
application/json
. -
[ Issuer ] The issuer URL when issuer aliases are configured, or the issuer URL for a tenant (in the multi-tenant Connect2id server edition). The tenant can be alternatively specified by the Tenant-ID header.
-
[ Tenant-ID ] The tenant ID (in the multi-tenant Connect2id server edition). The tenant can be alternatively specified by the Issuer header.
Body:
- A JSON object representation of a CIBA authorisation.
Success:
- Code:
204
Errors:
- 400 Bad Request
- 401 Unauthorized
- 460 Invalid Client ID
- 461 Invalid / Expired Subject Session ID
- 500 Internal Server Error
Example submission of a CIBA authorisation to issue an ID token to the client and let it access the user’s email address:
POST ciba/sessions/rest/v1/authorize HTTP/1.1
Host: c2id.com
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzYmgiOiJLOWdHeVg4T0FLOGFIOE15a...
Content-Type: application/json
{
"sub_sid" : "WYqFXK7Q4HFnJv0hiT3Fgw.-oVkvSXgalUuMQDfEsh1lw"
"scope" : [ "openid", "email" ],
"claims" : [ "email", "email_verified" ]
}
Example success response:
HTTP/1.1 204 No Content
Example error response for an invalid or expired callback token:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="invalid_token", error_description="Invalid access token"
Content-Type: application/json
{
"error" : "invalid_token",
"error_description" : "Unauthorized: Invalid Bearer access token"
}
4.3. Representations
4.3.1 CIBA authorisation
The authorisation must either specify the session ID (sub_sid
) of the native
IdP app where the CIBA request was confirmed, or the subject identifier
(sub
).
A scope
must be specified, unless the authorisation deals with
RAR.
If the authorisation specifies a session ID (sub_sid
) and an ID token is
issued, the Connect2id server will populate the auth_time
and acr
ID token
claims from the respective session values. To
override the session values, for instance if the user had to be
re-authenticated as part of the consent, set values in the CIBA authorisation.
If the authorisation specifies a subject (sub
) and an ID token is issued, the
auth_time
and acr
values should be supplied.
Refresh token issue and persistence of the authorisation are not supported at present.
JSON object members:
-
sub_sid {string} The subject session identifier (SID) of the native IdP app. Must not be used together with
sub
. -
sub {string} The subject (end-user). Must not be used together with
sub_sid
. -
[ scope ] {string array} The consented scope values. These may be a subset of the originally requested values, or include additional ones. The
openid
scope value must be included for a consented OpenID authentication request. May be omitted or empty, for example for a Rich Authorisation Request (RAR). -
[ auth_time ] {integer} Optional time of the subject authentication, as number of seconds since the Unix epoch.
-
[ acr ] {string} Optional Authentication Context Class Reference (ACR). Signifies the strength of the employed authentication methods.
-
[ amr ] {string array} Optional list of the Authentication Method References (AMR). Indicates the methods employed to authenticate the subject, such as password, OTP, biometrics, etc.
-
[ audience ] {string array} Optional parameter specifying the resource server audience for the issued access token. Should typically include the
client_id
(s) of the resource(s), but any other type of identifier, such as URI, is also accepted. Identifier-based tokens with a specified audience can be introspected only by resource servers whoseclient_id
is in the audience. -
[ claims ] {string array} Optional array of names of consented OpenID claims. These can be a subset of the originally requested claims, or include additional ones.
Special keywords and prefixes:
*
- An asterisk (“*“) in the string array indicates consent for all requested claims.id_token:
- For a non-requested claim, the “id_token:” prefix to its name will cause the claim to be delivered in the issued ID token instead of at the UserInfo endpoint (default location for all non-requested claims).access_token:
- For a non-requested claim, this prefix will cause the claim to be delivered in the issued access token. If the access token is self-contained (JWT) the claim will be added at the top-level. If the access token is identifier-based the claim will appear at the top-level in the token introspection response.access_token:uip:
- For a non-requested claim, this prefix will cause the claim to be merged into the top-level “uip” (optional preset UserInfo claims) JSON object claim of the access token.access_token:dat:
- For a non-requested claim, this prefix will cause the claim to be merged into the top-level “dat” (optional data) JSON object claim of the access token.verified:
- If Identity Assurance is enabled indicates a verified claim. Must be after any other prefixes. -
[ claims_data ] {object} Optional data to be passed in the request to retrieve the consented OpenID claims from the configured source(s). The claims data will be included in a “cld” (claims data) field in the issued access token(s) and in the long-lived authorisations if the consent is persisted. If the claims data must be kept confidential from the client either an identifier access token encoding must be chosen or if a self-contained (JWT) access token is chosen it must be additionally encrypted. An AdvancedClaimsSource SPI implementation can retrieve the claims data JSON object by a call to the
ClaimsSourceRequestContext.getClaimsData
method. -
[ preset_claims ] {object} Optional JSON object specifying additional preset OpenID claims to include in the ID token and / or the UserInfo response:
-
[ id_token ] {object} Preset claims to include in the ID token, omitted or empty JSON object if none.
-
[ userinfo ] {object} Preset claims to include in the UserInfo response, omitted or empty JSON object if none.
-
-
[ claims_locales ] {string array} The end-user’s preferred claims locales, by order of preference, omitted if not specified.
-
[ claims_transport = “USERINFO” ] {“USERINFO”|“ID_TOKEN”} The preferred OpenID claims transport, defaults to
USERINFO
. IfUSERINFO
the claims will be made available at the UserInfo endpoint by presenting the access token. IfID_TOKEN
the claims will be included in the ID token. -
[ access_token ] {object} Optional access token settings, overriding the default configuration:
-
[ lifetime = 0 ] {integer} The access token lifetime in seconds. If zero or omitted the default setting will apply.
-
[ encoding = “SELF_CONTAINED” ] {“SELF_CONTAINED”|“IDENTIFIER”} The access token encoding. If
SELF-CONTAINED
the token authorisation is encoded in the access token, as a signed and optionally encrypted JSON Web Token (JWT). IfIDENTIFIER
the issued access token is a secure random identifier; the underlying token authorisation can be retrieved at the introspection endpoint. Defaults toSELF_CONTAINED
. -
[ encrypt = false ] {true|false} Encryption of the self-contained (JWT) access token after signing, to make its payload confidential from the client. The token is encrypted with the current active AES key using the configured JWE algorithm and method. The resource server(s) must be provisioned with a copy of the AES key to decrypt the token. Defaults to
false
, unless the client is an OpenID relying party registered for pairwise subjects in which case the token will be encrypted. The encryption can be opted out from if the access token subject is set to pairwise. -
[ sub_type = “PUBLIC” ] {“PUBLIC”|“PAIRWISE”} The access token subject type. If
PAIRWISE
the access token with be issued with a pairwise subject identifier. This requires theaudience
to be set (if multiple audience values are set the first in the list will used to compute the pairwise identifier). Defaults toPUBLIC
.
-
-
[ id_token ] {object} Optional ID token settings, overriding the default configuration:
- [ lifetime = 0 ] {integer} The ID token lifetime in seconds. When zero or omitted the default setting will apply.
-
[ data ] {object} Optional additional information to be stored in the
dat
field of the authorisation record and included asdat
claim in access tokens.
Example CIBA authorisation for an ID token and OpenID claims, referencing the session ID of the native IdP app:
{
"sub_sid" : "WYqFXK7Q4HFnJv0hiT3Fgw.-oVkvSXgalUuMQDfEsh1lw"
"scope" : [ "openid", "email" ],
"claims" : [ "email", "email_verified" ]
}
Another example CIBA authorisation which supplies the subject identifier directly. Because a native IdP session isn’t referenced, the authentication time and ACR claims for the ID token are supplied here:
{
"sub" : "alice",
"scope" : [ "openid", "email" ],
"claims" : [ "email", "email_verified" ],
"auth_time" : 1744272392,
"acr" : "https://loa.c2id.com/high"
}
Example CIBA authorisation for a transaction confirmation:
{
"sub_sid" : "WYqFXK7Q4HFnJv0hiT3Fgw.-oVkvSXgalUuMQDfEsh1lw"
"scope" : [ "https://example.com/accounts/tx-confirmation?id=aTouWee6" ]
}
4.4. Errors
400 Bad Request
Invalid or malformed request.
Example:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error" : "invalid_request",
"error_description" : "Bad request: Invalid JSON"
}
401 Unauthorized
The request was denied due to an invalid, expired or missing callback token.
Example:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
Content-Type: application/json
{
"error" : "missing_token",
"error_description" : "Unauthorized: Missing Bearer access token"
}
460 Invalid Client ID
There is no existing client registration for the referred client_id
.
Example:
HTTP/1.1 460
Content-Type: application/json
{
"error" : "invalid_client_id",
"error_description" : "Invalid client ID"
}
461 Invalid / Expired Subject Session ID
There is no existing subject (end-user) session for the specified sub_sid
or
it has expired.
Example:
HTTP/1.1 461
Content-Type: application/json
{
"error" : "invalid_subject_session_id",
"error_description" : "Invalid / expired subject session ID"
}
500 Internal Server Error
An internal server error has occurred. Check the Connect2id server logs for details.
Example:
HTTP/1.1 500 Internal Server Error