Skip to content

Implement the code id_token / code id_token token hybrid flows (with the REQUIRED c_hash claim) #340

Description

@55728

Current behavior

The library registers exactly two OIDC response types — id_token and id_token token — plus the implicit_oidc alias grouping them with implicit (lib/doorkeeper/openid_connect.rb). An authorization request with response_type=code id_token (or code id_token token) is rejected by Doorkeeper as an unsupported response type before any code or token is issued. There is no conformance bug in shipped behavior today; the hybrid variants that include a code are simply not implemented.

Motivation

OpenID Connect Core §3.3 defines the Hybrid Flow with the response types code id_token, code token, and code id_token token. The two variants that include an ID Token are the relevant ones for this gem: the front-channel ID Token carries a c_hash claim binding it to the authorization code, letting the RP detect code substitution before it ever calls the token endpoint. With #335/#337 having consolidated the hybrid at_hash logic into HybridIdTokenConcern, this is the natural next extension point.

(code token contains no ID Token and is arguably out of scope for an OIDC extension; listed only for completeness.)

Spec requirements

Per §3.3.2.11, for ID Tokens issued from the authorization endpoint in the hybrid flow:

  • c_hash is REQUIRED whenever a code is issued alongside the ID Token (code id_token, code id_token token). It is computed like at_hash, but over the code value: hash using the algorithm implied by the ID Token's JOSE alg header, keep the left-most half, base64url-encode without padding.
  • at_hash is REQUIRED whenever an access token is issued alongside (code id_token token).
  • The ID Token later returned from the token endpoint for the code exchange follows the ordinary code-flow rules; the hash claims are not required there (§3.3.3.6).

Implementation sketch

  1. Register the flows — two new Doorkeeper::GrantFlow.register entries ("code id_token", "code id_token token") with fragment/form_post response modes, plus response strategies under Doorkeeper::Request that issue an authorization code and build the ID Token (and access token, for the triple).
  2. c_hash computation — parallel to at_hash. Either a sibling concern, or generalize HybridIdTokenConcern to emit at_hash / c_hash conditionally based on which artifacts are present. Note the coupling flagged in Strengthen user_info_class validation and check initializer arity #339: the digest must follow the ID Token's actual JOSE alg, which the concern currently reads from the global signing_algorithm.
  3. Nonce plumbing — the code half must persist the nonce through oauth_openid_requests (as the existing code flow does) so the token-endpoint ID Token can echo it, while the front-channel ID Token receives it directly.
  4. Discovery — advertise the new values in response_types_supported.
  5. Specs — examples for both response types covering c_hash / at_hash presence and the §3.3.2.11 computation, mirroring the existing HybridIdTokenConcern spec.

Response type matrix

response_type Registered today Authz-endpoint ID Token must include
id_token
id_token token at_hash
code id_token ❌ (this issue) c_hash
code id_token token ❌ (this issue) at_hash + c_hash

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions