DEV Community

yutianle
yutianle

Posted on

OIDC token hashes need a flow and an algorithm, not a generic equality check

OIDC token hashes need a flow and an algorithm, not a generic equality check

OpenID Connect binds tokens and authorization codes to an ID Token with hash claims. at_hash covers an access token in flows that return one from the authorization endpoint. c_hash covers an authorization code in hybrid flows. The claim is a base64url encoded, left-most half of a hash of the ASCII representation of the bound value. A verifier that treats the value as an arbitrary opaque string is not performing the check the specification describes.

The hash algorithm is tied to the JWS algorithm used to sign the ID Token. A verifier must first validate the signature and establish the key, then calculate the expected hash with the matching function. Do not accept an algorithm supplied only by the token's own header when that algorithm is outside the client's registered policy.

OpenID's Token Hash Algorithm Implementer's Guide adds a useful distinction for modern algorithms. EdDSA does not identify a single hash function by name. The implementation must determine the parameter set from the validated key, including the JWK crv value. The guide records SHA-512 for Ed25519 and SHAKE256 for the ML-DSA family, while noting that decisions for SLH-DSA remain open. A generic hash selector keyed only by alg will be wrong or incomplete.

Check the flow that produced the ID Token

An authorization response that includes an access token or authorization code is a different event from a token-endpoint response. In the relevant flows, c_hash and at_hash let the client detect substitution during the front-channel exchange. The claim is not a replacement for PKCE, state validation, nonce validation, issuer validation, or audience validation.

Read the claim in context. An optional claim that is present should be checked. A required claim that is missing should be a failure. A claim from a different flow should not be accepted just because its field name is familiar.

The comparison should be constant time and should use validated bytes, not a browser-normalized string. Handle padding and base64url exactly as specified. Reject a digest with the wrong length instead of comparing a prefix. Keep a test vector for each registered JWS algorithm the client accepts.

Operate the algorithm policy

Record the JWS algorithm, key type, hash function, and flow in logs. Do not record the code, access token, or ID Token. Alert when a provider begins issuing a key type that the client has not tested. During key rotation, validate the new key and its parameter set before enabling the algorithm for production.

Test a token with the right signature and wrong at_hash, a token with the right hash and wrong audience, and an EdDSA token whose key curve changes. These cases separate signature validation from claim binding. They also catch a client that accidentally validates only the happy path.

The hash claim is a small field with a narrow job. It ties one token value to one signed identity response in one flow. Implement that job precisely, and leave authorization to the claims and policies designed to carry it.

References

Top comments (0)