-
Notifications
You must be signed in to change notification settings - Fork 7
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
Adds server-provided nonces for Client Attestation PoP JWT freshness verification #64
base: main
Are you sure you want to change the base?
Conversation
An authorization server MAY require the use of nonces. | ||
This requirement is communicated to the client by having the authorization server return an HTTP response with the `400` status and an `error` field with the value `"use_attestation_nonce"`, when the Client Attestation PoP JWT present in the HTTP request does not contain a valid nonce. | ||
This HTTP response MUST also contain the `Attestation-Nonce` header, with the value of the new server provided nonce. | ||
The client MUST use this new nonce value to create a new Client Attestation PoP JWT and resend the previous request. |
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 client MUST use this new nonce value to create a new Client Attestation PoP JWT and resend the previous request. | |
The Client MUST use this new nonce value to create a new Client Attestation PoP JWT and resend the previous request. |
@pmhsfelix I'm wondering if using Client as defined term in OAuth 2.0. If yes this change is required within the entire text
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.
lgtm
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 suggest some normative language for the nonce
syntax and HTTP error message. All in all good, so green light from me.
|
||
This section specifies a mechanism using server provided opaque nonces to limit the lifetime of a Client Attestation PoP JWT, similar to the one defined in section 8 of {{RFC9449}}. | ||
Without employing such a mechanism, a malicious party controlling the client (potentially including the end-user) can create Client Attestation PoP JWT for use arbitrarily far in the future. | ||
In addition, a mismatch between the time reference of a non-malicious client (e.g. a mobile device) and the time reference of the authorization server, may result in Client Attestation PoP JWT that are never accepted by the authorization server. |
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.
In addition, a mismatch between the time reference of a non-malicious client (e.g. a mobile device) and the time reference of the authorization server, may result in Client Attestation PoP JWT that are never accepted by the authorization server. | |
In addition, a mismatch between the time reference of a client (e.g. a mobile device) and the time reference of the authorization server, may result in Client Attestation PoP JWT that are never accepted by the authorization server. |
Without employing such a mechanism, a malicious party controlling the client (potentially including the end-user) can create Client Attestation PoP JWT for use arbitrarily far in the future. | ||
In addition, a mismatch between the time reference of a non-malicious client (e.g. a mobile device) and the time reference of the authorization server, may result in Client Attestation PoP JWT that are never accepted by the authorization server. | ||
|
||
Including a nonce value contributed by the authorization server in the Client Attestation PoP JWT MAY be used by authorization servers to limit the lifetime of those proofs, both protecting against attacks and allowing for interoperability with clients with different time references. |
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.
Including a nonce value contributed by the authorization server in the Client Attestation PoP JWT MAY be used by authorization servers to limit the lifetime of those proofs, both protecting against attacks and allowing for interoperability with clients with different time references. | |
Including a nonce value provided by the authorization server in the Client Attestation PoP JWT MAY be used by authorization servers to limit the lifetime of those proofs, both protecting against attacks and allowing for interoperability with clients with different time references. |
"provided" because it maps the header.
Including a nonce value contributed by the authorization server in the Client Attestation PoP JWT MAY be used by authorization servers to limit the lifetime of those proofs, both protecting against attacks and allowing for interoperability with clients with different time references. | ||
|
||
An authorization server MAY require the use of nonces. | ||
This requirement is communicated to the client by having the authorization server return an HTTP response with the `400` status and an `error` field with the value `"use_attestation_nonce"`, when the Client Attestation PoP JWT present in the HTTP request does not contain a valid nonce. |
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.
Use formative language:
This requirement is communicated to the client by having the authorization server return an HTTP response with the `400` status and an `error` field with the value `"use_attestation_nonce"`, when the Client Attestation PoP JWT present in the HTTP request does not contain a valid nonce. | |
If the authorization server requires the use of nonces, the authorization server MUST return an HTTP response with the `400` status and an `error` field with the value `"use_attestation_nonce"`, when the Client Attestation PoP JWT present in the HTTP request does not contain a valid nonce. |
This requirement is communicated to the client by having the authorization server return an HTTP response with the `400` status and an `error` field with the value `"use_attestation_nonce"`, when the Client Attestation PoP JWT present in the HTTP request does not contain a valid nonce. | ||
This HTTP response MUST also contain the `Attestation-Nonce` header, with the value of the new server provided nonce. | ||
The client MUST use this new nonce value to create a new Client Attestation PoP JWT and resend the previous request. | ||
The server provided nonce must be included in the `nonce` JWT payload claim, as a JSON string. |
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 server provided nonce must be included in the `nonce` JWT payload claim, as a JSON string. | |
The server provided nonce must be included in the `nonce` JWT payload claim, as a string. |
Doesn't "JWT payload claim" imply that the data is JSON?
} | ||
~~~ | ||
|
||
Authorization servers MAY also include the `Attestation-Nonce` in success responses, as a way to communicate newer nonces values to clients. |
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.
Authorization servers MAY also include the `Attestation-Nonce` in success responses, as a way to communicate newer nonces values to clients. | |
Authorization servers MAY also include the `Attestation-Nonce` in success responses, as a way to communicate newer nonce values to clients. |
|
||
Authorization servers MAY also include the `Attestation-Nonce` in success responses, as a way to communicate newer nonces values to clients. | ||
Clients SHOULD keep using a nonce received in a `Attestation-Nonce` header until a newer value is received via this header, both on success or non-success responses. | ||
Responses that include the `Attestation-Nonce` HTTP header should be uncacheable (e.g., using `Cache-Control: no-store` in response to a GET request) to prevent the response from being used to serve a subsequent request and a stale nonce value from being used as a result. |
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.
Responses that include the `Attestation-Nonce` HTTP header should be uncacheable (e.g., using `Cache-Control: no-store` in response to a GET request) to prevent the response from being used to serve a subsequent request and a stale nonce value from being used as a result. | |
Responses that include the `Attestation-Nonce` HTTP header should be uncacheable (e.g., using `Cache-Control: no-store` in response to a GET request) to prevent returning cached, stale nonce values in subsequent requests. |
The client MUST use this new nonce value to create a new Client Attestation PoP JWT and resend the previous request. | ||
The server provided nonce must be included in the `nonce` JWT payload claim, as a JSON string. | ||
|
||
The following non-normative example presents an example of a non-success response, including the new nonce in the `Attestation-Nonce` header. |
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.
Repeating expression:
The following non-normative example presents an example of a non-success response, including the new nonce in the `Attestation-Nonce` header. | |
The following non-normative example represents a non-success response, including the new nonce in the `Attestation-Nonce` header. |
When receiving a `Attestation-Nonce` in a success response, the client MUST not retry the request. | ||
Instead, the client MUST use the provided nonce the next time a Client Attestation PoP JWT need to be computed. | ||
|
||
An example 200 OK response providing a new nonce value is shown below. |
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.
An example 200 OK response providing a new nonce value is shown below. | |
The following non-formative example shows a 200 OK response providing a new nonce value. |
|
||
## Nonce syntax | ||
|
||
The nonce syntax in ABNF as used by {{RFC6749}} (which is the same as the scope-token syntax) is shown below. |
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 believe this sentence is missing a formative language. We may even add it above where thenonce
claim is originally defined.
This is the obvious solution going in the right direction. I'm not convinced yet that this is the ideal solution, especially in combination with DPoP. |
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.
just editorial, consider it approved
@@ -233,6 +234,57 @@ The following example is the decoded header and payload of a JWT meeting the pro | |||
} | |||
~~~ | |||
|
|||
# Authorization Server-provided nonces | |||
|
|||
This section specifies a mechanism using server provided opaque nonces to limit the lifetime of a Client Attestation PoP JWT, similar to the one defined in section 8 of {{RFC9449}}. |
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.
This section specifies a mechanism using server provided opaque nonces to limit the lifetime of a Client Attestation PoP JWT, similar to the one defined in section 8 of {{RFC9449}}. | |
This section outlines a method that utilizes server-generated opaque nonces to restrict the lifespan of a Client Attestation Proof of Possession (PoP) JWT., similar to the one defined in section 8 of {{RFC9449}}. |
Without employing such a mechanism, a malicious party controlling the client (potentially including the end-user) can create Client Attestation PoP JWT for use arbitrarily far in the future. | ||
In addition, a mismatch between the time reference of a non-malicious client (e.g. a mobile device) and the time reference of the authorization server, may result in Client Attestation PoP JWT that are never accepted by the authorization server. |
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.
Without employing such a mechanism, a malicious party controlling the client (potentially including the end-user) can create Client Attestation PoP JWT for use arbitrarily far in the future. | |
In addition, a mismatch between the time reference of a non-malicious client (e.g. a mobile device) and the time reference of the authorization server, may result in Client Attestation PoP JWT that are never accepted by the authorization server. | |
Without this mechanism, a malicious entity, which could include the end-user, controlling the client can generate Client Attestation Proof of Possession (PoP) JWTs for unrestricted future use. Moreover, a discrepancy between the time reference of a benign client (like a mobile device) and the authorization server's time reference could lead to Client Attestation PoP JWTs that the authorization server never accepts. |
Including a nonce value contributed by the authorization server in the Client Attestation PoP JWT MAY be used by authorization servers to limit the lifetime of those proofs, both protecting against attacks and allowing for interoperability with clients with different time references. | ||
|
||
An authorization server MAY require the use of nonces. | ||
This requirement is communicated to the client by having the authorization server return an HTTP response with the `400` status and an `error` field with the value `"use_attestation_nonce"`, when the Client Attestation PoP JWT present in the HTTP request does not contain a valid nonce. |
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.
This requirement is communicated to the client by having the authorization server return an HTTP response with the `400` status and an `error` field with the value `"use_attestation_nonce"`, when the Client Attestation PoP JWT present in the HTTP request does not contain a valid nonce. | |
This requirement is communicated to the Client by having the authorization server return an HTTP response with the `400` status and an `error` field with the value `"use_attestation_nonce"`, when the Client Attestation PoP JWT present in the HTTP request does not contain a valid nonce. |
Agree with the direction and also unsureness around DPoP. There's a lot of overlap and duplicative text and functionality with DPoP in this nonce mechanism and the Client Attestation PoP JWT itself. A lot. It makes me question (again) if it wouldn't be better to use the DPoP Proof JWT as the PoP mechanism in this work rather than recreate so much of it with the Client Attestation PoP JWT. |
@bc-pi That ties two mechanisms together that were built for different purposes. I think that would make sense if client attestation would always be used with DPoP bound access tokens. That means: a) no client attestation without sender constrained access tokens and b) no mTLS for sender constrained access tokens when using client attestation. |
The DPoP proof JWT part of RFC9449 was built exactly for the purpose of proving possession of a key in the context of an HTTP request. And can be used without necessarily binding access tokens. |
Also had the exact same feeling while writing the PR, namely the creation of a duplicate header and a duplicate OAuth error code. Using DPoP for the proof-of-possession did also cross my mind. We could perhaps decouple the DPoP proof of possession JWT from the
If we want to use DPoP all the way, then this seems to work perfectly. |
DPoP itself specifically has text in the DPoP Access Token Request section that allows for an AS to issue access tokens that are not DPoP bound. It says:
And this draft could certainly reiterate that, if it went with the DPoP proof as its PoP mechanism. There is and has been (it's come up previously) a lot of resistance to that approach though. But maybe that resistance was from the misconception that DPoP usage at the token endpoint meant that access tokens had to be DPoP bound. |
At least I'd failed to realise this language existed in DPoP and it feels like because of that I dont really see why we shouldn't consider using the DPoP format for the PoP, it feels both generalised enough for other endpoints AND doesn't mandate the tokens issued from the token endpoint are DPoP bound. |
So we would use the DPoP token format and convey it via the |
I'm somehow hesitant to put everything in the headers. I think we should evaluate to reuse the key from the client attestation as a key for dpop binding and somehow reuse the nonce providing mechanism. As this is a major use case in mind, we should avoid sending multiple nonces, using multiple keys and proofs. |
I also prefer reusing and building upon existing specs, i.e. DPoP (RFC 9449) and Assertion based client authentication (RFC 7521), over copying text. This spec already profiles RFC 7521 but could also use DPoP to satisfy the key-binding of the client attestation. Instead of concatenating two JWTs into a single assertion, the POST /token HTTP/1.1
Host: as.example
Content-Type: application/x-www-form-urlencoded
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImp3ayI6eyJhbGciOiJFUzI1NiIsImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ4IjoiaThReW03NFRNUHVLQXVKUGlZczFSZlVsYTVjemNxelVobEpmRHNMdzd0NCIsInkiOiJGQjlUY2ZmeVZDSEpFQjJjejc4NTE2MUE0SmxlTkh2cG44bXhHRldZMlNjIn0sImFsZyI6IkVTMjU2In0.eyJqdGkiOiIzNTc2ODI5Ny1kZWM1LTQ2ZjYtODVlNS1iNzU4MjE2YWI1ZmYiLCJodG0iOiJQT1NUIiwiaHR1IjoiaHR0cHM6Ly9hcy5leGFtcGxlL3Rva2VuIiwiaWF0IjoxNzAwODEyODAwLCJub25jZSI6ImV5SjdTX3pHLmV5SkgwLVouSFg0dy03diJ9.5VuDrkd8RhMRaps_AzJBs2p-_UXXWT4dVHITBHiQxe31GeDq81otnIh3HBQN8_XjS1diHPq1tti1pn55eZdI5g
grant_type=authorization_code&
code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4&
client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-client-attestation&
client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6IjIyIn0.eyJpc3Mi[...omitted for brevity...].cC4hiUPo[...omitted for brevity...]
where the DPoP proof JWT decodes as follows: JOSE Header
{
"typ": "dpop+jwt",
"jwk" : {
"alg": "ES256",
"crv": "P-256",
"kty": "EC",
"x": "i8Qym74TMPuKAuJPiYs1RfUla5czcqzUhlJfDsLw7t4",
"y": "FB9TcffyVCHJEB2cz785161A4JleNHvpn8mxGFWY2Sc"
},
"alg": "ES256"
}
Payload
{
"jti": "35768297-dec5-46f6-85e5-b758216ab5ff",
"htm": "POST",
"htu": "https://as.example/token",
"iat": "1700812800",
"nonce": "eyJ7S_zG.eyJH0-Z.HX4w-7v"
} Note, that the DPoP proof JWT MUST contain the |
@ju-cu's description of how the DPoP proof JWT would serve as the client attestation PoP JWT is pretty much in line with how I'd envisioned it. Although I believe it'd need to be a bit less prescriptive about checking the confirmation/pop key and just say that the public key from the |
This conversation made me consider the following:
So, what if, instead of having an attestation specific specification, this work was divided into two parts.
Seems a bit more work, but the result is also much more general: a mechanism for client authentication using JWT assertions with proof-of-possession, independent of attestation. And by using the DPoP specification, the proof-of-possession part could be relatively easier to specify. If you think this is a conversation worth having, I can create an issue, since this isn't specifically related to this PR. |
Please see #67 for a concrete proposal to shift to using DPoP as the PoP syntax for this client authentication method. |
After giving it much thought, I realized that DPoP uses HTTP headers in HTTP requests, and consequently, it makes sense to obtain a nonce within the headers of the received HTTP responses. Meanwhile, the nonces we use in OAuth and for endpoint requests utilize GET or POST parameters, and the idea of forcibly using HTTP headers for nonce provisioning doesn't excite me. We already have a nonce endpoint in IETF literature, for example in ACME (RFC8555), and with the aim of creating something highly specialized, reusable in other contexts, efficient, and scalable, I thought of this: |
We had a discussion on this topic in today's editors call, I posted my thoughts here: #59 (comment) |
Closes #59
📑 Description
This PR adds server-provided nonces as a way to check the freshness of Client Attestation PoP JWT, in a similar way to what is done in DPoP (RFC 9449).
Preview Link
NA