Thanks to visit codestin.com
Credit goes to Github.com

Skip to content

Conversation

@tdiesler
Copy link
Contributor

@tdiesler tdiesler commented Feb 11, 2026

closes #45005

Discussion: #46202

@tdiesler
Copy link
Contributor Author

tdiesler commented Feb 11, 2026

Depends on ...
#45960
#45985
#46004

@tdiesler tdiesler force-pushed the ghi45005 branch 2 times, most recently from 2460fa7 to 58a1668 Compare February 11, 2026 10:32
@tdiesler tdiesler force-pushed the ghi45005 branch 3 times, most recently from 55b67da to 1c7d141 Compare February 12, 2026 16:28
Copy link
Contributor

@mposolda mposolda left a 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())
Copy link
Contributor

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 .

Copy link
Contributor Author

@tdiesler tdiesler Feb 13, 2026

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.

public Response createCredentialOffer(
@QueryParam("credential_configuration_id") String credConfigId,
@QueryParam("pre_authorized") @DefaultValue("true") boolean preAuthorized,
@QueryParam("client_id") String appClientId,
Copy link
Contributor

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.

Copy link
Contributor Author

@tdiesler tdiesler Feb 13, 2026

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.

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] Revisit and fix /credential_offer_uri endpoint

2 participants