-
Notifications
You must be signed in to change notification settings - Fork 8k
[OID4VCI] Credential Offer must be created by Issuer not Holder #44255
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
6e3bd96 to
d17afa3
Compare
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.LevelOfAssuranceFlowTest#essentialClaimNotReachedFailsKeycloak CI - Forms IT (chrome) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unreported flaky test detected, please review
77e3047 to
6d5fe4c
Compare
Captain-P-Goldfish
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not yet finished with the review but I do not have time anymore ^^°
services/src/main/java/org/keycloak/protocol/oid4vc/issuance/OID4VCIssuerEndpoint.java
Outdated
Show resolved
Hide resolved
...va/org/keycloak/protocol/oid4vc/issuance/credentialoffer/InMemoryCredentialOfferStorage.java
Outdated
Show resolved
Hide resolved
services/src/main/java/org/keycloak/protocol/oid4vc/issuance/OID4VCIssuerEndpoint.java
Show resolved
Hide resolved
services/src/main/java/org/keycloak/protocol/oid4vc/issuance/OID4VCIssuerEndpoint.java
Outdated
Show resolved
Hide resolved
services/src/main/java/org/keycloak/protocol/oid4vc/issuance/OID4VCIssuerEndpoint.java
Outdated
Show resolved
Hide resolved
148a067 to
0e2d39c
Compare
|
@Captain-P-Goldfish Thanks Pascal, for reviewing this |
92f6b41 to
fd6fba0
Compare
|
Is there a way to trigger re-testing other than rebase and forced push? |
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.federation.ldap.LDAPGroupMapperTest#test01_ldapOnlyGroupMappingsorg.keycloak.testsuite.federation.ldap.LDAPGroupMapperTest#test02_readOnlyGroupMappingsorg.keycloak.testsuite.federation.ldap.LDAPGroupMapperTest#test09_emptyMemberOnDeletionWorks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unreported flaky test detected, please review
IngridPuppet
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @tdiesler - Thank you for the substantial update to the OpenID4VCI flow. I checked the PR and left a few comments for consideration. Please could you check them?
My main concern would be that support for retrieving credentials with only the credential_identifier parameter at the Credential Endpoint was seemingly dropped, judging from the changes in tests.
...va/org/keycloak/protocol/oid4vc/issuance/credentialoffer/InMemoryCredentialOfferStorage.java
Show resolved
Hide resolved
...keycloak/protocol/oid4vc/issuance/credentialoffer/InMemoryCredentialOfferStorageFactory.java
Outdated
Show resolved
Hide resolved
services/src/main/java/org/keycloak/protocol/oid4vc/issuance/OID4VCIssuerEndpoint.java
Outdated
Show resolved
Hide resolved
services/src/main/java/org/keycloak/protocol/oid4vc/issuance/OID4VCIssuerEndpoint.java
Outdated
Show resolved
Hide resolved
services/src/main/java/org/keycloak/protocol/oid4vc/issuance/OID4VCIssuerEndpoint.java
Show resolved
Hide resolved
services/src/main/java/org/keycloak/protocol/oid4vc/issuance/OID4VCIssuerEndpoint.java
Outdated
Show resolved
Hide resolved
services/src/main/java/org/keycloak/protocol/oidc/grants/PreAuthorizedCodeGrantType.java
Outdated
Show resolved
Hide resolved
services/src/main/java/org/keycloak/protocol/oidc/grants/PreAuthorizedCodeGrantType.java
Show resolved
Hide resolved
...a/org/keycloak/testsuite/oid4vc/issuance/signing/OID4VCAuthorizationDetailsFlowTestBase.java
Outdated
Show resolved
Hide resolved
...e/src/test/java/org/keycloak/testsuite/oid4vc/issuance/OID4VCICredentialOfferMatrixTest.java
Outdated
Show resolved
Hide resolved
|
@IngridPuppet thank you so much for your detailed review - great suggestions, comments and lots of TLC for detail :-)
Using the credential scope as credential identifier is (imho) a hack that was used by many test cases - support for that has been removed and tests have been migrated to credential_configuration_id. Requesting a credential with only |
a97de63 to
02ea986
Compare
IngridPuppet
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for addressing my concerns and providing clarification. The PR looks good to me.
mposolda
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tdiesler Thanks for the PR and sorry for the late review.
@IngridPuppet @Captain-P-Goldfish Thanks for your reviews!
I've added 2 inline comments. Can you please check them? Also it seems that HoKTest failure might be a regression of your PR as it doesn't fail for any other PRs sent to Keycloak main. In your PR, you did some changes unrelated to oid4vci (like EG. marking one of the clients to have direct-grants enabled by default or renaming endpoints on TestingResource) and in theory, some of these can cause the test failure. Maybe just rebase on top of latest keycloak main helps.
| errorMessage, Response.Status.BAD_REQUEST); | ||
| } | ||
|
|
||
| UserSessionModel userSession = session.sessions().createUserSession(null, realm, userModel, userModel.getUsername(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: Is it strictly required to create new userSession (and new clientSession) for this use-case? For example for some similar use-cases (like for example OAuth2 client credentials grant implemented in ClientCredentialsGrantType), we are using "transient" user session.
This means that tokens are not attached to the real userSession, which is persisted into the DB. But tokens can be still used to be sent to Keycloak endpoints (like introspection-endpoint or admin REST API or anything else. I believe that oid4VCI credentials endpoint should work as well).
In short: Real user session is needed just if token refreshes are supposed to work. But it seems that tokens issued from "pre-authorized" grant doesn't need to be refreshed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The client exchanges the pre-auth code for an AccessToken it then calls the /credential endpoint with that AccessToken. For the TRANSIENT case authentication fails with invalid token here ...
UserSessionUtil.UserSessionValidationResult validationResult = UserSessionUtil.findValidSessionForAccessToken(session, realm, token, client, invalidUserSessionCallback);
if (validationResult.getError() != null) {
return null;
}
It would be expected to have no valid user session, because ...
- the Issuer created the the Pre-Auth CredentialOffer for a given target user (which might not have a user session)
- the target user then exchanges the pre-auth code for an AccessToken (i.e. no other login required)
- the issuer is expected to provide the pre-auth credential without the user ever needing to login
For clarity, I added the AuthorizationDetails to the pre-auth AccessToken as well (and not just to the AccessTokenResponse)
I left the the persistent user session in place (for now)
UserSessionModel userSession = session.sessions().createUserSession(null, realm, userModel, userModel.getUsername(),
null, "pre-authorized-code", false, null,
null, UserSessionModel.SessionPersistenceState.PERSISTENT);
Perhaps there is a way to work with a TRANSIENT user session. This could then be an improvement for later imho.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
retest this please |
Signed-off-by: Thomas Diesler <[email protected]>
…ent session against offer state (should be guaranteed by pre-auth token login) Signed-off-by: Thomas Diesler <[email protected]>
Signed-off-by: Thomas Diesler <[email protected]>
Signed-off-by: Thomas Diesler <[email protected]>
…ionDetailsResponse Signed-off-by: Thomas Diesler <[email protected]>
…CompleteFlowWithClaimsValidation Signed-off-by: Thomas Diesler <[email protected]>
Signed-off-by: Thomas Diesler <[email protected]>
Signed-off-by: Thomas Diesler <[email protected]>
closes #44116
This PR introduces CredentialOfferState that is decoupled from the any login session. It is acted upon getCredentialOffer and (later) upon getCredential. To create a credential offer, one must have the credential-offer-create role i.e. this is an issuer admin task and not something anybody can do. The credential offer is potentially bound to a target clientId and/or a target userId. Other constraints could also be enforced through this mechanism.
Once, the credential-offer-uri has been created successfully and (somehow) delivered to the wallet. There is no pre-requisite of any existing login session to redeem the credential-offer.
Credential Offer Validity Matrix
In the pre-auth offer case, the AccessTokenResponse does contain one AuthorizationDetail with both properties (i.e. credential_identifiers, credential_configuration_id). This is now natively supported in AccessTokenResponse.
The spec talks about what the wallet has to use in the CredentialRequest. It must use a credential identifier in the pre-auth case - this is now enforced in the endpoint.
Using the credential_configuration_id in the CredentialRequest is still supported.
Using the credential scope as credential identifier is (imho) a hack that was used by many test cases - support for that has been removed and tests have been migrated to credential_configuration_id.
The credential endpoint now does this ...
In short, a credential identifier can (currently) only be obtained through a pre-auth credential offer.
The tests that have a credential identifier, now also use it.