Skip to content

[OID4VCI] Fix c_nonce replay protection#50120

Open
forkimenjeckayang wants to merge 2 commits into
keycloak:mainfrom
adorsys:issue-48043
Open

[OID4VCI] Fix c_nonce replay protection#50120
forkimenjeckayang wants to merge 2 commits into
keycloak:mainfrom
adorsys:issue-48043

Conversation

@forkimenjeckayang

Copy link
Copy Markdown
Contributor

Fixes OID4VCI c_nonce replay protection by marking verified proof nonces as consumed after successful credential request processing.

The nonce is stored in SingleUseObjectProvider using a hashed key, with the cache lifetime calculated from the remaining nonce validity plus clock skew. This prevents a captured proof JWT from being replayed within the nonce validity window.

Details

  • Add CNonceHandler.consumeCNonce() for explicit nonce consumption.
  • Implement single-use storage in JwtCNonceHandler with putIfAbsent().
  • Calculate cache TTL as exp - now + clockSkew.
  • Consume each distinct proof nonce once at the credential request boundary.
  • Keep verifyCNonce() side-effect free so multi-proof and key-attestation flows can validate the same nonce during one request.
  • Remove eager attestation nonce replay handling that used an incorrect TTL.
  • Add regression coverage for single-use nonce consumption.

closes #48043

Signed-off-by: forkimenjeckayang <forkimenjeckayang@gmail.com>
@forkimenjeckayang forkimenjeckayang requested a review from a team as a code owner June 18, 2026 11:37
Copilot AI review requested due to automatic review settings June 18, 2026 11:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes OID4VCI c_nonce replay protection by introducing explicit nonce consumption (single-use enforcement) after successful credential issuance, preventing replay of captured proof JWTs within the nonce validity window.

Changes:

  • Adds CNonceHandler.consumeCNonce() and implements it in JwtCNonceHandler using SingleUseObjectProvider.putIfAbsent() with TTL derived from remaining nonce validity plus clock skew.
  • Consumes distinct proof nonces once at the credential request boundary in OID4VCIssuerEndpoint (while keeping verifyCNonce() side-effect free for multi-proof flows).
  • Removes prior (incorrect) attestation nonce replay handling and adds regression coverage for consumption semantics.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/base/src/test/java/org/keycloak/tests/oid4vc/NonceEndpointTest.java Adds a regression test for single-use nonce consumption behavior (provider-level).
services/src/main/java/org/keycloak/protocol/oid4vc/issuance/OID4VCIssuerEndpoint.java Consumes proof c_nonce values once per successful credential request to block replay.
services/src/main/java/org/keycloak/protocol/oid4vc/issuance/keybinding/JwtCNonceHandler.java Implements single-use consumption via SingleUseObjectProvider with hashed key and TTL.
services/src/main/java/org/keycloak/protocol/oid4vc/issuance/keybinding/CNonceHandler.java Introduces the consumeCNonce() API (default throws when unsupported).
services/src/main/java/org/keycloak/protocol/oid4vc/issuance/keybinding/AttestationProofValidator.java Removes earlier attestation-specific replay handling to centralize consumption at request boundary.

Comment thread tests/base/src/test/java/org/keycloak/tests/oid4vc/NonceEndpointTest.java Outdated
Signed-off-by: forkimenjeckayang <forkimenjeckayang@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[OID4VCI] c_nonce Replay

3 participants