7. Protected Resource Access
Requests to DPoP-protected resources MUST include both a DPoP proof as per Section 4 and the access token as described in Section 7.1. The DPoP proof MUST include the ath claim with a valid hash of the associated access token.
Binding the token value to the proof in this way prevents a proof to be used with multiple different access token values across different requests. For example, if a client holds tokens bound to two different resource owners, AT1 and AT2, and uses the same key when talking to the authorization server, it's possible that these tokens could be swapped. Without the ath field to bind it, a captured signature applied to AT1 could be replayed with AT2 instead, changing the rights and access of the intended request. This same substitution prevention remains for rotated access tokens within the same combination of client and resource owner -- a rotated token value would require the calculation of a new proof. This binding additionally ensures that a proof intended for use with the access token is not usable without an access token, or vice-versa.
The resource server is required to calculate the hash of the token value presented and verify that it is the same as the hash value in the ath field as described in Section 4.3. Since the ath field value is covered by the DPoP proof's signature, its inclusion binds the access token value to the holder of the key used to generate the signature.
Note that the ath field alone does not prevent replay of the DPoP proof or provide binding to the request in which the proof is presented, and it is still important to check the time window of the proof as well as the included message parameters, such as htm and htu.
7.1. The DPoP Authentication Scheme
A DPoP-bound access token is sent using the Authorization request header field per Section 11.6.2 of [RFC9110] with an authentication scheme of DPoP. The syntax of the Authorization header field for the DPoP scheme uses the token68 syntax defined in Section 11.2 of [RFC9110] for credentials and is repeated below for ease of reference. The ABNF notation syntax for DPoP authentication scheme credentials is as follows:
token68 = 1*( ALPHA / DIGIT /
"-" / "." / "_" / "~" / "+" / "/" ) *"="
credentials = "DPoP" 1*SP token68
Figure 12: DPoP Authentication Scheme ABNF
For such an access token, a resource server MUST check that a DPoP proof was also received in the DPoP header field of the HTTP request, check the DPoP proof according to the rules in Section 4.3, and check that the public key of the DPoP proof matches the public key to which the access token is bound per Section 6.
The resource server MUST NOT grant access to the resource unless all checks are successful.
Figure 13 shows an example request to a protected resource with a DPoP-bound access token in the Authorization header and the DPoP proof in the DPoP header. The example uses "" line wrapping per [RFC8792]. Figure 14 shows the decoded content of that DPoP proof. The JSON of the JWT header and payload are shown, but the signature part is omitted. As usual, line breaks and indentation are included for formatting and readability.
GET /protectedresource HTTP/1.1
Host: resource.example.org
Authorization: DPoP Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik\
VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR\
nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE\
QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiJlMWozVl9iS2ljOC1MQUVCIiwiaHRtIj\
oiR0VUIiwiaHR1IjoiaHR0cHM6Ly9yZXNvdXJjZS5leGFtcGxlLm9yZy9wcm90ZWN0Z\
WRyZXNvdXJjZSIsImlhdCI6MTU2MjI2MjYxOCwiYXRoIjoiZlVIeU8ycjJaM0RaNTNF\
c05yV0JiMHhXWG9hTnk1OUlpS0NBcWtzbVFFbyJ9.2oW9RP35yRqzhrtNP86L-Ey71E\
OptxRimPPToA1plemAgR6pxHF8y6-yqyVnmcw6Fy1dqd-jfxSYoMxhAJpLjA
Figure 13: DPoP-Protected Resource Request
{
"typ":"dpop+jwt",
"alg":"ES256",
"jwk": {
"kty":"EC",
"x":"l8tFrhx-34tV3hRICRDY9zCkDlpBhF42UQUfWVAWBFs",
"y":"9VE4jf_Ok_o64zbTTlcuNJajHmt6v9TDVrU0CdvGRDA",
"crv":"P-256"
}
}
.
{
"jti":"e1j3V_bKic8-LAEB",
"htm":"GET",
"htu":"https://resource.example.org/protectedresource",
"iat":1562262618,
"ath":"fUHyO2r2Z3DZ53EsNrWBb0xWXoaNy59IiKCAqksmQEo"
}
Figure 14: Decoded Content of the DPoP Proof JWT in Figure 13
Upon receipt of a request to a protected resource within the protection space requiring DPoP authentication, the server can respond with a challenge to the client to provide DPoP authentication information if the request does not include valid credentials or does not contain an access token sufficient for access. Such a challenge is made using the 401 (Unauthorized) response status code ([RFC9110], Section 15.5.2) and the WWW-Authenticate header field ([RFC9110], Section 11.6.1). The server MAY include the WWW-Authenticate header in response to other conditions as well.
In such challenges:
- The scheme name is DPoP.
- The authentication parameter realm MAY be included to indicate the scope of protection in the manner described in [RFC9110], Section 11.5.
- A scope authentication parameter MAY be included as defined in [RFC6750], Section 3.
- An error parameter ([RFC6750], Section 3) SHOULD be included to indicate the reason why the request was declined, if the request included an access token but failed authentication. The error parameter values described in [RFC6750], Section 3.1 are suitable, as are any appropriate values defined by extension. The value use_dpop_nonce can be used as described in Section 9 to signal that a nonce is needed in the DPoP proof of a subsequent request(s). Additionally, invalid_dpop_proof is used to indicate that the DPoP proof itself was deemed invalid based on the criteria of Section 4.3.
- An error_description parameter ([RFC6750], Section 3) MAY be included along with the error parameter to provide developers a human-readable explanation that is not meant to be displayed to end-users.
- An algs parameter SHOULD be included to signal to the client the JWS algorithms that are acceptable for the DPoP proof JWT. The value of the parameter is a space-delimited list of JWS alg (Algorithm) header values ([RFC7515], Section 4.1.1).
- Additional authentication parameters MAY be used, and unknown parameters MUST be ignored by recipients.
Figure 15 shows a response to a protected resource request without authentication.
HTTP/1.1 401 Unauthorized
WWW-Authenticate: DPoP algs="ES256 PS256"
Figure 15: HTTP 401 Response to a Protected Resource Request without
Authentication
Figure 16 shows a response to a protected resource request that was rejected due to the failed confirmation of the DPoP binding in the access token. Figure 16 uses "" line wrapping per [RFC8792].
HTTP/1.1 401 Unauthorized
WWW-Authenticate: DPoP error="invalid_token", \
error_description="Invalid DPoP key binding", algs="ES256"
Figure 16: HTTP 401 Response to a Protected Resource Request with
an Invalid Token
Note that browser-based client applications using Cross-Origin Resource Sharing (CORS) [WHATWG.Fetch] only have access to CORS-safelisted response HTTP headers by default. In order for the application to obtain and use the WWW-Authenticate HTTP response header value, the server needs to make it available to the application by including WWW-Authenticate in the Access-Control-Expose-Headers response header list value.
This authentication scheme is for origin-server authentication only. Therefore, this authentication scheme MUST NOT be used with the Proxy-Authenticate or Proxy-Authorization header fields.
Note that the syntax of the Authorization header field for this authentication scheme follows the usage of the Bearer scheme defined in Section 2.1 of [RFC6750]. While it is not the preferred credential syntax of [RFC9110], it is compatible with the general authentication framework therein and is used for consistency and familiarity with the Bearer scheme.
7.2. Compatibility with the Bearer Authentication Scheme
Protected resources simultaneously supporting both the DPoP and Bearer schemes need to update how the evaluation process is performed for bearer tokens to prevent downgraded usage of a DPoP-bound access token. Specifically, such a protected resource MUST reject a DPoP-bound access token received as a bearer token per [RFC6750].
Section 11.6.1 of [RFC9110] allows a protected resource to indicate support for multiple authentication schemes (i.e., Bearer and DPoP) with the WWW-Authenticate header field of a 401 (Unauthorized) response.
A protected resource that supports only [RFC6750] and is unaware of DPoP would most presumably accept a DPoP-bound access token as a bearer token (JWT [RFC7519] says to ignore unrecognized claims, Introspection [RFC7662] says that other parameters might be present while placing no functional requirements on their presence, and [RFC6750] is effectively silent on the content of the access token since it relates to validity). As such, a client can send a DPoP-bound access token using the Bearer scheme upon receipt of a WWW-Authenticate: Bearer challenge from a protected resource (or it can send a DPoP-bound access token if it has prior knowledge of the capabilities of the protected resource). The effect of this likely simplifies the logistics of phased upgrades to protected resources in their support DPoP or prolonged deployments of protected resources with mixed token type support.
If a protected resource supporting both Bearer and DPoP schemes elects to respond with multiple WWW-Authenticate challenges, attention should be paid to which challenge(s) should deliver the actual error information. It is RECOMMENDED that the following rules be adhered to:
-
If no authentication information has been included with the request, then the challenges SHOULD NOT include an error code or other error information, as per Section 3.1 of [RFC6750] (Figure 17).
-
If the mechanism used to attempt authentication could be established unambiguously, then the corresponding challenge SHOULD be used to deliver error information (Figure 18).
-
Otherwise, both Bearer and DPoP challenges MAY be used to deliver error information (Figure 19).
The following examples use "" line wrapping per [RFC8792].
GET /protectedresource HTTP/1.1
Host: resource.example.org
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer, DPoP algs="ES256 PS256"
Figure 17: HTTP 401 Response to a Protected Resource Request without
Authentication
GET /protectedresource HTTP/1.1
Host: resource.example.org
Authorization: Bearer INVALID_TOKEN
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="invalid_token", \
error_description="Invalid token", DPoP algs="ES256 PS256"
Figure 18: HTTP 401 Response to a Protected Resource Request with
Invalid Authentication
GET /protectedresource HTTP/1.1
Host: resource.example.org
Authorization: Bearer Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU
Authorization: DPoP Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU
HTTP/1.1 400 Bad Request
WWW-Authenticate: Bearer error="invalid_request", \
error_description="Multiple methods used to include access token", \
DPoP algs="ES256 PS256", error="invalid_request", \
error_description="Multiple methods used to include access token"
Figure 19: HTTP 400 Response to a Protected Resource Request with
Ambiguous Authentication
7.3. Client Considerations
Authorization including a DPoP proof may not be idempotent (depending on server enforcement of jti, iat, and nonce claims). Consequently, all previously idempotent requests for protected resources that were previously idempotent may no longer be idempotent. It is RECOMMENDED that clients generate a unique DPoP proof, even when retrying idempotent requests in response to HTTP errors generally understood as transient.
Clients that encounter frequent network errors may experience additional challenges when interacting with servers with stricter nonce validation implementations.