[OID4VCI] Fix unbounded OID4VCI credential offer expiration#50957
[OID4VCI] Fix unbounded OID4VCI credential offer expiration#50957forkimenjeckayang wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Prevents unbounded OID4VCI credential offers and binds REST-created pre-authorized codes to their originating sessions.
Changes:
- Validates offer expiration and introduces long timestamps.
- Revokes codes after logout, user disablement, or password changes.
- Adds integration and SPI compatibility tests.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
CredentialOfferUriRequest.java |
Supports long expiration values. |
OID4VCredentialOfferPreAuthTest.java |
Tests expiration and session revocation. |
OID4VCBasicWallet.java |
Keeps originating sessions active during tests. |
PreAuthorizedCodeGrantTypeTest.java |
Tests lifespan validation. |
CredentialOfferProviderTest.java |
Tests SPI delegation. |
PreAuthorizedCodeGrantType.java |
Validates lifespan and originating session. |
VerifiableCredentialOfferAction.java |
Widens calculated expiration. |
OID4VCIssuerEndpoint.java |
Bounds expiration and records session metadata. |
DefaultCredentialOfferProvider.java |
Implements long expiration support. |
CredentialOfferState.java |
Stores creation and originating-session metadata. |
CredentialOfferProvider.java |
Adds a compatible long overload. |
a1cba9d to
96bfad7
Compare
96bfad7 to
b139949
Compare
088b02b to
78a69b5
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
services/src/main/java/org/keycloak/protocol/oid4vc/issuance/OID4VCIssuerEndpoint.java:571
- Legacy stateless access tokens decode to
UNKNOWN; bearer authentication then reconstructs a transient session for non-service-account users, but this check treats it as persistent and stores a request-scoped session ID that can never be resolved, so the resulting pre-authorized code always fails redemption. ForUNKNOWN, fall back to the reconstructed session's persistence state andCREATED_FROM_PERSISTENTnote before binding it.
AccessTokenContext.SessionType originatingSessionType = session
.getProvider(TokenContextEncoderProvider.class)
.getTokenContextFromTokenId(getAuthResult().token().getId())
.getSessionType();
boolean transientUserSession = originatingSessionType == AccessTokenContext.SessionType.TRANSIENT;
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.forms.BrowserFlowTest#testUserWithOneAdditionalFactorOtpSuccessorg.keycloak.testsuite.forms.MultipleTabsLoginTest#multipleTabsParallelLoginTestWithAuthSessionExpiredAndRequiredActionKeycloak CI - Forms IT (chrome) org.keycloak.testsuite.forms.MultipleTabsLoginTest#multipleTabsParallelLoginTestWithAuthSessionExpiredAndRegisterClickKeycloak CI - Forms IT (chrome) |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
services/src/main/java/org/keycloak/protocol/oid4vc/issuance/OID4VCIssuerEndpoint.java:571
- Legacy/unencoded token IDs produce
SessionType.UNKNOWN; when such a normal-user token has no session ID,UserSessionUtil.java:86-88reconstructs a transient request-scoped session. This check then binds that ephemeral ID, so the resulting offer can never be redeemed; include the actual session persistence state when handlingUNKNOWN.
boolean transientUserSession = originatingSessionType == AccessTokenContext.SessionType.TRANSIENT;
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.forms.BrowserFlowTest#testUserWithOneAdditionalFactorOtpSuccess |
Signed-off-by: forkimenjeckayang <forkimenjeckayang@gmail.com>
7cdccb8 to
48bbcfa
Compare
Signed-off-by: forkimenjeckayang <forkimenjeckayang@gmail.com>
Signed-off-by: forkimenjeckayang <forkimenjeckayang@gmail.com>
This change prevents
/create-credential-offerfrom creating credentialoffers and pre-authorized codes with an unbounded expiration.
It also binds REST-created pre-authorized offers to the session that
authorized their creation, allowing logout and password changes to revoke
outstanding pre-authorized codes.
Changes
expireparameter:longexpiration timestamps to avoid integer overflow.pre-authorized offers.
pre-authorized code is redeemed.
CredentialOfferProviderimplementations through the existing
Integer-based SPI method.closes #50520