Access Management 7.3.2

Hybrid grant

The OpenID Connect hybrid grant is designed for clients that require flexibility when requesting ID, access, and refresh tokens.

Similar to the authorization code grant flow, the hybrid grant flow is a two-step process:

  1. The relying party makes a first request for tokens or codes. For example, a request for an ID token and an access code. AM returns them in the redirection fragment, as it does during the Implicit grant flow.

    The client relying party usually starts using these tokens immediately.

  2. Some time after the first request has happened, the relying party makes a second request for additional tokens. For example, a request for an access token using the access code, or a request for a refresh token.

Consider the following security tips when implementing this flow:

  • Requesting an access token during the first step exposes the token in the redirection fragment, just like during the implicit grant flow.

    Also, you must consider the security impact of cross-site scripting (XSS) attacks that could leak the ID and access tokens to other systems, and implement Cross-Origin Resource Sharing (CORS) to make OAuth 2.0/OpenID Connect requests to different domains.

    Due to the security implications, ForgeRock recommends not to request access tokens during the first step of this flow.

  • If the relying party is a public client, you can use the PKCE specification to mitigate against interception attacks performed by malicious users.

A common use case is the relying party requesting an ID token which can be used to, for example, pre-register the end user so they can start shopping. Only later and, if required, the relying party requests an access token to inquire the OpenID provider about additional claims. For example, during the check out, the relying party requests from AM the end user’s address details.

OpenID Connect Hybrid Flow
Figure 1. OpenID Connect Hybrid Flow
Hybrid flow explained
  1. The end user wants to use the services provided by the relying party. The relying party, usually a web-based service, requires an account to provide those services.

    The end user issues a request to the relying party to access their information, which is stored in an OpenID provider.

  2. To access the end user’s information in the provider, the relying party requires authorization from the end user. Therefore, the relying party redirects the end user’s user agent…​

  3. ... to the OpenID provider.

  4. The OpenID provider authenticates the end user, confirms resource access, and gathers consent if not previously saved.

  5. If the end user’s credentials are valid, the OpenID provider redirects the end user to the relying party.

  6. During the redirection process, the OpenID provider appends an authorization code and an ID token to the URL.

    Note that AM can return any combination of access token, ID token, and authorization code depending on the request. In this example, the access token is not requested at this time due to security concerns.

  7. The relying party stores the authorization code for future use. It also validates the ID token and gets the subject ID.

  8. With the ID token, the relying party starts providing services to the end user.

  9. Later, but always before the authorization code has expired, the relying party requests an access token from the OpenID provider so it can access more information about the end user.

    A use case would be the end user requiring services from the relying party that requires additional (usually more sensitive) information. For example, the end user requests the relying party to compare their electricity usage and supplier information against offers in the market.

    If required, the relying party could also request a refresh token.

  10. If the relying party credentials and the authorization code are valid, AM returns an access token.

  11. The relying party makes a request to AM’s /oauth2/userinfo endpoint with the access token to access the end user’s additional claims.

  12. If the access token is valid, the /oauth2/userinfo endpoint returns additional claims, if any.

  13. The relying party can now use the subject ID in the ID token and the additional claims as the end user’s identity to provide them with more services.

Get an authorization code and an ID token using a browser

Perform the steps in the following procedure to obtain an authorization code and an ID token, and later an access token:

This procedure assumes the following configuration:

  • AM is configured as an OAuth 2.0/OpenID provider. Ensure that:

    • The token, code, and id_token plugins are configured in the Response Type Plugins field.

    • The Authorization Code grant type is configured in the Grant Types field.

    For more information, refer to OpenID provider configuration.

  • A confidential client called myClient is registered in AM with the following configuration:

    • Client secret: forgerock

    • Scopes: openid profile

    • Response Types: code id_token token

    • Grant Types: Authorization Code

    • Token Endpoint Authentication Method: client_secret_post

      Confidential OpenID Connect clients can use several methods to authenticate. For more information, refer to OIDC client authentication.

For more information, refer to Dynamic client registration.

Perform the steps in the following procedure to obtain an ID token and an authorization code that will later be exchanged for an access token:

  1. The client redirects the end user’s user-agent to the authorization server’s authorization endpoint specifying, at least, the following form parameters:

    • client_id=your-client-id

    • response_type=code id_token

      As per the specification, you can request the following response types:

      • code id_token

      • code token

      • code id_token token

      Since AM returns the tokens in the redirection URL, requesting access tokens in this way poses a security risk.

    • redirect_uri=your-redirect-uri

    • scope=openid profile

    For information about the parameters supported by the /oauth2/authorize endpoint, refer to /oauth2/authorize.

    If the OAuth 2.0/OpenID provider is configured for a subrealm rather than the Top Level Realm, you must specify it in the endpoint. For example, if the OAuth 2.0/OpenID provider is configured for the /alpha realm, then use /oauth2/realms/root/realms/alpha/authorize.

    For example:

    https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/authorize \
    ?client_id=myClient \
    &response_type=code%20id_token \
    &scope=openid%20profile \
    &state=abc123 \
    &nonce=123abc \
    &redirect_uri=https://www.example.com:443/callback

    Note that the URL is split and spaces have been added for readability purposes. The state and nonce parameters have been included to protect against CSRF and replay attacks.

    Implement the PKCE specification to mitigate against interception attacks performed by malicious users.

    For more information about the required additional parameters and an example, refer to Authorization code grant with PKCE.

  2. The end user authenticates to AM, for example, using the credentials of the demo user.

    In this case, they log in using the default chain or tree configured for the realm.

    After logging in, AM presents its consent screen:

    The OpenID Connect AM user interface consent screen requesting access to the profile scope.
    Figure 2. OpenID Connect Consent Screen

    Note that requesting the profile scope translates into requesting access to several claims. For more information about the special profile scope, refer to Claims.

  3. The end user selects the Allow button to grant consent for the profile scope.

    AM redirects the end user to the URL specified in the redirect_uri parameter.

  4. Inspect the URL in the browser.

    It contains a code parameter with the authorization code and a id_token parameter with the ID token AM has issued. For example:

    https://www.example.com:443/callback#code=bOrAijEerd_YdNCUC1piL5VfNO4&id_token=eyJ0eXAiOiJKV1QiLCJra...7r8soMCk8A7QdQpg

    The client relying party can now use the ID token as the end user’s identity and store the access code for later use.

  5. The client exchanges the authorization code for an access token (and maybe, an refresh token).

    Perform the steps in one of the following procedures:

Get an authorization code and an ID token without using a browser

This procedure assumes the following configuration:

  • AM is configured as an OAuth 2.0/OpenID provider.

    For more information, refer to OpenID provider configuration.

  • A confidential client called myClient is registered in AM with the following configuration:

    • Client secret: forgerock

    • Scopes: openid profile

    • Response Types: code id_token token

    • Grant Types: Authorization Code

    • Token Endpoint Authentication Method: client_secret_post

      Confidential OpenID Connect clients can use several methods to authenticate. For more information, refer to OIDC client authentication.

For more information, refer to Dynamic client registration.

Perform the steps in the following procedure to obtain an ID token and an authorization code that will later be exchanged for an access token:

  1. The end user logs in to AM, for example, using the credentials of the demo user.

    For example:

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "X-OpenAM-Username: demo" \
    --header "X-OpenAM-Password: Ch4ng31t" \
    --header "Accept-API-Version: resource=2.0, protocol=1.0" \
    'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate'
    {
        "tokenId":"AQIC5wM…​TU3OQ*",
        "successUrl":"/openam/console",
        "realm":"/alpha"
    }
  2. The client makes a POST call to AM’s authorization endpoint, specifying the SSO token of the demo in a cookie and, at least, the following parameters:

    • client_id=your-client-id

    • response_type=code id_token

      As per the specification, you can request the following response types:

      • code id_token

      • code token

      • code id_token token

      Since AM returns the tokens in the redirection URL, requesting access tokens in this way poses a security risk.

    • redirect_uri=your-redirect-uri

    • scope=openid profile

    • decision=allow

    • csrf=demo-user-SSO-token

    For information about the parameters supported by the /oauth2/authorize endpoint, refer to /oauth2/authorize.

    If the OAuth 2.0/OpenID provider is configured for a subrealm rather than the Top Level Realm, you must specify it in the endpoint. For example, if the OAuth 2.0/OpenID provider is configured for the /alpha realm, then use /oauth2/realms/root/realms/alpha/authorize.

    For example:

    $ curl --dump-header - \
    --request POST \
    --Cookie "iPlanetDirectoryPro=AQIC5wM…​TU3OQ*" \
    --data "scope=openid profile" \
    --data "response_type=code id_token" \
    --data "client_id=myClient" \
    --data "csrf=AQIC5wM…​TU3OQ*" \
    --data "redirect_uri=https://www.example.com:443/callback" \
    --data "state=abc123" \
    --data "nonce=123abc" \
    --data "decision=allow" \
    "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/authorize"

    Note that the state and nonce parameters have been included to protect against CSRF and replay attacks.

    Implement the PKCE specification to mitigate against interception attacks performed by malicious users.

    For more information about the required additional parameters and an example, refer to Authorization code grant with PKCE.

    If AM is able to authenticate the user and the client, it returns an HTTP 302 response with the authorization code appended to the redirection URL:

    HTTP/1.1 302 Found
    Server: Apache-Coyote/1.1
    X-Frame-Options: SAMEORIGIN
    Pragma: no-cache
    Cache-Control: no-store
    Date: Mon, 30 Jul 2018 11:42:37 GMT
    Accept-Ranges: bytes
    Location: https://www.example.com:443/callback#code=bOrAijEerd_YdNCUC1piL5VfNO4&id_token=eyJ0eXAiOiJKV1QiLCJra…​7r8soMCk8A7QdQpg
    Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
    Content-Length: 0

    The client relying party can now use the ID token as the end user’s identity and store the access code for later use.

  3. The client exchanges the authorization code for an access token (and maybe, a refresh token).

    Perform the steps in one of the following procedures: