-
Notifications
You must be signed in to change notification settings - Fork 8k
[OID4VCI] Revisit and fix /credential_offer_uri endpoint #46199
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
base: main
Are you sure you want to change the base?
Conversation
2460fa7 to
58a1668
Compare
55b67da to
1c7d141
Compare
Signed-off-by: Thomas Diesler <[email protected]>
Signed-off-by: Thomas Diesler <[email protected]>
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! Did not reviewed whole PR (as I see it depends on the other PRs), but added some comments inline (especially the tx_code is the most important one).
| } | ||
| CredentialOfferURI credOfferURI = new CredentialOfferURI() | ||
| .setIssuer(credOffer.getCredentialIssuer() + "/protocol/" + OID4VC_PROTOCOL + "/" + CREDENTIAL_OFFER_PATH) | ||
| .setTxCode(offerState.getTxCode()) |
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.
We should not send tx_code in a response this way. This would make security of this REST endpoint even more broken than it is today.
The tx_code should be shared just with the user. Not with the other parties like administrator or "DataHolder / Issuer portal" application.
In Keycloak, the only reliable way to share things asynchronously with users is via email and that should be default how tx_code would be sent to the users (maybe we can have SPI to consider other ways if someone prefers SMS for example or something else like you're doing here, but that is likely out of scope of this PR).
Ideally, there should be email sent to the user. Once user clicks on the link from the email, Keycloak will display him the page with tx_code from where he can get it and fill inside wallet, which applies for pre-auth codes. @stianst suggested to use action-tokens flow instead of sending directly action-token by email for better security. Some thoughts about this are in this issue: #46269 .
This is additional work and might be not so trivial to implement (if you're not familiar with action-tokens and how they are used in KC). I can help (possibly somewhen next week) and send the initial PR for tx_code support somewhen next week, which then you would be able to consume more easily in this PR. Planning to do that after initial work for #46196 .
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 purpose of this endpoint is to create the credential offer - it is not concerned about how the offer (or parts of it) are delivered to the target value. We can make the return of this endpoint void and have a another endpoint that fetches credential offer state. It would however not fix the issue in principal - just delegate it to some other endpoint.
Please don't forget, the pre-auth grant is designed for cases where a wallet cannot do alternative authorization steps. The assumption that the holder can authenticate with Keycloak in order to use a pre-auth offer is likely flawed - if it could, there would be no need to use a pre-auth offer.
My stance on this is that access to this endpoint must be protected (for the targeted pre-auth case) like any other rest endpoint that allows an admin to do security sensitive stuff (e.g. modify a user's password). the pre-auth code should give access to the offered credential (and nothing else). Getting hold of the pre-auth code would be equivalent to getting hold of any credential that is bound to someone else.
services/src/main/java/org/keycloak/protocol/oidc/grants/PreAuthorizedCodeGrantType.java
Outdated
Show resolved
Hide resolved
| public Response createCredentialOffer( | ||
| @QueryParam("credential_configuration_id") String credConfigId, | ||
| @QueryParam("pre_authorized") @DefaultValue("true") boolean preAuthorized, | ||
| @QueryParam("client_id") String appClientId, |
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 think client_id should be still possible and would be good to keep it. The credential-offer permission might not be limited to the single wallet/client, but there are also use-cases where it might be limited to single client.
In relation to that: Specification defines credential_offer_endpoint as additional field in client's metadata where credential offer could be eventually sent. We do not have support for this endpoint, but it indicates that specification counts with the fact that credential-offer could be sent directly to the wallet, which indicates that it is used for particular wallet.
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.
Let's perhaps do the targeted clientId after preview when we have an actual use case that demands it.
The wallet is not the oauth client.
Yes, we can talk about credential_offer_endpoint (perhaps also after preview) it is however unrelated to targetClient which names the oauth clientId that the (pre-auth) offer is good for.
I removed it for security reasons. The user that has privileges to create a targeted offer (i.e. has the create_credential_offer role) has that privilege only for the current clientId - he cannot create a targeted offer for a clientId that he himself has no access to.
Signed-off-by: Thomas Diesler <[email protected]>
closes #45005
Discussion: #46202