Skip to content
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

Clarify that signed requests for DC API should be rejected if the signature can't be verfied #395

Open
GarethCOliver opened this issue Jan 23, 2025 · 8 comments
Labels
ISO_VirtualMeeting relevant for ISO OID4VP mdoc profile over DC API
Milestone

Comments

@GarethCOliver
Copy link

It'd be good to call out that, if the wallet can not verify the signature for the signed version (A.3.2), then they must reject the request. As we were implementing this, initially we assumed that falling back to how we handle the unsigned case would make sense. However, because the origin is not included for signed cases, it would be vulnerable to replay attacks in ways that unsigned is not.

At least to me, this wasn't clear from reading A.3.

It'd be nice (IMO) if an unsigned request, and a signed request that can't be verified by a wallet had the same security properties and would be a motivation for including the origin in all cases.

@c2bo
Copy link
Member

c2bo commented Jan 24, 2025

If that kind of downgrade is wanted, couldn't you in theory just change the client_id to web-origin: in the response? That way you would still include the platform-provided origin in the response and keep the same security assumptions as a standard unsigned flow.

That would also clearly signal to the RP that the wallet was not able to verify the trust framework it provided and it downgraded to the unsigned flow.

Somewhat relevant issue: #362

@Sakurann Sakurann added the ISO_VirtualMeeting relevant for ISO OID4VP mdoc profile over DC API label Jan 28, 2025
@jogu
Copy link
Collaborator

jogu commented Jan 29, 2025

Two probably very related clarifying questions:

@GarethCOliver "However, because the origin is not included for signed cases" - do you mean we should state that in the response to a signed request (e.g. the aud value in SD-JWT) the web-origin:https://www.example.com/ value should be used in this case? Or did you mean something else?

@c2bo Included where? In an mdoc response I don't think we return the client_id to the verifier other than encoded in the session transcript?

@jogu
Copy link
Collaborator

jogu commented Jan 29, 2025

It was raised in today's ISO meeting that (if we are going to allow the wallet to accept requests where it can't validate the signature) then we do need to be clear in OID4VP how the wallet should then behave (e.g. if it should use the client_id in the signed request, or as suggested above use one derived from the origin instead), so that the verifier then knows what to expect.

This is particularly important in the case of mdoc/mdl where the verifier will need to know what client_id the wallet decided to use in order to calculate the SessionTranscript correctly.

@GarethCOliver
Copy link
Author

So I was initially assuming we should just reject if the request signature can't be verified (as expected_origins can't be trusted in that case). @c2bo's suggest is more elegant:

Essentially treat the platform-provided origin as one of many different potential client_ids. Whichever one the RP trusts, should be included in the aud (and then which one was trusted needs to be included in the response somewhere to prevent needing to attempt verification multiple times).

(so for a concrete example, if there is a signed request for age-over-18, but the wallet can't verify it, and doesn't recognize the origin, but issuer policy for that mDL is that all origins are allowed to request age-over-18, then the wallet will return the request using client_id=web-origin:.. A wallet that could verify the signature as belong to a trust framework it trusts would return that client_id instead).

This does then open up the follow-up of 'what if the wallet trusts multiple of the provided client-ids'. The answer to which could be:

  1. include whichever one the wallet thinks is strongest (e.g. if you get a client_id and an origin, trust both but trust the trust framework more, include the client id, otherwise if you trust the origin more, include the origin).

  2. include all ones that you trust (this helps with the problem @martijnharing was raising: if you trust both origin and client_id, but the trust framework is weaker than the TLS, having both requires both to be broken).

@c2bo
Copy link
Member

c2bo commented Jan 30, 2025

@c2bo Included where? In an mdoc response I don't think we return the client_id to the verifier other than encoded in the session transcript?

Fair point, we would have a similar problem to the one we have in the multi rp discussion for mdoc. In both cases the RP would need that information explicitly. I guess the same problem would hold true for credentials that are not key-bound since they currently would not include client_id anywhere in the response.

Not entirely sure about this, but it looks to me like we should think about adding client_id as an explicit field somewhere in the Authorization Response (or vp_token).

@Sakurann Sakurann added this to the Final 1.0 milestone Jan 30, 2025
@Sakurann
Copy link
Collaborator

WG discussion:

  • need time to think a bit more, but rough consensus forming around proposal to change client_id to use client_id_scheme web-origin:, when request was signed, but wallet did not validate the request.
    • one issue that arises from this approach is that RP knows the client id scheme changed, one way to cope with this will be to pass client_id in the response, which means breaking change and changing the response structure? Alternative is aud in signed and encrypted response, which is rarely used.
    • explicitly say that it is up to the wallet whether it fails the request when signature is not validated or to continue
    • this means that verifier needs to support both cases if it cares? always? need to explicitly state - in the client metadata?
  • passing client_id in the response is an info leak, which should be clearly documented but isn't being able to detect ignoring the signature more concerning?
  • do we want to detect that wallet did not validate the signature or not?
  • alternative is to always pass the origin in the key binding piece (session transcript, KB JWT, anon creds, etc.), but that has implications on other credential formats.

will discuss in the next WG and make a decision .

@Sakurann
Copy link
Collaborator

Sakurann commented Feb 4, 2025

WG discussion

who determines what...:

  • when the RP gets credential it can determine the issuer. it is issuer who defines the security policy, wallet enforces it so verifier needs to know
  • new input: ultimately verifier makes the decision whether it is ok for the wallet not to validate the signature and fallback to webPKI authentication?
  • ultimately it is up to the wallet to decide what to do?
  • ultimately verifier has to know whether the wallet has validated the signature or not. if the wallet did not consider the signature, response can be replayed.
  • can also be issuer's choice for example with embedded disclosure policy with EUDIW

Role of the signature...:

  • difference in perspective is whether signature of the request is THE authentication mechanism or layer on top. In EUDIW ecosystem for example, signature is the authenticaiton mechanism and falling back to web pki is not an option.
    • security of the signed request is bound to the origin?
  • signature is usually tied to a certain trust infrastructure.
  • a lot of this is solved by multi RP PR?

options

  1. say wallet must fail if it cannot validate the signature
  2. say wall is ok not to validate the signature
  3. do not say anything
  4. in openid4vp say it depends on the trust framework; in HAIP define two+ behaviors dependent on the trust framework (like in EUDIW wallet must validate, outside it, ok not to?)
  5. define a mechanism
    a. verifier indicates if it requires to validate
    b. wallet communicates if it validated or not
  6. issuer communicates whether it mandates the wallet to validate or not and wallet and verifier has to follow that

1, 2 does not seem to be able to get consensus?
3, 4 are not ideal for interop?
5 or 6 seems to be an option...?

@tlodderstedt
Copy link
Collaborator

I perceive there is common ground regarding the governance model for RP authentication: The issuer defines the policy, the wallet enforces it.

I think the fundamental difference is in assumptions regarding what the RP knows. Some people believe the verifier does not know anything about what mechanism/credentials are needed to obtain a certain credential from the wallet. I would like to understand how the RP would determine whether to sign a request or not and with what key material (tying into some trust infrastructure).

I believe the RP wil need to know and can know. The RP knows what issuer's credentials it accepts. So it will also determine from the set of issuers their requirements on RP authentication and, if needed, get the respective credentials and use them with the respective requests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ISO_VirtualMeeting relevant for ISO OID4VP mdoc profile over DC API
Projects
None yet
Development

No branches or pull requests

5 participants