Skip to content

Commit 05670e6

Browse files
authored
Merge pull request #90 from oauth-wg/c2bo/proposed-format
Restructure text and add alternative representation
2 parents 52766bc + 8417c2c commit 05670e6

File tree

1 file changed

+140
-58
lines changed

1 file changed

+140
-58
lines changed

draft-ietf-oauth-attestation-based-client-auth.md

Lines changed: 140 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ author:
2727

2828
normative:
2929
RFC3986: RFC3986
30-
RFC7800: RFC7800
3130
RFC7591: RFC7591
3231
RFC7519: RFC7519
32+
RFC7800: RFC7800
3333
RFC8414: RFC8414
3434
RFC8725: RFC8725
3535
RFC9110: RFC9110
@@ -41,8 +41,10 @@ normative:
4141
target: "https://www.iana.org/assignments/http-fields/http-fields.xhtml"
4242
informative:
4343
RFC6749: RFC6749
44+
RFC7523: RFC7523
4445
ARF:
4546
title: "The European Digital Identity Wallet Architecture and Reference Framework"
47+
SD-JWT: I-D.ietf-oauth-selective-disclosure-jwt
4648

4749

4850
--- abstract
@@ -118,56 +120,9 @@ Client Instance:
118120
Client Instance Key:
119121
: A cryptographic asymmetric key pair that is generated by the Client Instance where the public key of the key pair is provided to the client backend. This public key is then encapsulated within the Client Attestation JWT and is utilized to sign the Client Attestation Proof of Possession.
120122

121-
# Client Attestation
122-
123-
This draft introduces the concept of client attestations to the OAuth 2 protocol, using two JWTs: a Client Attestation and a Client Attestation Proof of Possession (PoP). These JWTs are transmitted via HTTP headers in an HTTP request from a Client Instance to an Authorization Server or Resource Server. The primary purpose of these headers is to authenticate the Client Instance.
124-
125-
## Client Attestation HTTP Headers {#headers}
126-
127-
A Client Attestation JWT and Client Attestation PoP JWT is included in an HTTP request using the following request header fields.
128-
129-
OAuth-Client-Attestation:
130-
: A JWT that conforms to the structure and syntax as defined in [](#client-attestation-jwt)
131-
132-
OAuth-Client-Attestation-PoP:
133-
: A JWT that adheres to the structure and syntax as defined in [](#client-attestation-pop-jwt)
134-
135-
The following is an example of the OAuth-Client-Attestation header.
136-
137-
~~~
138-
OAuth-Client-Attestation: eyJhbGciOiAiRVMyNTYiLCJraWQiOiAiMTEifQ.eyJ\
139-
pc3MiOiJodHRwczovL2NsaWVudC5leGFtcGxlLmNvbSIsInN1YiI6Imh0dHBzOi8vY2x\
140-
pZW50LmV4YW1wbGUuY29tIiwibmJmIjoxMzAwODE1NzgwLCJleHAiOjEzMDA4MTkzODA\
141-
sImNuZiI6eyJqd2siOnsia3R5IjoiRUMiLCJ1c2UiOiJzaWciLCJjcnYiOiJQLTI1NiI\
142-
sIngiOiIxOHdITGVJZ1c5d1ZONlZEMVR4Z3BxeTJMc3pZa01mNko4bmpWQWlidmhNIiw\
143-
ieSI6Ii1WNGRTNFVhTE1nUF80Zlk0ajhpcjdjbDFUWGxGZEFnY3g1NW83VGtjU0EifX1\
144-
9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
145-
~~~
146-
147-
The following is an example of the OAuth-Client-Attestation-PoP header.
148-
149-
~~~
150-
OAuth-Client-Attestation-PoP: eyJhbGciOiJFUzI1NiJ9.ewogICJpc3MiOiAia\
151-
HR0cHM6Ly9jbGllbnQuZXhhbXBsZS5jb20iLAogICJhdWQiOiAi\aHR0cHM6Ly9hcy5l\
152-
eGFtcGxlLmNvbSIsCiAgIm5iZiI6MTMwMDgxNTc4MCwKICAiZXhwIjoxMzAwODE5Mzgw\
153-
LAogICJqdGkiOiAiZDI1ZDAwYWItNTUyYi00NmZjLWFlMTktOThmNDQwZjI1MDY0IiwK\
154-
ICAibm9uY2UiIDogIjVjMWE5ZTEwLTI5ZmYtNGMyYi1hZTczLTU3YzA5NTdjMDljNCIK\
155-
fQ.coB_mtdXwvi9RxSMzbIey8GVVQLv9qQrBUqmc1qj9Bs
156-
~~~
157-
158-
Note that per {{RFC9110}} header field names are case-insensitive; so OAUTH-CLIENT-ATTESTATION, oauth-client-attestation, etc., are all valid and equivalent
159-
header field names. Case is significant in the header field value, however.
123+
# Client Attestation Format
160124

161-
The OAuth-Client-Attestation and OAuth-Client-Attestation-PoP HTTP header field values uses the token68 syntax defined in Section 11.2 of {{RFC9110}} (repeated below for ease of reference).
162-
163-
~~~
164-
OAuth-Client-Attestation = token68
165-
OAuth-Client-Attestation-PoP = token68
166-
token68 = 1*( ALPHA / DIGIT / "-" / "." /
167-
"_" / "~" / "+" / "/" ) *"="
168-
~~~
169-
170-
It is RECOMMENDED that the authorization server validate the Client Attestation JWT prior to validating the Client Attestation PoP.
125+
This draft introduces the concept of client attestations to the OAuth 2 protocol, using two JWTs: a Client Attestation and a Client Attestation Proof of Possession (PoP). The primary purpose of these JWTs is to authenticate the Client Instance. These JWTs can be transmitted via HTTP headers in an HTTP request (as described in [](#headers)) from a Client Instance to an Authorization Server or Resource Server, or via a concatenated serialization (as described in [](#alternative-representation)) to enable usage outside of the traditional OAuth2 ecosystem .
171126

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

@@ -259,15 +214,66 @@ The following example is the decoded header and payload of a JWT meeting the pro
259214
}
260215
~~~
261216

262-
## Checking HTTP requests feature client attestations {#checking-http-requests-with-client-attestations}
217+
# Client Attestation using a Header based syntax
218+
219+
The following section defines how a Client Attestation can be provided in an HTTP request using HTTP headers.
220+
221+
## Client Attestation HTTP Headers {#headers}
222+
223+
A Client Attestation JWT and Client Attestation PoP JWT can be included in an HTTP request using the following request header fields.
224+
225+
OAuth-Client-Attestation:
226+
: A JWT that conforms to the structure and syntax as defined in [](#client-attestation-jwt)
227+
228+
OAuth-Client-Attestation-PoP:
229+
: A JWT that adheres to the structure and syntax as defined in [](#client-attestation-pop-jwt)
230+
231+
The following is an example of the OAuth-Client-Attestation header.
232+
233+
~~~
234+
OAuth-Client-Attestation: eyJhbGciOiAiRVMyNTYiLCJraWQiOiAiMTEifQ.eyJ\
235+
pc3MiOiJodHRwczovL2NsaWVudC5leGFtcGxlLmNvbSIsInN1YiI6Imh0dHBzOi8vY2x\
236+
pZW50LmV4YW1wbGUuY29tIiwibmJmIjoxMzAwODE1NzgwLCJleHAiOjEzMDA4MTkzODA\
237+
sImNuZiI6eyJqd2siOnsia3R5IjoiRUMiLCJ1c2UiOiJzaWciLCJjcnYiOiJQLTI1NiI\
238+
sIngiOiIxOHdITGVJZ1c5d1ZONlZEMVR4Z3BxeTJMc3pZa01mNko4bmpWQWlidmhNIiw\
239+
ieSI6Ii1WNGRTNFVhTE1nUF80Zlk0ajhpcjdjbDFUWGxGZEFnY3g1NW83VGtjU0EifX1\
240+
9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
241+
~~~
242+
243+
The following is an example of the OAuth-Client-Attestation-PoP header.
244+
245+
~~~
246+
OAuth-Client-Attestation-PoP: eyJhbGciOiJFUzI1NiJ9.ewogICJpc3MiOiAia\
247+
HR0cHM6Ly9jbGllbnQuZXhhbXBsZS5jb20iLAogICJhdWQiOiAiaHR0cHM6Ly9hcy5le\
248+
GFtcGxlLmNvbSIsCiAgIm5iZiI6MTMwMDgxNTc4MCwKICAiZXhwIjoxMzAwODE5MzgwL\
249+
AogICJqdGkiOiAiZDI1ZDAwYWItNTUyYi00NmZjLWFlMTktOThmNDQwZjI1MDY0IiwKI\
250+
CAibm9uY2UiIDogIjVjMWE5ZTEwLTI5ZmYtNGMyYi1hZTczLTU3YzA5NTdjMDljNCIKf\
251+
Q.coB_mtdXwvi9RxSMzbIey8GVVQLv9qQrBUqmc1qj9Bs
252+
~~~
253+
254+
Note that per {{RFC9110}} header field names are case-insensitive; so OAUTH-CLIENT-ATTESTATION, oauth-client-attestation, etc., are all valid and equivalent
255+
header field names. Case is significant in the header field value, however.
256+
257+
The OAuth-Client-Attestation and OAuth-Client-Attestation-PoP HTTP header field values uses the token68 syntax defined in Section 11.2 of {{RFC9110}} (repeated below for ease of reference).
258+
259+
~~~
260+
OAuth-Client-Attestation = token68
261+
OAuth-Client-Attestation-PoP = token68
262+
token68 = 1*( ALPHA / DIGIT / "-" / "." /
263+
"_" / "~" / "+" / "/" ) *"="
264+
~~~
265+
266+
It is RECOMMENDED that the authorization server validate the Client Attestation JWT prior to validating the Client Attestation PoP.
267+
268+
## Validating HTTP requests feature client attestations {#checking-http-requests-with-client-attestations}
263269

264270
To validate an HTTP request which contains the client attestation headers, the receiving server MUST ensure the following with regard to a received HTTP request:
265271

266272
1. There is precisely one OAuth-Client-Attestation HTTP request header field, where its value is a single well-formed JWT conforming to the syntax outlined in []{client-attestation-jwt}.
267-
2. There is precisely one OAuth-Client-Attestation-PoP HTTP request header field, where its value is a single well-formed JWT conforming to the syntax outlined in []{client-attestation-pop-jwt}.
273+
2. There is precisely one OAuth-Client-Attestation-PoP HTTP request header field, where its value is a single well-formed JWT conforming to the syntax outlined in [](client-attestation-pop-jwt).
268274
3. The signature of the Client Attestation PoP JWT obtained from the OAuth-Client-Attestation-PoP HTTP header verifies with the Client Instance Key contained in the `cnf` claim of the Client Attestation JWT obtained from the OAuth-Client-Attestation HTTP header.
269275

270-
# Client Attestation at the Token Endpoint
276+
## Client Attestation at the Token Endpoint {#token-endpoint}
271277

272278
While usage of the the client attestation mechanism defined by this draft can be used in a variety of different HTTP requests to different endpoints, usage within the token request as defined by {{RFC6749}} has particular additional considerations outlined below.
273279

@@ -287,16 +293,90 @@ sIngiOiIxOHdITGVJZ1c5d1ZONlZEMVR4Z3BxeTJMc3pZa01mNko4bmpWQWlidmhNIiw\
287293
ieSI6Ii1WNGRTNFVhTE1nUF80Zlk0ajhpcjdjbDFUWGxGZEFnY3g1NW83VGtjU0EifX1\
288294
9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
289295
OAuth-Client-Attestation-PoP: eyJhbGciOiJFUzI1NiJ9.ewogICJpc3MiOiAia\
290-
HR0cHM6Ly9jbGllbnQuZXhhbXBsZS5jb20iLAogICJhdWQiOiAi\aHR0cHM6Ly9hcy5l\
291-
eGFtcGxlLmNvbSIsCiAgIm5iZiI6MTMwMDgxNTc4MCwKICAiZXhwIjoxMzAwODE5Mzgw\
292-
LAogICJqdGkiOiAiZDI1ZDAwYWItNTUyYi00NmZjLWFlMTktOThmNDQwZjI1MDY0IiwK\
293-
ICAibm9uY2UiIDogIjVjMWE5ZTEwLTI5ZmYtNGMyYi1hZTczLTU3YzA5NTdjMDljNCIK\
294-
fQ.coB_mtdXwvi9RxSMzbIey8GVVQLv9qQrBUqmc1qj9Bs
296+
HR0cHM6Ly9jbGllbnQuZXhhbXBsZS5jb20iLAogICJhdWQiOiAiaHR0cHM6Ly9hcy5le\
297+
GFtcGxlLmNvbSIsCiAgIm5iZiI6MTMwMDgxNTc4MCwKICAiZXhwIjoxMzAwODE5MzgwL\
298+
AogICJqdGkiOiAiZDI1ZDAwYWItNTUyYi00NmZjLWFlMTktOThmNDQwZjI1MDY0IiwKI\
299+
CAibm9uY2UiIDogIjVjMWE5ZTEwLTI5ZmYtNGMyYi1hZTczLTU3YzA5NTdjMDljNCIKf\
300+
Q.coB_mtdXwvi9RxSMzbIey8GVVQLv9qQrBUqmc1qj9Bs
295301

296302
grant_type=authorization_code&
297303
code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4
298304
~~~
299305

306+
## Client Attestation at the PAR Endpoint {#par-endpoint}
307+
308+
A Client Attestation can be used at the PAR endpoint instead of alternative client authentication mechanisms like JWT client assertion-based authentication (as defined in Section 2.2 of [RFC7523]).
309+
310+
The Authorization Server MUST perform all of the checks outlined in [](#checking-http-requests-with-client-attestations) for a received PAR request which is making use of the client attestation mechanism as defined by this draft.
311+
312+
The following example demonstrates usage of the client attestation mechanism in a PAR request (with extra line breaks for display purposes only):
313+
314+
~~~
315+
POST /as/par HTTP/1.1
316+
Host: as.example.com
317+
Content-Type: application/x-www-form-urlencoded
318+
OAuth-Client-Attestation: eyJhbGciOiAiRVMyNTYiLCJraWQiOiAiMTEifQ.eyJ\
319+
pc3MiOiJodHRwczovL2NsaWVudC5leGFtcGxlLmNvbSIsInN1YiI6Imh0dHBzOi8vY2x\
320+
pZW50LmV4YW1wbGUuY29tIiwibmJmIjoxMzAwODE1NzgwLCJleHAiOjEzMDA4MTkzODA\
321+
sImNuZiI6eyJqd2siOnsia3R5IjoiRUMiLCJ1c2UiOiJzaWciLCJjcnYiOiJQLTI1NiI\
322+
sIngiOiIxOHdITGVJZ1c5d1ZONlZEMVR4Z3BxeTJMc3pZa01mNko4bmpWQWlidmhNIiw\
323+
ieSI6Ii1WNGRTNFVhTE1nUF80Zlk0ajhpcjdjbDFUWGxGZEFnY3g1NW83VGtjU0EifX1\
324+
9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
325+
OAuth-Client-Attestation-PoP: eyJhbGciOiJFUzI1NiJ9.ewogICJpc3MiOiAia\
326+
HR0cHM6Ly9jbGllbnQuZXhhbXBsZS5jb20iLAogICJhdWQiOiAiaHR0cHM6Ly9hcy5le\
327+
GFtcGxlLmNvbSIsCiAgIm5iZiI6MTMwMDgxNTc4MCwKICAiZXhwIjoxMzAwODE5MzgwL\
328+
AogICJqdGkiOiAiZDI1ZDAwYWItNTUyYi00NmZjLWFlMTktOThmNDQwZjI1MDY0IiwKI\
329+
CAibm9uY2UiIDogIjVjMWE5ZTEwLTI5ZmYtNGMyYi1hZTczLTU3YzA5NTdjMDljNCIKf\
330+
Q.coB_mtdXwvi9RxSMzbIey8GVVQLv9qQrBUqmc1qj9Bs
331+
332+
response_type=code&state=af0ifjsldkj&client_id=s6BhdRkqt3
333+
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
334+
&code_challenge=K2-ltc83acc4h0c9w6ESC_rEMTJ3bww-uCHaoeK1t8U
335+
&code_challenge_method=S256&scope=account-information
336+
~~~
337+
338+
# Concatenated Serialization for Client Attestations {#alternative-representation}
339+
340+
A Client Attestation according to this specification MAY be presented using an alternative representation for cases where the header-based mechanism (as introduced in introduced in [](#headers) does not fit the underlying protocols, e.g., for direct calls to Browser APIs.
341+
In those cases, a concatenated serialization of the Client Attestation and Client Attestation PoP can can be used.
342+
343+
## Concatenated Serialization Format {#format-alternative}
344+
345+
This representation is created by concatenating Client Attestation and Client Attestation PoP separated by a tilde ('~') character:
346+
347+
~~~
348+
<Client Attestation>~<Client Attestation PoP>
349+
~~~
350+
351+
This form is similar to an SD-JWT+KB according to Section 5 of {{SD-JWT}} but does not include Disclosures, uses different typ values and does not include the `sd_hash` claim in the PoP.
352+
353+
This concatenated serialization form allows a the presentation of a Client Attestation and Client Attestation PoP for cases where a header-based approach is unavailable, e.g., to establish trust in a client when using a direct Browser API call.
354+
355+
The following is an example of such a concatenated serialization (with extra line breaks for display purposes only):
356+
357+
~~~
358+
eyJhbGciOiAiRVMyNTYiLCJraWQiOiAiMTEifQ.eyJpc3MiOiJodHRwczovL2NsaWVud\
359+
C5leGFtcGxlLmNvbSIsInN1YiI6Imh0dHBzOi8vY2xpZW50LmV4YW1wbGUuY29tIiwib\
360+
mJmIjoxMzAwODE1NzgwLCJleHAiOjEzMDA4MTkzODAsImNuZiI6eyJqd2siOnsia3R5I\
361+
joiRUMiLCJ1c2UiOiJzaWciLCJjcnYiOiJQLTI1NiIsIngiOiIxOHdITGVJZ1c5d1ZON\
362+
lZEMVR4Z3BxeTJMc3pZa01mNko4bmpWQWlidmhNIiwieSI6Ii1WNGRTNFVhTE1nUF80Z\
363+
lk0ajhpcjdjbDFUWGxGZEFnY3g1NW83VGtjU0EifX19.SflKxwRJSMeKKF2QT4fwpMeJ\
364+
f36POk6yJV_adQssw5c~eyJhbGciOiJFUzI1NiJ9.ewogICJpc3MiOiAiaHR0cHM6Ly9\
365+
jbGllbnQuZXhhbXBsZS5jb20iLAogICJhdWQiOiAiaHR0cHM6Ly9hcy5leGFtcGxlLmN\
366+
vbSIsCiAgIm5iZiI6MTMwMDgxNTc4MCwKICAiZXhwIjoxMzAwODE5MzgwLAogICJqdGk\
367+
iOiAiZDI1ZDAwYWItNTUyYi00NmZjLWFlMTktOThmNDQwZjI1MDY0IiwKICAibm9uY2U\
368+
iIDogIjVjMWE5ZTEwLTI5ZmYtNGMyYi1hZTczLTU3YzA5NTdjMDljNCIKfQ.coB_mtdX\
369+
wvi9RxSMzbIey8GVVQLv9qQrBUqmc1qj9Bs
370+
~~~
371+
372+
## Validating the Concatenated Serialization {#validate-alternative}
373+
374+
To validate a client attestation using the concatenated serialization form, the receiving server MUST ensure the following:
375+
376+
1. Before the '~' character, there exists precisely a single well-formed JWT conforming to the syntax outlined in [](client-attestation-jwt).
377+
2. After the '~' character, there exists precisely a single well-formed JWT conforming to the syntax outlined in [](client-attestation-pop-jwt).
378+
3. The signature of the Client Attestation PoP JWT obtained after the '~' character verifies with the Client Instance Key contained in the `cnf` claim of the Client Attestation JWT obtained before the '~' character.
379+
300380
# Implementation Considerations
301381

302382
## Reuse of a Client Attestation JWT
@@ -396,6 +476,8 @@ This non-normative example shows a client attestations used as an wallet instanc
396476

397477
-04
398478

479+
* add concatenated representation without headers
480+
* add PAR endpoint example
399481
* fix PoP examples to include jti and nonce
400482
* add iana http field name registration
401483

0 commit comments

Comments
 (0)