-
Notifications
You must be signed in to change notification settings - Fork 9
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
Wallet-provided nonce #92
Comments
The verifier should know its calling origin, and could include it as a parameter in the signed request. The web platform can pass the origin to the app platform and then to the wallet. The wallet can then validate that the signed request origin and calling origin match. Doesn't this address the concerns? |
Perhaps. The fundamental challenge is whether the Wallet is allowed to trust in the origin asserted by the web platform. If we assume so, I think it would require Verifier metadata trusted under the external trust management that would authorize the web origin along with requirements re the authentication of that web origin (e.g. qWACs only). As an example, if trust in the Verifier would be established using OpenID Federation, the Verifier's entity configuration could list legit web origins along with the respective trust anchors. |
I brought this trust issue up previously. The options are
Without 1 some info could leak about the existence of a credential if not the actual contents. To make 2 work on its own the wallet would need to: |
Yeah i think you can do one or more of the following:
|
I don't know that signing a timestamp is the equivalent to a nonce. The problem is that there is no audience in the nonce. Part of the problem is that we have two worlds, one that is webauthn which is a 2 party model based on web origins. The other is OAuth/Connect that are based on redirects where web origin is only available via Referer: headers and that is not to be trusted. This leads redirect based protocols to use identifiers for the parties and sign/encrypt messages end to end for security. Verifier/RP claims to be RPID X by signing a request , Wallet/AS looks up ClientID via internal DB or meta-data, Wallet/AS validates signature and determines encryption key and redirect URI for the response. The question is how to integrate the models and provide the best security and privacy, given the wallet may be regulated to not trust the browser completely when it comes to validating the origin, and the web origin not directly relating the the current notion of clientID being an abstract identifier. |
Ah yeah, ack on the timestamp issue! |
Not saying things are entirely equivalent here but isn't this the assumption that WebAuthn makes? E.g if the origin is compromised, an attacker could trick a webauthn provider to leak the existence of a credential?
The other problem to consider with signed timestamps is clock sync issues that could occur between the RP and wallet, generally a clock skew has to be introduced to account for this which can further degrade the rudimentary replay attack detection by widening the accepted time window by the wallet.
Personally I think I find this solution more appealing then a wallet provided nonce, however we'd have to carefully consider relying on encryption alone here (assuming we aren't trusting the browser). |
I'm not convinced that signing the request here does anything to provide the wallet with any greater assurance about who sent the request in the event you don't trust the web platform, because the entire request can just be replayed. It feels like the two core options we have are as @ve7jtb has pointed out, wallet provided nonce, or rely on authenticating the encryption key where I prefer the latter. |
Yes, WebAuthn operates on the premise that the client and channel are trusted. |
If we were to pursue a wallet-provided nonce, what would that look like in the API shape in practice? We can't share the nonce with the site until the user has consented to the data exchange and we don't even know which wallet is relevant until we show the credential picker. So I guess we'd be talking about adding a back-and-forth exchange after the user selects a credential? So the verifier first makes a request, then gets the nonce, then re-issues the signed request with the nonce? That seems pretty ugly and complex (eg. what happens if the second request is now different somehow?). Or maybe there's a simpler design I'm missing? |
As a part of deciding whether we need to explore this I'd like to understand the underlying threat model we are considering. For example it would appear on the surface that the solution option 2) as raised by @ve7jtb
wouldn't complicate the web API design (e.g it could still be a single request/response), while guaranteeing that only the relying party could decrypt the response (under the assumption of sound encryption). It would also allow the wallet to authenticate the relying party independent of the web platform through the encryption of the response. If we don't think this solution works, I'd be keen to understand why, if the assumption is that the attacker can defeat encryption, which is one of the possible POV's I've heard, then any wallet provided nonce solution here is also vulnerable because TLS can be defeated. To be clear I don't believe we should be making this assumption, I just wanted to share that observation. The only other concern I've heard about this proposed solution is that if the web origin is compromised, an attacker can get a credential presentation from a wallet, even though its encrypted and it cannot decrypt it. Which again I do question how big of an issue this is. Other then knowing a credential was presented to the origin from a wallet, what is leaked? On the flip side I find the wallet provided nonce solution quite complex for little benefit, it requires the wallet to interact directly with the verifier through network requests which could have negative privacy consequences and just generally increases the implementation complexity for both the wallet and the relying party. |
The question whether encryption is the solution is less a technical than a question of perception by users and regulators. Same with origin authentication. Authentication with the web origin might work for web authn, but the context we are in differs in some aspects: in Web Authn, the origin is used for creation (issuance) and use of one authentication credential and this credential is always presented to this origin only. Digital Credentials presentation is different as it may result in the disclosure of a huge number of credentials with substantial amount of PII to a third party. Think of personal identification, health data, and so on. So users as well as regulators might want to make sure the party the data is disclosed to can truly be identified (to be able to sue/prosecute them if needed) and they might not necessarily trust in the web PKI. Just take a look into the respective requirements in the eIDAS regulation. So if we cannot rely on the origin authentication (in regulated use cases), should we trust in the encryption of the response (assuming the encryption key can be linked to the legit recipient)? I'm not sure as it means the wallet would ask the user for consent to disclose data to a party we have not authenticated as recipient of the actual request. This is like saying "eh, we are not sure but even if you disclose the data to an evildoer, don't worry, it's encrypted." I'm sorry if that sounds paranoid, but I'm simply not sure whether this is the way we want to pursue. I think having a wallet provided nonce is a straightforward solution to the problem as it ensure the correct context of the authentication. There is a reason it is best practice in secure protocol design that the party consuming a signature should provide the challenge/nonce used in it. If that is impossible with the Digital Credentials API design, I suggest to pursue the alternative design I have meanwhile added to the OID4VP over Digital Credentials API proposal. It is to send the initial request (used to select the wallet) through the API and then let the Wallet obtain the signed request directly from the Verifier through a HTTPS endpoint. |
+1 to better understanding the threat models. I've written a threat model for the Chrome API that I can probably produce a public version of, but it can assume little about the credential and wallet ecosystem and so is pretty limited to the generic case which isn't likely to be helpful in this eIDAS-focused discussion (in which I'm definitely not qualified to produce a threat model). In terms of @leecam's signed timestamp suggestion for thwarting replay attacks, isn't it fairly standard to use a timestamp plus a random value as a nonce? If the verifier generated a nonce like that, then the wallet just has to verify that the timestamp is recent and also that the nonce wasn't previously seen within the timestamp acceptance window. I think that's almost as strong as having a wallet-generated nonce (and much simpler to implement). Also +1 to having the wallet encrypt the response using a verifier-supplied certificate (whether that's qWAC or something else in other contexts). That seems like the primary mechanism for ensuring confidentiality of the response. But presumably @tlodderstedt has a threat in mind where just replaying a request without being able to read the response could be harmful, which I can definitely imagine (eg. exhausting the wallet's limited supply of tokens like, I think, the ISO-18013 MSO). |
I think we need to reframe here for these "regulated usecases". I dont think this API should be conceptualised or designed to have two distinct ways of a wallet authenticating the RP. Rather the wallet authenticating the RP via the attested origin from the browser should be table stakes and something that is mandatory for a wallet to perform. Authenticating the RP via an external mechanism (like an independent certificate chain) should be viewed as an additional layer not an alternative.
I understand the driver here but I think its important to point out that even if an API design was pursued where there was never any trust in the web platform assumed, trust is still required in the web platform because you are after all in a web browser. Everything the user did up until the point that the website they are visiting calls this API and everything after requires a level of trust in the browser. |
I'm ok with viewing the external mechanism as additional layer. My focus is on getting this additional layer secured appropriate. As I explained, I think a signed request including a wallet provided nonce is the most appropriate design taking into consideration secure design best practices. There are two options: 1) the DG API provides that feature or 2) wallet and verifier sort that our directly. I would prefer (1) but (2) works, too, and don't requires changes to the API design. |
This thread needs flow diagrams to be comprehensible. The use of the word "nonce" is also extremely ambiguous, because it could be random, signed or encrypted. |
Thinking about the OpenID4VP proposal referenced in this issue, after discussing with others more, I don't think the approach achieves the security properties it desires, specifically "authenticating the RP before sending the response". This is because the request sent over the browser API is inherently replay-able. For example consider example.com is the verifier origin making the credential presentation request using this OpenID4VP proposal, if an attacker simply obtains a fresh valid OpenID4VP request from the verifier backend (example.com's backend) and sends it through the browser api from its own origin (attacker.com) or through a compromise to the verifiers origin (example.com). The wallet on receipt of the the request will resolve the request_uri and conclude the verifier is "authenticated" (e.g as the sender of the request), after obtaining user consent it will generate and send a response back through the API to the attacker. This to me makes it clear that the wallet provided nonce doesn't meaningfully improve the assurances around authenticating the verifier prior to generating and sending the response. So I would prefer we explore for usecases that require it, providing a way to authenticating the response encryption key as an additional web platform independent mechanism for authenticating the RP. |
@tplooker which of the messages is replayed? |
Replay might be a bit presumptuous, but basically the attacker site gets a genuine request from the attacker backend, which includes a genuine request_uri that will resolve. It then plays it through its own (attacker) origin, basically because all the relying party authenticate is based on the response to the request_uri, the wallet will "authenticate" the request and send the response, even though it is sending the response back to the attacker. |
@tplooker the attacker can get access to credential data. Counter-measures:
|
Agree with all the above as counter measures other then the last one
The only way I see this one working is if the origin sent here is the attested origin provided by the browser? Perhaps that is what you meant? IMO though fetching the request from the request_uri with a wallet provided nonce would appear not to make sense now from a security perspective, because if we have concluded that the signed request coming back from this endpoint doesn't actually reliably authenticate the verifier / relying party, could we not revert to a simpler model which just relies on the verifier / relying party, sending the wallet the request directly over the browser API, if not, what does fetching the signed request from the request_uri do security wise? |
Discussed on the call now that this can probably be closed based on conversations at IIW, but will wait for confirmation from @tlodderstedt. |
yes, we have found an appropriate solution that is described in the OID4VP DC API Profile. I close this issue. |
Based on our work on an OpenID 4 VP profile for the Digital Credentials API, I believe the API would benefit from allowing Wallets to provide Verifiers with a nonce.
The challenge we see is that at least the eIDAS regulation requires the Wallet to authenticate the Verifier/RP based on a trust management, that is not the Web trust management. Articles 5a and 5b of the eIDAS regulation require the EU member states to run their own trust management infrastructure with dedicated certificates/attestations to be used for that purpose (see the OpenID 4 VP proposal for details).
That's why the OpenID 4 VP profile allows Verifiers to send signed requests through the Digital Credentials API. The fundamental challenge with this approach is that the signed request can be captured and replayed by anyone able to run a legit website in his browser. If an attacker would replay such a request through the Digital Credentials API, the wallet would provide the credential data to the attacker.
The wallet could use the calling origin as asserted by the platform. However, I see the following issues:
I think we need additional countermeasures.
That challenge exists independent of the Digital Credentials API. OpenID 4 VP implementations today cope with that challenge by sending the data to an endpoint asserted in the signed request object. Additionally, we are in the process of allowing the wallet to issue a nonce that the Verifier must include in the signed request object.
I suggest to add support for a wallet provided nonce to the Digital Credentials API. This would allow the selected wallet (instance) to create a nonce and force the Verifier to add it to the signed request. Given the device/instance bound nature of that nonce, the request could not be replayed on a different device.
The alternative, I'm considering currently, is to allow for direct communication between Wallet and Verifier, so the Wallet could provide a nonce directly to the Verifier through a HTTP POST request and the Wallet could send the credential data directly to the Verifier through another HTTP POST request. This alternative would use existing OpenID 4 VP messages.
see the OpenID 4 VP profile proposal for details.
The text was updated successfully, but these errors were encountered: