Skip to content
Connect2id

Web session bootstrap for native apps

This guide describes how a native app that has obtained an ID token for a user can seamlessly bootstrap a web session with the Connect2id server.

Use cases:

  • To seamlessly sign-in the native app user into one or more web apps.

  • To create or refresh a Connect2id server web session for the native app user.

Assumes Connect2id server 15.0 or later.

1. Flow variants

This guide describes three different flows to bootstrap a web session at the Connect2id server in order to enable seamless sign-in to a web app.

1.1 Direct web session bootstrap with the Connect2id server

This is the recommended flow. It requires no changes to the web app clients and to the handling of the OpenID authentication requests by the Connect2id server. It also aligns with the future direction to switch from ID tokens to device secrets (from native SSO) for enhanced security.

  1. The native app exchanges the ID token for a web session bootstrap token.

  2. The native app posts the token to a web session endpoint on the identity provider domain. The web session endpoint validates the token, creates a new Connect2id server web session, and redirects the browser to a target URL of the web app.

  3. The web app makes an OpenID authentication request to sign-in the user. In the presence of an established web session with the Connect2id server the login prompt is skipped, resulting in a seamless sign-in experience.

1.2 Bootstrap via an OpenID authentication request

  1. The native app exchanges the ID token for a web session bootstrap token.

  2. The native app makes an OpenID authentication request to sign-in the user, passing the web session bootstrap token in an optional login_hint_token parameter. The Connect2id server validates the token and creates a new server web session for it, resulting in a seamless sign-in experience.

  3. Subsequent OpenID authentication requests from web apps that utilise the established Connect2id server web session will also result in a seamless sign-in experience.

1.3 Bootstrap via an OpenID authentication request initiated by the web app

  1. The native app exchanges the ID token for a web session bootstrap token.

  2. The native app opens a link to the target web app, passing the token in a agreed upon parameter, for example login_hint_token.

  3. The web app makes an OpenID authentication request to sign-in the user, passing the web session bootstrap token in an optional login_hint_token parameter. The Connect2id server validates the token and creates a new server web session for it, resulting in a seamless sign-in experience.

2. Native client

To allow a native client to obtain web session bootstrap tokens it must be registered with these capabilities:

  • The grant_types for the client must include urn:ietf:params:oauth:grant-type:token-exchange.

  • The scope for the client must include web_session_bootstrap.

Example registration request for a native client:

POST /clients HTTP/1.1
Content-Type: application/json

{
  "application_type"           : "native",
  "grant_types"                : [ "authorization_code",
                                   "refresh_token",
                                   "urn:ietf:params:oauth:grant-type:token-exchange" ],
  "redirect_uris"              : [ "com.example.app:///auth" ],
  "token_endpoint_auth_method" : "none",
  "code_challenge_method"      : "S256",
  "scope"                      : "openid email profile web_session_bootstrap"
}

The client registration guide has further examples.

3. ID token for web bootstrap token exchange

The native app obtains a web session bootstrap token by submitting an ID token for the signed-in user. It does it at the token endpoint of the Connect2id server, using a profile of the token exchange OAuth 2.0 grant (RFC 8693).

Token request:

  • grant_type – Must be urn:ietf:params:oauth:grant-type:token-exchange.
  • scope – Must be web_session_bootstrap.
  • subject_token – Must be an ID token for the signed-in native app user. Its exp (expiration) may be in the past.
  • subject_token_type – Must be urn:ietf:params:oauth:token-type:id_token.

Example:

POST /token HTTP/1.1
Host: demo.c2id.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange
&scope=web_session_bootstrap
&subject_token=eyJraWQiOiJDWHVwIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJjbGFpcmUiLC...
&subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Aid_token
&client_id=123

Token response:

  • access_token – The web session bootstrap token.
  • token_type – Set to Bearer.
  • issued_token_type – Set to urn:ietf:params:oauth:token-type:access_token.
  • expires_in – The token validity lifetime, in seconds.
  • scope – Set to web_session_bootstrap.

Example:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "access_token"      : "Ywjgiiy_8ERaV9D5DxhaBg.vWpARr3IzLLT_weUlltCPA",
  "token_type"        : "Bearer",
  "issued_token_type" : "urn:ietf:params:oauth:token-type:access_token",
  "expires_in"        : 120,
  "scope"             : "web_session_bootstrap"
}

Token exchange handling

The exchange is to be handled by a Connect2id server plugin for the token exchange OAuth 2.0 grant.

Token request validation:

  1. The ID token signature must be validated, using the public Connect2id server JWK set.
  2. The ID token iss (issuer) must be the configured Connect2id server issuer URL.
  3. The ID token aud (audience) must include the client_id value of the client that made the token request.
  4. The ID token exp (expiration) may be in the past, as this claim is used to indicate the time after which the token must not be accepted by the OpenID relying party for the user authentication. The exp claim is not related to the user session expiration at the Connect2id server. The handler should, however, require a reasonable freshness of the ID token (see next point).
  5. The ID token iat (issued-at time) should be reasonably recent and not older than the expiration time of refresh tokens issued to the native client.
  6. The requested scope must be web_session_bootstrap and it must be present in the registered client metadata.

Web session bootstrap token:

  1. Must be issued as an identifier-based (not JWT-encoded) access token, to enforce one-time use of the token at the introspection endpoint with the revoke=true option.
  2. The token subject must be the user identifier obtained from the ID token sub (subject). If the native app is registered for pairwise subjects, the ID token sub must be reversed (decrypted) to provide a correct web session bootstrap token sub.
  3. The token audience must be the Connect2id server issuer URL. If the token is going to be consumed in an OpenID authentication request, the client_id of the web app that is going to make the request should be added to the audience.
  4. The token scope must be web_session_bootstrap.
  5. The token lifetime should be sufficient to allow its use according to the intended flow.
  6. The token data object may be populated with the ID token auth_time, acr and other claims to configure the web session later.

Connect2id server deployments that choose to utilise the web-based handler (web-hook) to process requests for web session bootstrap tokens should set up the handler according to the above requirements.

Example configuration, to accept ID tokens and verify their digital signature prior to invoking the web-hook:

op.grantHandler.tokenExchange.webAPI.enable=true
op.grantHandler.tokenExchange.webAPI.url=[web-hook-url]
op.grantHandler.tokenExchange.webAPI.apiAccessToken=[web-hook-access-token]
op.grantHandler.tokenExchange.webAPI.subjectToken.types=urn:ietf:params:oauth:token-type:id_token
op.grantHandler.tokenExchange.webAPI.subjectToken.jwtVerification.1.jwkSetURI=[connect2id-server-jwk-set-url]
op.grantHandler.tokenExchange.webAPI.subjectToken.jwtVerification.mustPass=true

The handler must validate the ID token according to the token request validation steps 2 through 6 above.

To allow the issue of the web session bootstrap token the handler returns a response with the following parameters:

  • sub – The user identifier from the ID token.
  • issued_token_type – Must be urn:ietf:params:oauth:token-type:access_token.
  • scope – Must be ["web_session_bootstrap"].
  • access_token.lifetime – The web session bootstrap token validity, in seconds.
  • access_token.encoding – Must be IDENTIFIER.
  • access_token.audience – Must contain the Connect2id server issuer URL.
  • refresh_token.issue – Must be false.

To deny the issue the handler returns an error.

Example handler response:

{
  "sub"               : "164476e0-5c10-4cf0-bf75-b30fec2ba925",
  "issued_token_type" : "urn:ietf:params:oauth:token-type:access_token",
  "scope"             : [ "web_session_bootstrap" ],
  "access_token"      : { "lifetime" : 120,
                          "encoding" : "IDENTIFIER",
                          "audience" : [ "https://demo.c2id.com" ] },
  "refresh_token"     : { "issue" : false }
}

4. Web session bootstrap endpoint

The endpoint to create web sessions with bootstrap tokens must fulfil the following:

  1. Must be hosted on the same web domain as the authorisation endpoint (login page) of the Connect2id server.

  2. Must support token submission via HTTP GET and POST, per OAuth 2.0 Bearer Token Usage (RFC 6750).

  3. Must support a parameter, e.g. redirect_uri, where the browser is to be redirected if the web session bootstrap is successfully validated.

  4. Must validate the token, with replay prevention. This is done at the Connect2id server token introspection endpoint using the revoke=true option. If the token is invalid or expired, the endpoint must return a 401 Unauthorized error.

  5. If the token is valid, must first check whether a session cookie for a valid web session is not already present. If a web session is already present, the endpoint should not create a new web session, and proceed to redirect to the requested URL. If the sub (subject) of the present web session and the token are not identical, this must be logged as an error, and redirection must not take place.

  6. Create a new web session for the token sub (subject). If ID token auth_time, acr and other claims were passed via the token data they can be used to configure the new web session. Alternatively, the session may be given a special acr to clearly indicate that it was bootstrapped with a token.

  7. Use the SID (session ID) to set a new session cookie and redirect to the requested URL.

Example request to the web session bootstrap endpoint:

https://demo.c2id.com/web-session-bootstrap?
 access_token=Ywjgiiy_8ERaV9D5DxhaBg.vWpARr3IzLLT_weUlltCPA
 &redirect_uri=https%3A%2F%2Fweb-app.example.com%2Faccount%2FLB6P

Example success response with a redirection:

HTTP/1.1 302 Found
Location: https://web-app.example.com/account/LB6P
Set-Cookie: sid=WYqFXK7Q4HFnJv0hiT3Fgw.-oVkvSXgalUuMQDfEsh1lw; Domain=demo.c2id.com; Path=/; Secure; HttpOnly

5. OpenID authentication with a web session bootstrap token

A client in possession of a web session bootstrap token is able to make an OpenID authentication request where the login prompt for the user is bypassed.

Connect2id server configuration:

Example:

op.authz.requestParamsInAuthPrompt=client_id,login_hint_token

To accept bootstrap tokens the authorisation session handler must act as follows:

  1. On receiving an authentication prompt the handler must check if a token was passed in the request.login_hint_token parameter.

  2. The token must be validated, with replay prevention. This is done at the Connect2id server token introspection endpoint using the revoke=true option. The client_id of the OpenID authentication request (obtained from request.client_id) should be checked to be present in the token aud (audience). If the token is invalid or expired, the handler must present the regular login prompt to the user.

  3. Submit the token sub (subject) in response to the authentication prompt. If ID token auth_time, acr and other claims were passed via the token data they can be used to configure the new web session. Alternatively, the session may be given a special acr to clearly indicate that it was bootstrapped with a token.

6. Future directions

6.1 Switch to native SSO device secrets, with optional sender constraining

Connect2id is researching an alternative flow where the native app is provisioned with a device_secret that links to a device session managed by the identity provider. Device sessions and secrets were originally devised for the OpenID Connect native SSO.

Replacing the ID token with a device_secret in the token exchange is going to represent a significant security enhancement:

  • The device_secret and the web session bootstrap token can be sender-constrained, with DPoP or mTLS. The use of ID tokens in the token exchange offer no such possibility. This reduces the risk of unauthorised session creation in case of a token leak.
  • Closing, expiration or revocation of the device session immediately removes the ability of the native app to obtain web session bootstrap tokens. This can be further chained to automatically close any web sessions that were derived from it by means of bootstrap tokens.
  • Straightforward conversion from a device to a web session.

6.2 Built-in support

Given sufficient interest from customers on the enterprise plan Connect2id will consider providing a built-in token exchange profile for the web session bootstrap tokens and the endpoint for their consumption.

7. Credits

The flows described here are based on the following previous work:

  • OAuth 2.0 Bootstrap to Web Session (draft 02), by George Fletcher (2013-01-07).
  • Work on Connect2id server deployments.