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

feat: initial proposal to use dpop #67

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 16 additions & 67 deletions draft-ietf-oauth-attestation-based-client-auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ normative:
RFC7519: RFC7519
RFC8414: RFC8414
RFC8725: RFC8725
RFC9449: RFC9449
informative:
RFC6749: RFC6749
RFC7521: RFC7521
Expand Down Expand Up @@ -85,17 +86,12 @@ The following steps describe this OAuth flow:

(4) The Client Backend responds to the Client Instance by sending the Client Attestation JWT.

(5) The Client Instance generates a Proof of Possession (PoP) with the Client Instance Key.
(5) The Client Instance generates a DPoP proof with the Client Instance Key.

(6) The Client Instance sends both the Client Attestation JWT and the Client Attestation PoP JWT to the authorization server, e.g. within a token request. The authorization server validates the Client Attestation and thus authenticates the Client Instance.
(6) The Client Instance sends both the Client Attestation JWT and the DPoP proof to the authorization server, e.g. within a token request. The authorization server validates the Client Attestation and thus authenticates the Client Instance.

Note that the protocol for steps (2) and (4) and how the Client Instance authenticates to the Client Backend is out of scope of this specification. Note also that this specification can be utilized without the client having a backend server at all; in this case, each client instance will perform the functions described as being done by the backend for itself.

This specification defines the format of the Client Attestation that a Client Instance uses to authenticate in its interactions with an authorization server, which is comprised of two key parts:

1. A Client Attestation JWT - typically produced by the client backend.
2. A Client Attestation Proof of Possession (PoP) - produced by the client instance.

# Conventions and Definitions

{::boilerplate bcp14-tagged}
Expand All @@ -105,9 +101,6 @@ This specification defines the format of the Client Attestation that a Client In
Client Attestation JWT:
: A JSON Web Token (JWT) generated by the client backend which is bound to a key managed by a client instance which can then be used by the instance for client authentication.

Client Attestation Proof of Possession (PoP) JWT:
: A Proof of Possession generated by the client instance using the key that the Client Attestation JWT is bound to.

Client Instance Key:
: A cryptographic, asymmetric key generated by the client instance and proven to the client backend. The public key is contained in the Client Attestation JWT and is used to sign the Client Attestation Proof of Possession.

Expand All @@ -117,31 +110,31 @@ To perform client authentication using this scheme, the client instance uses the

The value of the "client_assertion_type" parameter (as defined in {{RFC7521}}) set to "urn:ietf:params:oauth:client-assertion-type:jwt-client-attestation".

The value of the "client_assertion" parameter (as defined in {{RFC7521}}) set to a value containing two JWTs, separated by a '~' character. It MUST NOT contain more or less than precisely two JWTs separated by the '~' character. The first JWT MUST be the client attestation JWT defined in [](#client-attestation-jwt), the second JWT MUST be the client attestation PoP defined in [](#client-attestation-pop-jwt).
The value of the "client_assertion" parameter contains a single JWT known as the client attestation JWT as defined defined in [](#client-attestation-jwt). It MUST NOT contain more than one JWT.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the second sentence is necessary since it is implied by the former sentence.

Suggested change
The value of the "client_assertion" parameter contains a single JWT known as the client attestation JWT as defined defined in [](#client-attestation-jwt). It MUST NOT contain more than one JWT.
The value of the "client_assertion" parameter contains a single JWT known as the client attestation JWT as defined defined in [](#client-attestation-jwt).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we would want this constraint wouldn't we? Why would you like to remove it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't read your original comment just the suggestion, while I agree I think this makes the normative requirement a little more explicit. I took the language structure from RFC7523

The value of the "client_assertion" parameter contains a single JWT.
It MUST NOT contain more than one JWT.

I'm ok with removing this additional sentence though.


The request MUST also contain a DPoP HTTP Header (as defined in section 4.1 of {{RFC9449}}).

The following example demonstrates client authentication using this scheme during the presentation of an authorization code grant in an access token request (with extra line breaks for display purposes only):

~~~
POST /token HTTP/1.1
Host: as.example.com
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%3A
client-assertion-type%3Ajwt-client-attestation&
client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6IjIyIn0.
eyJpc3Mi[...omitted for brevity...].
cC4hiUPo[...omitted for brevity...]~eyJzI1NiIsImtphbGciOimtpZCI6IjIyIn0.
IjIyIn0[...omitted for brevity...].
iOiJSUzI1[...omitted for brevity...]
cC4hiUPo[...omitted for brevity...]
~~~

## JWT Format and Processing Requirements {#jwt-format-and-processing-requirements}
## Request Processing Requirements {#request-processing-requirements}

In order to authenticate the client using this scheme, the authorization server MUST validate BOTH the JWTs present in the "client_assertion" parameter according to the criteria below.
In order to authenticate the client using this scheme, the authorization server MUST validate BOTH the Client Attestation JWT present in the "client_assertion" parameter and the DPoP HTTP header according to the criteria below.

It is RECOMMENDED that the authorization server validate the Client Attestation JWT prior to validating the Client Attestation PoP.

### Client Attestation JWT {#client-attestation-jwt}

Expand All @@ -153,7 +146,7 @@ The following rules apply to validating the client attestation JWT. Application

3. The JWT MUST contain an "exp" (expiration time) claim that limits the time window during which the JWT can be used. The authorization server MUST reject any JWT with an expiration time that has passed, subject to allowable clock skew between systems.

4. The JWT MUST contain an "cnf" claim conforming {{RFC7800}} that conveys the key to be used for producing the client attestation pop for client authentication with an authorization server. The key MUST be expressed using the "jwk" representation.
4. The JWT MUST contain an "cnf" claim conforming to {{RFC7800}} that conveys the key to be used for producing the DPoP HTTP header for client authentication with an authorization server. The key MUST be expressed using the "jwk" representation.

5. The JWT MAY contain an "nbf" (not before) claim that identifies the time before which the token MUST NOT be accepted for processing.

Expand Down Expand Up @@ -190,53 +183,19 @@ The following example is the decoded header and payload of a JWT meeting the pro
}
~~~

### Client Attestation PoP JWT {#client-attestation-pop-jwt}

The following rules apply to validating the Client Attestation JWT. Application of additional restrictions and policy are at the discretion of the Authorization Server.

1. The JWT MUST contain an "iss" (issuer) claim with a value corresponding to the "client_id" of the OAuth client.

2. The JWT MUST contain an "exp" (expiration time) claim that limits the time window during which the JWT can be used. The authorization server MUST reject any JWT with an expiration time that has passed, subject to allowable clock skew between systems. Note that the authorization server may reject JWTs with an "exp" claim value that is unreasonably far in the future.

3. The JWT MUST contain a "jti" (JWT ID) claim that provides a unique identifier for the token. The authorization server MAY ensure that JWTs are not replayed by maintaining the set of used "jti" values for the length of time for which the JWT would be considered valid based on the applicable "exp" instant.

4. The JWT MUST contain an "aud" (audience) claim containing a value that identifies the authorization server as an intended audience. The {{RFC8414}} issuer identifier URL of the authorization server MUST be used as a value for an "aud" element to identify the authorization server as the intended audience of the JWT.

5. The JWT MAY contain an "nonce" claim containing a String value that is provided by the authorization server to associate the Client Attestation PoP JWT with a particular transaction and prevent replay attacks.

6. The JWT MAY contain an "nbf" (not before) claim that identifies the time before which the token MUST NOT be accepted for processing.

7. The JWT MAY contain an "iat" (issued at) claim that identifies the time at which the JWT was issued. Note that the authorization server may reject JWTs with an "iat" claim value that is unreasonably far in the past.

8. The JWT MAY contain other claims.

9. The JWT MUST be digitally signed using an asymmetric cryptographic algorithm. The authorization server MUST reject the JWT if it is using a Message Authentication Code (MAC) based algorithm. The authorization server MUST reject JWTs with an invalid signature.

10. The public key used to verify the JWT MUST be the key located in the "cnf" claim of the corresponding client attestation JWT.
### DPoP HTTP header

11. The authorization server MUST reject a JWT that is not valid in all other respects per "JSON Web Token (JWT)" {{RFC7519}}.
The following rules apply to validating the DPoP HTTP header. Application of additional restrictions and policy are at the discretion of the authorization server.

The following example is the decoded header and payload of a JWT meeting the processing rules as defined above.
1. The key represented in the JWK header parameter of the DPoP proof MUST match the key that is represented in the "cnf" claim of the Client Attestation JWT present in the "client_attestation" parameter.

~~~
{
"alg": "ES256"
}
.
{
"iss": "https://client.example.com",
"aud": "https://as.example.com",
"nbf":1300815780,
"exp":1300819380,
"jti": "d25d00ab-552b-46fc-ae19-98f440f25064"
}
~~~
2. The DPoP proof JWT present in the DPoP HTTP header MUST be valid in all other respects per the processing rules defined in {{RFC9449}}.

# Implementation Considerations

## Reuse of a Client Attestation JWT

Implementers should be aware that the design of this authentication mechanism deliberately allows for a client instance to re-use a single Client Attestation JWT in multiple interactions/requests with an authorization server, whilst producing a fresh Client Attestation PoP JWT. Client deployments should consider this when determining the validity period for issued Client Attestation JWTs as this ultimately controls how long a client instance can re-use a single Client Attestation JWT.
Implementers should be aware that the design of this authentication mechanism deliberately allows for a client instance to re-use a single Client Attestation JWT in multiple interactions/requests with an authorization server, whilst producing a fresh DPoP proof. Client deployments should consider this when determining the validity period for issued Client Attestation JWTs as this ultimately controls how long a client instance can re-use a single Client Attestation JWT.

## Refresh token binding

Expand All @@ -252,16 +211,6 @@ Implementers should be aware that using the same client attestation across multi

The guidance provided by {{RFC7519}} and {{RFC8725}} applies.

## Replay Attack Detection

The following mechanisms exist within this client authentication method in order to allow an authorization server to detect replay attacks for presented client attestation PoPs:

- The client uses "jti" (JWT ID) claims for the Client Attestation PoP JWT and the authorization server maintains a list of used (seen) "jti" values for the time of which the JWT would be considered valid based on the applicable "exp" claim. If any Client Attestation PoP JWT would be replayed, the authorization server would recognize the "jti" and respond with an authentication error.
- The authorization server provides a nonce for the particular transaction and the client uses it for the "nonce" claim in the Client Attestation PoP JWT. The authorization server validates that the nonce matches for the transaction. This approach may require an additional roundtrip in the protocol. The authorization server MUST ensure that the nonce provides sufficient entropy.
- The authorization server may expect the usage of a nonce in the Client Attestation PoP JWT, but instead of providing the nonce explicitly, the client may implicitly reuse an existing artefact, e.g. the authorization code. The authorization server MUST ensure that the nonce provides sufficient entropy.

The approach using a nonce explicitly provided by the authorization server gives stronger replay attack detection guarantees, however support by the authorization server is OPTIONAL to simplify mandatory implementation requirements. The "jti" method is mandatory and hence acts as a default fallback.

# Appendix A IANA Considerations

## Sub-Namespace Registration of urn:ietf:params:oauth:client-assertion-type:jwt-client-attestation
Expand Down