openid / OpenID4VCI

68 stars 20 forks source link

Additional options for wallet-provided nonces for PoP #357

Open awoie opened 4 months ago

awoie commented 4 months ago

On the DCP WG call on June 27th, we concluded that c_nonce is in fact optional. To mitigate the attack discussed here https://github.com/openid/OpenID4VCI/issues/19 without a c_nonce, several options were brought up and we agreed to create a dedicated issue for this.

Some options are:

  1. ath (access token hash)
  2. jti (chosen by the wallet with enough entropy)
  3. nonce (keep nonce in PoP but allow wallet-generated nonces similar to jti; probably not a good idea because in some situations/policies a server might fail distinguishing between c_nonce values and wallet-generated nonces in the nonce claim)

(cc @David-Chadwick @Sakurann @jogu @bc-pi @babisRoutis)

peppelinux commented 4 months ago

The ath indeed has limitations, as it is typically applicable only to the first HTTP request made to the Resource Server (RS).

From a security and design perspective, when the RS supports the issuance of multiple credentials using the same Access Token (AT), it is practical to issue a c_nonce in the RS's response; in this way the RS hints the client about its support of multiple issuance with the same AT. This c_nonce should then be expected in the next request to the RS, utilizing the nonce parameter.

Given these considerations, I support option 2, using the jti (JWT ID). This choice avoids conflicts with the optional nature of the nonce during the initial request and aligns with the requirement for a nonce in subsequent requests if it is provided in the RS's response.

babisRoutis commented 4 months ago

The ath indeed has limitations, as it is typically applicable only to the first HTTP request made to the Resource Server (RS).

@peppelinux Can you please clarify - to understand your comment - whether the RS term corresponds to the Credential Issuer (protected endpoints)?

peppelinux commented 4 months ago

@babisRoutis yes, the credential endpoint is an RS in the OAuth 2.0 paradigm

nemqe commented 4 months ago

I think the jti variant makes sense.

Would this be a purely Wallet side mechanism, no Issuer involvement needed?

peppelinux commented 4 months ago

@nemqe yes jti is self-issued by the issuer, it's a pure identifier that uniquely identifies a JWT within its issuer

a non-exaustive comparison between nonce and jti was outlined in the following I-D: https://peppelinux.github.io/draft-demarco-oauth-nonce-endpoint/draft-demarco-oauth-nonce-endpoint.html#name-considerations-about-nonce-

nemqe commented 4 months ago

@peppelinux I was thinking more about who is protecting who in this case.

Wasn't sure where the responsibility for safety of this interaction lies, and if the Issuer will need to keep track of jti values so it guarantees that no same value has been used during the session or not or will it be ok if the Issuer does not care at all.

peppelinux commented 4 months ago

@nemqe

jti unlike nonce is not absolute but relative to its issuer

nonce is absolute because who evaluates its uniqueness is at the same time its issuer

jti is "unique together" with its issuer and who evaluates its uniqueness must keep track of it until the jwt in which it is contained is active and not expired (or revoked, see introspection endpoint)

for this reason nonce is cheaper, because we "suppose" that a jwt may have a longer lifetime of a nonce that is it issued just in time for a specific transaction, where this transaction assumes a short duration.

I support jti to uniquely identify a jwt, together with its issuer, like a best practice (you see in all the italian specs its presence).

peppelinux commented 4 months ago

the RS is the party that must protect itself from replay attacks, therefore it should keep track of jwts against any replay of these, until the jwts expires.

awoie commented 4 months ago

It is also possible to include both, ath and jti which would mitigate @peppelinux concern that ath would be the same during the lifetime of the access token. Using both has the advantage to have something the holder chose and something the AS chose.

babisRoutis commented 4 months ago

These options remind me DPoP

DPoP JWT contains jti, ath and .. nonce (among other claims).

Anyway, with regards to the issue I strongly believe that a single mandatory solution would be better than have multiple alternative (yet optional) choices.

Should c_nonce be kept? Then:

if c_nonce is considered, on the other hand, optional, let's remove it from spec and define a single alternative (jti, jti+ath, or something else)

nemqe commented 4 months ago

Small brain dump, I apologize in advance for possibly saying things people know, have discussed, or just plain incorrect things

The way I see it:

ath in the proof should prevent the proof-replay of the initial request (token header alone should prevent request-replay)

Being a defensive Wallet I might not trust the Issuer and his way of generating tokens, and for this reason I would want to introduce a jti into the proof because now I also participate in ensuring the safety on my communication.

Now the problem with a jti is that I as an Issuer might not trust the value provided by the Wallet. Problem is not only checking that a jti is unique during a 'session' but also ensuring that the same jti has not been used with some other Issuer. Because of this as an Issuer I want to add a c_nonce for subsequent requests.

Meaning:

awoie commented 4 months ago

Meaning:

  • for the initial request i see a ath + jti scheme
  • for subsequent requests I see a ath + jti + c_nonce scheme

@nemqe I believe I agree with this.

@babisRoutis on removing c_nonce from token endpoint, let's have the discussion in this other issue https://github.com/openid/OpenID4VCI/issues/39

Sakurann commented 3 weeks ago

this probably supersedes/relates to #19 ?