├── .editorconfig ├── .github ├── CODEOWNERS └── workflows │ ├── LICENSE.md │ ├── archive.yml │ ├── ghpages.yml │ ├── publish.yml │ └── update.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── Makefile ├── README.md └── draft-ietf-oauth-attestation-based-client-auth.md /.editorconfig: -------------------------------------------------------------------------------- 1 | # See http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*.{md,xml,org}] 6 | charset = utf-8 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Automatically generated CODEOWNERS 2 | # Regenerate with `make update-codeowners` 3 | draft-ietf-oauth-attestation-based-client-auth.md tobias.looker@mattr.global paul.bastian@bdr.de chris.bormann@gmx.de 4 | -------------------------------------------------------------------------------- /.github/workflows/LICENSE.md: -------------------------------------------------------------------------------- 1 | This project is in the public domain. 2 | -------------------------------------------------------------------------------- /.github/workflows/archive.yml: -------------------------------------------------------------------------------- 1 | name: "Archive Issues and Pull Requests" 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * 0,2,4' 6 | repository_dispatch: 7 | types: [archive] 8 | workflow_dispatch: 9 | inputs: 10 | archive_full: 11 | description: 'Recreate the archive from scratch' 12 | default: false 13 | type: boolean 14 | 15 | jobs: 16 | build: 17 | name: "Archive Issues and Pull Requests" 18 | runs-on: ubuntu-latest 19 | permissions: 20 | contents: write 21 | steps: 22 | - name: "Checkout" 23 | uses: actions/checkout@v4 24 | 25 | # Note: No caching for this build! 26 | 27 | - name: "Update Archive" 28 | uses: martinthomson/i-d-template@v1 29 | env: 30 | ARCHIVE_FULL: ${{ inputs.archive_full }} 31 | with: 32 | make: archive 33 | token: ${{ github.token }} 34 | 35 | - name: "Update GitHub Pages" 36 | uses: martinthomson/i-d-template@v1 37 | with: 38 | make: gh-archive 39 | token: ${{ github.token }} 40 | 41 | - name: "Save Archive" 42 | uses: actions/upload-artifact@v4 43 | with: 44 | path: archive.json 45 | -------------------------------------------------------------------------------- /.github/workflows/ghpages.yml: -------------------------------------------------------------------------------- 1 | name: "Update Editor's Copy" 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - README.md 7 | - CONTRIBUTING.md 8 | - LICENSE.md 9 | - .gitignore 10 | pull_request: 11 | paths-ignore: 12 | - README.md 13 | - CONTRIBUTING.md 14 | - LICENSE.md 15 | - .gitignore 16 | 17 | jobs: 18 | build: 19 | name: "Update Editor's Copy" 20 | runs-on: ubuntu-latest 21 | permissions: 22 | contents: write 23 | steps: 24 | - name: "Checkout" 25 | uses: actions/checkout@v4 26 | 27 | - name: "Setup" 28 | id: setup 29 | run: date -u "+date=%FT%T" >>"$GITHUB_OUTPUT" 30 | 31 | - name: "Caching" 32 | uses: actions/cache@v4 33 | with: 34 | path: | 35 | .refcache 36 | .venv 37 | .gems 38 | node_modules 39 | .targets.mk 40 | key: i-d-${{ steps.setup.outputs.date }} 41 | restore-keys: i-d- 42 | 43 | - name: "Build Drafts" 44 | uses: martinthomson/i-d-template@v1 45 | with: 46 | token: ${{ github.token }} 47 | 48 | - name: "Update GitHub Pages" 49 | uses: martinthomson/i-d-template@v1 50 | if: ${{ github.event_name == 'push' }} 51 | with: 52 | make: gh-pages 53 | token: ${{ github.token }} 54 | 55 | - name: "Archive Built Drafts" 56 | uses: actions/upload-artifact@v4 57 | with: 58 | path: | 59 | draft-*.html 60 | draft-*.txt 61 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: "Publish New Draft Version" 2 | 3 | on: 4 | push: 5 | tags: 6 | - "draft-*" 7 | workflow_dispatch: 8 | inputs: 9 | email: 10 | description: "Submitter email" 11 | default: "" 12 | type: string 13 | 14 | jobs: 15 | build: 16 | name: "Publish New Draft Version" 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: "Checkout" 20 | uses: actions/checkout@v4 21 | 22 | # See https://github.com/actions/checkout/issues/290 23 | - name: "Get Tag Annotations" 24 | run: git fetch -f origin ${{ github.ref }}:${{ github.ref }} 25 | 26 | - name: "Setup" 27 | id: setup 28 | run: date -u "+date=%FT%T" >>"$GITHUB_OUTPUT" 29 | 30 | - name: "Caching" 31 | uses: actions/cache@v4 32 | with: 33 | path: | 34 | .refcache 35 | .venv 36 | .gems 37 | node_modules 38 | .targets.mk 39 | key: i-d-${{ steps.setup.outputs.date }} 40 | restore-keys: i-d- 41 | 42 | - name: "Build Drafts" 43 | uses: martinthomson/i-d-template@v1 44 | with: 45 | token: ${{ github.token }} 46 | 47 | - name: "Upload to Datatracker" 48 | uses: martinthomson/i-d-template@v1 49 | with: 50 | make: upload 51 | env: 52 | UPLOAD_EMAIL: ${{ inputs.email }} 53 | 54 | - name: "Archive Submitted Drafts" 55 | uses: actions/upload-artifact@v4 56 | with: 57 | path: "versioned/draft-*-[0-9][0-9].*" 58 | -------------------------------------------------------------------------------- /.github/workflows/update.yml: -------------------------------------------------------------------------------- 1 | name: "Update Generated Files" 2 | # This rule is not run automatically. 3 | # It can be run manually to update all of the files that are part 4 | # of the template, specifically: 5 | # - README.md 6 | # - CONTRIBUTING.md 7 | # - .note.xml 8 | # - .github/CODEOWNERS 9 | # - Makefile 10 | # 11 | # 12 | # This might be useful if you have: 13 | # - added, removed, or renamed drafts (including after adoption) 14 | # - added, removed, or changed draft editors 15 | # - changed the title of drafts 16 | # 17 | # Note that this removes any customizations you have made to 18 | # the affected files. 19 | on: workflow_dispatch 20 | 21 | jobs: 22 | build: 23 | name: "Update Files" 24 | runs-on: ubuntu-latest 25 | steps: 26 | - name: "Checkout" 27 | uses: actions/checkout@v4 28 | 29 | - name: "Update Generated Files" 30 | uses: martinthomson/i-d-template@v1 31 | with: 32 | make: update-files 33 | token: ${{ github.token }} 34 | 35 | - name: "Push Update" 36 | run: git push 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.pdf 3 | *.redxml 4 | *.swp 5 | *.txt 6 | *.upload 7 | *~ 8 | .tags 9 | /*-[0-9][0-9].xml 10 | /.*.mk 11 | /.gems/ 12 | /.refcache 13 | /.targets.mk 14 | /.venv/ 15 | /.vscode/ 16 | /lib 17 | /node_modules/ 18 | /versioned/ 19 | Gemfile.lock 20 | archive.json 21 | draft-ietf-oauth-attestation-based-client-auth.xml 22 | package-lock.json 23 | report.xml 24 | !requirements.txt 25 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | This repository relates to activities in the Internet Engineering Task Force 4 | ([IETF](https://www.ietf.org/)). All material in this repository is considered 5 | Contributions to the IETF Standards Process, as defined in the intellectual 6 | property policies of IETF currently designated as 7 | [BCP 78](https://www.rfc-editor.org/info/bcp78), 8 | [BCP 79](https://www.rfc-editor.org/info/bcp79) and the 9 | [IETF Trust Legal Provisions (TLP) Relating to IETF Documents](http://trustee.ietf.org/trust-legal-provisions.html). 10 | 11 | Any edit, commit, pull request, issue, comment or other change made to this 12 | repository constitutes Contributions to the IETF Standards Process 13 | (https://www.ietf.org/). 14 | 15 | You agree to comply with all applicable IETF policies and procedures, including, 16 | BCP 78, 79, the TLP, and the TLP rules regarding code components (e.g. being 17 | subject to a Simplified BSD License) in Contributions. 18 | 19 | 20 | ## Working Group Information 21 | 22 | Discussion of this work occurs on the [Web Authorization Protocol 23 | Working Group mailing list](mailto:oauth@ietf.org) 24 | ([archive](https://mailarchive.ietf.org/arch/browse/oauth/), 25 | [subscribe](https://www.ietf.org/mailman/listinfo/oauth)). 26 | In addition to contributions in GitHub, you are encouraged to participate in 27 | discussions there. 28 | 29 | **Note**: Some working groups adopt a policy whereby substantive discussion of 30 | technical issues needs to occur on the mailing list. 31 | 32 | You might also like to familiarize yourself with other 33 | [Working Group documents](https://datatracker.ietf.org/wg/oauth/documents/). 34 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | See the 4 | [guidelines for contributions](https://github.com/oauth-wg/draft-ietf-oauth-attestation-based-client-auth/blob/main/CONTRIBUTING.md). 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | LIBDIR := lib 2 | include $(LIBDIR)/main.mk 3 | 4 | $(LIBDIR)/main.mk: 5 | ifneq (,$(shell grep "path *= *$(LIBDIR)" .gitmodules 2>/dev/null)) 6 | git submodule sync 7 | git submodule update --init 8 | else 9 | ifneq (,$(wildcard $(ID_TEMPLATE_HOME))) 10 | ln -s "$(ID_TEMPLATE_HOME)" $(LIBDIR) 11 | else 12 | git clone -q --depth 10 -b main \ 13 | https://github.com/martinthomson/i-d-template $(LIBDIR) 14 | endif 15 | endif 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OAuth 2.0 Attestation-Based Client Authentication 2 | 3 | This is the working area for the IETF [OAUTH Working Group](https://datatracker.ietf.org/group/oauth/documents/) Internet-Draft, "OAuth 2.0 Attestation-Based Client Authentication". 4 | 5 | * [Editor's Copy](https://oauth-wg.github.io/draft-ietf-oauth-attestation-based-client-auth/#go.draft-ietf-oauth-attestation-based-client-auth.html) 6 | * [Datatracker Page](https://datatracker.ietf.org/doc/draft-ietf-oauth-attestation-based-client-auth) 7 | * [Working Group Draft](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-attestation-based-client-auth) 8 | * [Compare Editor's Copy to Working Group Draft](https://oauth-wg.github.io/draft-ietf-oauth-attestation-based-client-auth/#go.draft-ietf-oauth-attestation-based-client-auth.diff) 9 | 10 | 11 | ## Contributing 12 | 13 | See the 14 | [guidelines for contributions](https://github.com/oauth-wg/draft-ietf-oauth-attestation-based-client-auth/blob/main/CONTRIBUTING.md). 15 | 16 | Contributions can be made by creating pull requests. 17 | The GitHub interface supports creating pull requests using the Edit (✏) button. 18 | 19 | 20 | ## Command Line Usage 21 | 22 | Formatted text and HTML versions of the draft can be built using `make`. 23 | 24 | ```sh 25 | $ make 26 | ``` 27 | 28 | Command line usage requires that you have the necessary software installed. See 29 | [the instructions](https://github.com/martinthomson/i-d-template/blob/main/doc/SETUP.md). 30 | 31 | ## Keys for examples 32 | 33 | 34 | ``` 35 | -----BEGIN PUBLIC KEY----- 36 | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEVs/o5+uQbTjL3chynL4wXgUg2R9 37 | q9UU8I5mEovUf86QZ7kOBIjJwqnzD1omageEHWwHdBO6B+dFabmdT9POxg== 38 | -----END PUBLIC KEY----- 39 | ``` 40 | 41 | ``` 42 | -----BEGIN PRIVATE KEY----- 43 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgevZzL1gdAFr88hb2 44 | OF/2NxApJCzGCEDdfSp6VQO30hyhRANCAAQRWz+jn65BtOMvdyHKcvjBeBSDZH2r 45 | 1RTwjmYSi9R/zpBnuQ4EiMnCqfMPWiZqB4QdbAd0E7oH50VpuZ1P087G 46 | -----END PRIVATE KEY----- 47 | ``` 48 | -------------------------------------------------------------------------------- /draft-ietf-oauth-attestation-based-client-auth.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "OAuth 2.0 Attestation-Based Client Authentication" 3 | category: info 4 | lang: en 5 | 6 | docname: draft-ietf-oauth-attestation-based-client-auth-latest 7 | submissiontype: IETF # also: "IETF", "IAB", or "IRTF" 8 | area: "Security" 9 | workgroup: "Web Authorization Protocol" 10 | ipr: trust200902 11 | 12 | number: 13 | date: 14 | v: 3 15 | venue: 16 | group: "Web Authorization Protocol" 17 | type: "Working Group" 18 | mail: "oauth@ietf.org" 19 | arch: "https://mailarchive.ietf.org/arch/browse/oauth/" 20 | github: "oauth-wg/draft-ietf-oauth-attestation-based-client-auth" 21 | latest: "https://oauth-wg.github.io/draft-ietf-oauth-attestation-based-client-auth/draft-ietf-oauth-attestation-based-client-auth.html" 22 | 23 | author: 24 | - 25 | fullname: Tobias Looker 26 | organization: MATTR 27 | email: tobias.looker@mattr.global 28 | - 29 | fullname: Paul Bastian 30 | email: paul.bastian@bdr.de 31 | - 32 | fullname: Christian Bormann 33 | organization: SPRIND 34 | email: chris.bormann@gmx.de 35 | 36 | 37 | normative: 38 | RFC3986: RFC3986 39 | RFC7591: RFC7591 40 | RFC7519: RFC7519 41 | RFC7800: RFC7800 42 | RFC8414: RFC8414 43 | RFC8725: RFC8725 44 | RFC9110: RFC9110 45 | RFC9112: RFC9112 46 | IANA.HTTP.Fields: 47 | author: 48 | org: "IANA" 49 | title: "Hypertext Transfer Protocol (HTTP) Field Name Registry" 50 | target: "https://www.iana.org/assignments/http-fields/http-fields.xhtml" 51 | IANA.OAuth.Params: 52 | author: 53 | org: "IANA" 54 | title: "OAuth Authorization Server Metadata" 55 | target: "https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#authorization-server-metadata" 56 | informative: 57 | RFC6749: RFC6749 58 | RFC9334: RFC9334 59 | RFC7523: RFC7523 60 | ARF: 61 | title: "The European Digital Identity Wallet Architecture and Reference Framework" 62 | SD-JWT: I-D.ietf-oauth-selective-disclosure-jwt 63 | 64 | 65 | --- abstract 66 | 67 | This specification defines an extension to the OAuth 2 protocol as defined in {{RFC6749}} which enables a Client Instance to include a key-bound attestation in interactions with an Authorization Server or a Resource Server. This new method enables Client Instances involved in a client deployment that is traditionally viewed as a public client, to be able to utilize this key-bound attestation to authenticate. 68 | 69 | --- middle 70 | 71 | # Introduction 72 | 73 | Traditional OAuth security concepts perform client authentication through a backend channel. In ecosystems such as the Issuer-Holder-Verifier model used in {{SD-JWT}}, this model raises privacy concerns, as it would enable the backend to recognize which Holder (i.e. client) interacts with which Issuer (i.e. Authorization Server) and potentially furthermore see the credentials being issued. This specification establishes a mechanism for a backend-attested client authentication through a frontend channel to address these issues. 74 | 75 | Additionally, this approach acknowledges the evolving landscape of OAuth 2 deployments, where the ability for public clients to authenticate securely and reliably has become increasingly important. Leveraging platform mechanisms to validate a client instance, e.g. for mobile native apps, enables secure authentication that would otherwise be difficult with traditional OAuth client authentication methods. Transforming these platform-specific mechanisms into a common format as described in this specification abstracts this complexity to minimize the efforts for the Authorization Server. 76 | 77 | This primary purpose of this specification is the authentication of a client instance enabled through the client backend attesting to it. The client backend may also attest further technical properties about the hardware and software of the client instance. 78 | 79 | The following diagram depicts the overall architecture and protocol flow. 80 | 81 | ~~~ ascii-art 82 | (3) 83 | +-------+ 84 | | | 85 | | \ / 86 | +--------------------+ 87 | | | 88 | | Client Attester | 89 | | (backend) | 90 | | | 91 | +--------------------+ 92 | / \ | 93 | (2) | | (4) 94 | | \ / 95 | +---------------+ +---------------+ 96 | +----->| | | | 97 | (1) | | Client | (6) | Authorization | 98 | | | Instance |<--------->| Server | 99 | +------| | | | 100 | +---------------+ +---------------+ 101 | / \ | 102 | | | 103 | +-------+ 104 | (5) 105 | 106 | ~~~ 107 | 108 | The following steps describe this OAuth flow: 109 | 110 | (1) The Client Instance generates a key (Client Instance Key) and optional further attestations (that are out of scope) to prove its authenticity to the Client Attester. 111 | 112 | (2) The Client Instance sends this data to the Client Attester in request for a Client Attestation JWT. 113 | 114 | (3) The Client Attester validates the Client Instance Key and optional further data. It generates a signed Client Attestation JWT that is cryptographically bound to the Client Instance Key generated by the Client. Therefore, the attestation is bound to this particular Client Instance. 115 | 116 | (4) The Client Attester responds to the Client Instance by sending the Client Attestation JWT. 117 | 118 | (5) The Client Instance generates a Proof of Possession (PoP) with the Client Instance Key. 119 | 120 | (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. 121 | 122 | Please note that the protocol details for steps (2) and (4), particularly how the Client Instance authenticates to the Client Attester, are beyond the scope of this specification. Furthermore, this specification is designed to be flexible and can be implemented even in scenarios where the client does not have a backend serving as a Client Attester. In such cases, each Client Instance is responsible for performing the functions typically handled by the Client Attester on its own. 123 | 124 | # Conventions and Definitions 125 | 126 | {::boilerplate bcp14-tagged} 127 | 128 | # Terminology 129 | 130 | Client Attestation JWT: 131 | : A JSON Web Token (JWT) generated by the Client Attester which is bound to a key managed by a Client Instance which can then be used by the instance for client authentication. 132 | 133 | Client Attestation Proof of Possession (PoP) JWT: 134 | : A Proof of Possession generated by the Client Instance using the key that the Client Attestation JWT is bound to. 135 | 136 | Client Instance: 137 | : A deployed instance of a piece of client software. 138 | 139 | Client Instance Key: 140 | : 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 Attester. This public key is then encapsulated within the Client Attestation JWT and is utilized to sign the Client Attestation Proof of Possession. 141 | 142 | Client Attester: 143 | : An entity that authenticates a Client Instance and attests it by issuing a Client Attestation JWT. 144 | 145 | # Relation to RATS 146 | 147 | The Remote Attestation Procedures (RATS) architecture defined by {{RFC9334}} has some commonalities to this document. The flow specified in this specification relates to the "Passport Model" in RATS. However, while the RATS ecosystem gives explicit methods and values how the RATS Attester proves itself to the Verifier, this is deliberately out of scope for Attestation-Based Client Authentication. Additionally, the terminology between RATS and OAuth is different: 148 | 149 | - a RATS "Attester" relates to an OAuth "Client" 150 | - a RATS "Relying Party" relates to an OAuth "Authorization Server or Resource Server" 151 | - a RATS "Verifier" relates to the "Client Attester" defined in this specification 152 | - a RATS "Attestion Result" relates to the "Client Attestation JWT" defined by this specification 153 | - a RATS "Endorser", "Reference Value Provider", "Endorsement", "Evidence" and "Policies and Reference Values" are out of scope for this specification 154 | 155 | # Client Attestation Format 156 | 157 | 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 . 158 | 159 | ## Client Attestation JWT {#client-attestation-jwt} 160 | 161 | The Client Attestation MUST be encoded as a "JSON Web Token (JWT)" according to {{RFC7519}}. 162 | 163 | The following content applies to the JWT Header: 164 | 165 | * `typ`: REQUIRED. The JWT type MUST be `oauth-client-attestation+jwt`. 166 | 167 | The following content applies to the JWT Claims Set: 168 | 169 | * `iss`: REQUIRED. The `iss` (subject) claim MUST contains a unique identifier for the entity that issued the JWT. In the absence of an application profile specifying otherwise, compliant applications MUST compare issuer values using the Simple String Comparison method defined in Section 6.2.1 of {{RFC3986}}. 170 | * `sub`: REQUIRED. The `sub` (subject) claim MUST specify client_id value of the OAuth Client. 171 | * `exp`: REQUIRED. The `exp` (expiration time) claim MUST specify the time at which the Client Attestation is considered expired by its issuer. The authorization server MUST reject any JWT with an expiration time that has passed, subject to allowable clock skew between systems. 172 | * `cnf`: REQUIRED. The `cnf` (confirmation) claim MUST specify a key conforming to {{RFC7800}} that is used by the Client Instance to generate the Client Attestation PoP JWT for client authentication with an authorization server. The key MUST be expressed using the "jwk" representation. 173 | * `iat`: OPTIONAL. The `iat` (issued at) claim MUST specify the time at which the Client Attestation was issued. 174 | * `nbf`: OPTIONAL. The `nbf` (not before) claim MUST specify the time before which the Client Attestation MUST NOT be accepted for processing. 175 | 176 | The following additional rules apply: 177 | 178 | 1. The JWT MAY contain other claims. All claims that are not understood by implementations MUST be ignored. 179 | 180 | 2. 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. 181 | 182 | 3. The authorization server MUST reject a JWT that is not valid in all other respects per "JSON Web Token (JWT)" {{RFC7519}}. 183 | 184 | The following example is the decoded header and payload of a JWT meeting the processing rules as defined above. 185 | 186 | ~~~ 187 | { 188 | "typ": "oauth-client-attestation+jwt", 189 | "alg": "ES256", 190 | "kid": "11" 191 | } 192 | . 193 | { 194 | "iss": "https://attester.example.com", 195 | "sub": "https://client.example.com", 196 | "nbf": 1300815780, 197 | "exp": 1300819380, 198 | "cnf": { 199 | "jwk": { 200 | "kty": "EC", 201 | "use": "sig", 202 | "crv": "P-256", 203 | "x": "18wHLeIgW9wVN6VD1Txgpqy2LszYkMf6J8njVAibvhM", 204 | "y": "-V4dS4UaLMgP_4fY4j8ir7cl1TXlFdAgcx55o7TkcSA" 205 | } 206 | } 207 | } 208 | ~~~ 209 | 210 | ## Client Attestation PoP JWT {#client-attestation-pop-jwt} 211 | 212 | The Client Attestation PoP MUST be encoded as a "JSON Web Token (JWT)" according to {{RFC7519}}. 213 | 214 | The following content applies to the JWT Header: 215 | 216 | * `typ`: REQUIRED. The JWT type MUST be `oauth-client-attestation-pop+jwt`. 217 | 218 | The following content applies to the JWT Claims Set: 219 | 220 | * `iss`: REQUIRED. The `iss` (subject) claim MUST specify client_id value of the OAuth Client. 221 | * `exp`: REQUIRED. The `exp` (expiration time) claim MUST specify the time at which the Client Attestation PoP is considered expired. 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. 222 | * `aud`: REQUIRED. The `aud` (audience) claim MUST specify 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. 223 | * `jti`: REQUIRED. The `jti` (JWT identifier) claim MUST specify a unique identifier for the Client Attestation PoP. 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. 224 | * `nonce`: OPTIONAL. The `nonce` (nonce) claim MUST specify 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. 225 | * `iat`: OPTIONAL. The `iat` (issued at) claim MUST specify the time at which the Client Attestation PoP was issued. Note that the authorization server may reject JWTs with an "iat" claim value that is unreasonably far in the past. 226 | * `nbf`: OPTIONAL. The `nbf` (not before) claim MUST specify the time before which the Client Attestation PoP MUST NOT be accepted for processing. 227 | 228 | The following additional rules apply: 229 | 230 | 1. The JWT MAY contain other claims. All claims that are not understood by implementations MUST be ignored. 231 | 232 | 2. 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. 233 | 234 | 3. The public key used to verify the JWT MUST be the key located in the "cnf" claim of the corresponding Client Attestation JWT. 235 | 236 | 4. The Authorization Server MUST reject a JWT that is not valid in all other respects per "JSON Web Token (JWT)" {{RFC7519}}. 237 | 238 | The following example is the decoded header and payload of a JWT meeting the processing rules as defined above. 239 | 240 | ~~~ 241 | { 242 | "typ": "oauth-client-attestation-pop", 243 | "alg": "ES256" 244 | } 245 | . 246 | { 247 | "iss": "https://client.example.com", 248 | "aud": "https://as.example.com", 249 | "nbf": 1300815780, 250 | "exp": 1300819380, 251 | "jti": "d25d00ab-552b-46fc-ae19-98f440f25064", 252 | "nonce" : "5c1a9e10-29ff-4c2b-ae73-57c0957c09c4" 253 | } 254 | ~~~ 255 | 256 | # Client Attestation using a Header based syntax 257 | 258 | The following section defines how a Client Attestation can be provided in an HTTP request using HTTP headers. 259 | 260 | ## Client Attestation HTTP Headers {#headers} 261 | 262 | A Client Attestation JWT and Client Attestation PoP JWT can be included in an HTTP request using the following request header fields. 263 | 264 | OAuth-Client-Attestation: 265 | : A JWT that conforms to the structure and syntax as defined in [](#client-attestation-jwt) 266 | 267 | OAuth-Client-Attestation-PoP: 268 | : A JWT that adheres to the structure and syntax as defined in [](#client-attestation-pop-jwt) 269 | 270 | The following is an example of the OAuth-Client-Attestation header. 271 | 272 | ~~~ 273 | OAuth-Client-Attestation: eyJ0eXAiOiJvYXV0aC1jbGllbnQtYXR0ZXN0YXRpb24 274 | rand0IiwiYWxnIjoiRVMyNTYiLCJraWQiOiIxMSJ9.eyJpc3MiOiJodHRwczovL2F0dGV 275 | zdGVyLmV4YW1wbGUuY29tIiwic3ViIjoiaHR0cHM6Ly9jbGllbnQuZXhhbXBsZS5jb20i 276 | LCJuYmYiOjEzMDA4MTU3ODAsImV4cCI6MTMwMDgxOTM4MCwiY25mIjp7Imp3ayI6eyJrd 277 | HkiOiJFQyIsInVzZSI6InNpZyIsImNydiI6IlAtMjU2IiwieCI6IjE4d0hMZUlnVzl3Vk 278 | 42VkQxVHhncHF5MkxzellrTWY2SjhualZBaWJ2aE0iLCJ5IjoiLVY0ZFM0VWFMTWdQXzR 279 | mWTRqOGlyN2NsMVRYbEZkQWdjeDU1bzdUa2NTQSJ9fX0.4bCswkgmUHw06kKdiS2KEySR 280 | gjj73yCEIcrz3Mv7Bgns4Bm1tCQ9FAqMLtgzb5NthwJT9AhAEBogbiD5DtxV1g 281 | ~~~ 282 | 283 | The following is an example of the OAuth-Client-Attestation-PoP header. 284 | 285 | ~~~ 286 | OAuth-Client-Attestation-PoP: eyJhbGciOiJFUzI1NiIsInR5cCI6Im9hdXRoLWN 287 | saWVudC1hdHRlc3RhdGlvbi1wb3Arand0In0.eyJpc3MiOiJodHRwczovL2NsaWVudC5l 288 | eGFtcGxlLmNvbSIsImF1ZCI6Imh0dHBzOi8vYXMuZXhhbXBsZS5jb20iLCJuYmYiOjEzM 289 | DA4MTU3ODAsImV4cCI6MTMwMDgxOTM4MCwianRpIjoiZDI1ZDAwYWItNTUyYi00NmZjLW 290 | FlMTktOThmNDQwZjI1MDY0Iiwibm9uY2UiOiI1YzFhOWUxMC0yOWZmLTRjMmItYWU3My0 291 | 1N2MwOTU3YzA5YzQifQ.rEa-dKJgRuD-aI-4bj4fDGH1up4jV--IgDMFdb9A5jSSWB7Uh 292 | HfvLOVU_ZvAJfOWfO0MXyeunwzM3jGLB_TUkQ 293 | ~~~ 294 | 295 | Note that per {{RFC9110}} header field names are case-insensitive; so OAUTH-CLIENT-ATTESTATION, oauth-client-attestation, etc., are all valid and equivalent 296 | header field names. Case is significant in the header field value, however. 297 | 298 | 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). 299 | 300 | ~~~ 301 | OAuth-Client-Attestation = token68 302 | OAuth-Client-Attestation-PoP = token68 303 | token68 = 1*( ALPHA / DIGIT / "-" / "." / 304 | "_" / "~" / "+" / "/" ) *"=" 305 | ~~~ 306 | 307 | It is RECOMMENDED that the authorization server validate the Client Attestation JWT prior to validating the Client Attestation PoP. 308 | 309 | ## Validating HTTP requests feature client attestations {#checking-http-requests-with-client-attestations} 310 | 311 | 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: 312 | 313 | 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}. 314 | 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). 315 | 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. 316 | 317 | ## Client Attestation at the Token Endpoint {#token-endpoint} 318 | 319 | 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. 320 | 321 | The Authorization Server MUST perform all of the checks outlined in [](#checking-http-requests-with-client-attestations) for a received access token request which is making use of the client attestation mechanism as defined by this draft. 322 | 323 | The following example demonstrates usage of the client attestation mechanism in an access token request (with extra line breaks for display purposes only): 324 | 325 | ~~~ 326 | POST /token HTTP/1.1 327 | Host: as.example.com 328 | Content-Type: application/x-www-form-urlencoded 329 | OAuth-Client-Attestation: eyJ0eXAiOiJvYXV0aC1jbGllbnQtYXR0ZXN0YXRpb24 330 | rand0IiwiYWxnIjoiRVMyNTYiLCJraWQiOiIxMSJ9.eyJpc3MiOiJodHRwczovL2F0dGV 331 | zdGVyLmV4YW1wbGUuY29tIiwic3ViIjoiaHR0cHM6Ly9jbGllbnQuZXhhbXBsZS5jb20i 332 | LCJuYmYiOjEzMDA4MTU3ODAsImV4cCI6MTMwMDgxOTM4MCwiY25mIjp7Imp3ayI6eyJrd 333 | HkiOiJFQyIsInVzZSI6InNpZyIsImNydiI6IlAtMjU2IiwieCI6IjE4d0hMZUlnVzl3Vk 334 | 42VkQxVHhncHF5MkxzellrTWY2SjhualZBaWJ2aE0iLCJ5IjoiLVY0ZFM0VWFMTWdQXzR 335 | mWTRqOGlyN2NsMVRYbEZkQWdjeDU1bzdUa2NTQSJ9fX0.4bCswkgmUHw06kKdiS2KEySR 336 | gjj73yCEIcrz3Mv7Bgns4Bm1tCQ9FAqMLtgzb5NthwJT9AhAEBogbiD5DtxV1g 337 | OAuth-Client-Attestation-PoP: eyJhbGciOiJFUzI1NiIsInR5cCI6Im9hdXRoLWN 338 | saWVudC1hdHRlc3RhdGlvbi1wb3Arand0In0.eyJpc3MiOiJodHRwczovL2NsaWVudC5l 339 | eGFtcGxlLmNvbSIsImF1ZCI6Imh0dHBzOi8vYXMuZXhhbXBsZS5jb20iLCJuYmYiOjEzM 340 | DA4MTU3ODAsImV4cCI6MTMwMDgxOTM4MCwianRpIjoiZDI1ZDAwYWItNTUyYi00NmZjLW 341 | FlMTktOThmNDQwZjI1MDY0Iiwibm9uY2UiOiI1YzFhOWUxMC0yOWZmLTRjMmItYWU3My0 342 | 1N2MwOTU3YzA5YzQifQ.rEa-dKJgRuD-aI-4bj4fDGH1up4jV--IgDMFdb9A5jSSWB7Uh 343 | HfvLOVU_ZvAJfOWfO0MXyeunwzM3jGLB_TUkQ 344 | 345 | grant_type=authorization_code& 346 | code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4 347 | ~~~ 348 | 349 | ## Client Attestation at the PAR Endpoint {#par-endpoint} 350 | 351 | 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]). 352 | 353 | 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. 354 | 355 | The following example demonstrates usage of the client attestation mechanism in a PAR request (with extra line breaks for display purposes only): 356 | 357 | ~~~ 358 | POST /as/par HTTP/1.1 359 | Host: as.example.com 360 | Content-Type: application/x-www-form-urlencoded 361 | OAuth-Client-Attestation: eyJ0eXAiOiJvYXV0aC1jbGllbnQtYXR0ZXN0YXRpb24 362 | rand0IiwiYWxnIjoiRVMyNTYiLCJraWQiOiIxMSJ9.eyJpc3MiOiJodHRwczovL2F0dGV 363 | zdGVyLmV4YW1wbGUuY29tIiwic3ViIjoiaHR0cHM6Ly9jbGllbnQuZXhhbXBsZS5jb20i 364 | LCJuYmYiOjEzMDA4MTU3ODAsImV4cCI6MTMwMDgxOTM4MCwiY25mIjp7Imp3ayI6eyJrd 365 | HkiOiJFQyIsInVzZSI6InNpZyIsImNydiI6IlAtMjU2IiwieCI6IjE4d0hMZUlnVzl3Vk 366 | 42VkQxVHhncHF5MkxzellrTWY2SjhualZBaWJ2aE0iLCJ5IjoiLVY0ZFM0VWFMTWdQXzR 367 | mWTRqOGlyN2NsMVRYbEZkQWdjeDU1bzdUa2NTQSJ9fX0.4bCswkgmUHw06kKdiS2KEySR 368 | gjj73yCEIcrz3Mv7Bgns4Bm1tCQ9FAqMLtgzb5NthwJT9AhAEBogbiD5DtxV1g 369 | OAuth-Client-Attestation-PoP: eyJhbGciOiJFUzI1NiIsInR5cCI6Im9hdXRoLWN 370 | saWVudC1hdHRlc3RhdGlvbi1wb3Arand0In0.eyJpc3MiOiJodHRwczovL2NsaWVudC5l 371 | eGFtcGxlLmNvbSIsImF1ZCI6Imh0dHBzOi8vYXMuZXhhbXBsZS5jb20iLCJuYmYiOjEzM 372 | DA4MTU3ODAsImV4cCI6MTMwMDgxOTM4MCwianRpIjoiZDI1ZDAwYWItNTUyYi00NmZjLW 373 | FlMTktOThmNDQwZjI1MDY0Iiwibm9uY2UiOiI1YzFhOWUxMC0yOWZmLTRjMmItYWU3My0 374 | 1N2MwOTU3YzA5YzQifQ.rEa-dKJgRuD-aI-4bj4fDGH1up4jV--IgDMFdb9A5jSSWB7Uh 375 | HfvLOVU_ZvAJfOWfO0MXyeunwzM3jGLB_TUkQ 376 | 377 | response_type=code&state=af0ifjsldkj&client_id=s6BhdRkqt3 378 | &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb 379 | &code_challenge=K2-ltc83acc4h0c9w6ESC_rEMTJ3bww-uCHaoeK1t8U 380 | &code_challenge_method=S256&scope=account-information 381 | ~~~ 382 | 383 | # Concatenated Serialization for Client Attestations {#alternative-representation} 384 | 385 | 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. 386 | In those cases, a concatenated serialization of the Client Attestation and Client Attestation PoP can can be used. 387 | 388 | ## Concatenated Serialization Format {#format-alternative} 389 | 390 | This representation is created by concatenating Client Attestation and Client Attestation PoP separated by a tilde ('~') character: 391 | 392 | ~~~ 393 | ~ 394 | ~~~ 395 | 396 | 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. 397 | 398 | 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. 399 | 400 | The following is an example of such a concatenated serialization (with extra line breaks for display purposes only): 401 | 402 | ~~~ 403 | eyJ0eXAiOiJvYXV0aC1jbGllbnQtYXR0ZXN0YXRpb24rand0IiwiYWxnIjoiRVMyNTYiL 404 | CJraWQiOiIxMSJ9.eyJpc3MiOiJodHRwczovL2F0dGVzdGVyLmV4YW1wbGUuY29tIiwic 405 | 3ViIjoiaHR0cHM6Ly9jbGllbnQuZXhhbXBsZS5jb20iLCJuYmYiOjEzMDA4MTU3ODAsIm 406 | V4cCI6MTMwMDgxOTM4MCwiY25mIjp7Imp3ayI6eyJrdHkiOiJFQyIsInVzZSI6InNpZyI 407 | sImNydiI6IlAtMjU2IiwieCI6IjE4d0hMZUlnVzl3Vk42VkQxVHhncHF5MkxzellrTWY2 408 | SjhualZBaWJ2aE0iLCJ5IjoiLVY0ZFM0VWFMTWdQXzRmWTRqOGlyN2NsMVRYbEZkQWdje 409 | DU1bzdUa2NTQSJ9fX0.4bCswkgmUHw06kKdiS2KEySRgjj73yCEIcrz3Mv7Bgns4Bm1tC 410 | Q9FAqMLtgzb5NthwJT9AhAEBogbiD5DtxV1g~eyJhbGciOiJFUzI1NiIsInR5cCI6Im9h 411 | dXRoLWNsaWVudC1hdHRlc3RhdGlvbi1wb3Arand0In0.eyJpc3MiOiJodHRwczovL2Nsa 412 | WVudC5leGFtcGxlLmNvbSIsImF1ZCI6Imh0dHBzOi8vYXMuZXhhbXBsZS5jb20iLCJuYm 413 | YiOjEzMDA4MTU3ODAsImV4cCI6MTMwMDgxOTM4MCwianRpIjoiZDI1ZDAwYWItNTUyYi0 414 | 0NmZjLWFlMTktOThmNDQwZjI1MDY0Iiwibm9uY2UiOiI1YzFhOWUxMC0yOWZmLTRjMmIt 415 | YWU3My01N2MwOTU3YzA5YzQifQ.rEa-dKJgRuD-aI-4bj4fDGH1up4jV--IgDMFdb9A5j 416 | SSWB7UhHfvLOVU_ZvAJfOWfO0MXyeunwzM3jGLB_TUkQ 417 | ~~~ 418 | 419 | ## Validating the Concatenated Serialization {#validate-alternative} 420 | 421 | To validate a client attestation using the concatenated serialization form, the receiving server MUST ensure the following: 422 | 423 | 1. Before the '~' character, there exists precisely a single well-formed JWT conforming to the syntax outlined in [](client-attestation-jwt). 424 | 2. After the '~' character, there exists precisely a single well-formed JWT conforming to the syntax outlined in [](client-attestation-pop-jwt). 425 | 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. 426 | 427 | # Nonce Retrieval {#nonce-retrieval} 428 | 429 | This specification defines header fields that allow a Client to request a fresh nonce value to be used in the OAuth-Client-Attestation-PoP. The nonce is opaque to the client. 430 | 431 | An Authorization Server compliant with this specification SHOULD signal via the metadata entry `client_attestation_pop_nonce_required` which endpoints support and expect a server-provided nonce. The client MUST retrieve a nonce before other calls to this endpoint and MUST use this nonce for the Client Attestation PoP. 432 | 433 | A Request to an endpoint supporting the server-provided nonce MUST include the `attestation-nonce-request` field name with the value `true` and use the HTTP method of type OPTIONS (without payload) to actively request a nonce. The server answers with an HTTP Response with status code 200 without body, but sets the header field `attestation-nonce` to the nonce. 434 | 435 | The client MUST use this nonce in the OAuth-Attestation-PoP as defined in (#client-attestation-pop-jwt). 436 | 437 | The following is a non-normative example of a request: 438 | 439 | ~~~ 440 | OPTIONS /as/par HTTP/1.1 441 | Host: as.example.com 442 | attestation-nonce-request: true 443 | ~~~ 444 | 445 | the following is a non-normative example of a response: 446 | 447 | ~~~ 448 | HTTP/1.1 200 OK 449 | Host: as.example.com 450 | attestation-nonce: AYjcyMzY3ZDhiNmJkNTZ 451 | ~~~ 452 | 453 | # Implementation Considerations 454 | 455 | ## Reuse of a Client Attestation JWT 456 | 457 | 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. 458 | 459 | ## Refresh token binding 460 | 461 | Authorization servers issuing a refresh token in response to a token request using the client attestation mechanism as defined by this draft MUST bind the refresh token to the Client Instance, and NOT just the client as specified in section 6 {{RFC6749}}. To prove this binding, the Client Instance MUST use the client attestation mechanism when refreshing an access token. The client MUST also use the same key that was present in the "cnf" claim of the client attestation that was used when the refresh token was issued. 462 | 463 | ## Web Server Default Maximum HTTP Header Sizes 464 | 465 | Because the Client Attestation and Client Attestation PoP are communicated using HTTP headers, implementers should consider that web servers may have a default maximum HTTP header size configured which could be too low to allow conveying a Client Attestation and or Client Attestation PoP in an HTTP request. It should be noted, that this limit is not given by the HTTP {{RFC9112}}, but instead web server implementations commonly set a default maximum size for HTTP headers. As of 2024, typical limits for modern web servers configure maximum HTTP headers as 8 kB or more as a default. 466 | 467 | ## Rotation of Client Instance Key 468 | 469 | This specification does not provide a mechanism to rotate the Client Instance Key in the Client Attestation JWT's "cnf" claim. If the Client Instance needs to use a new Client Instance Key for any reason, then it MUST request a new Client Attestation JWT from its Client Attester. 470 | 471 | # Privacy Considerations 472 | 473 | ## Client Instance Tracking Across Authorization Servers 474 | 475 | Implementers should be aware that using the same client attestation across multiple authorization servers could result in correlation of the end user using the Client Instance through claim values (including the Client Instance Key in the `cnf` claim). Client deployments are therefore RECOMMENDED to use different Client Attestation JWTs with different Client Instance Keys across different authorization servers. 476 | 477 | # Security Considerations 478 | 479 | The guidance provided by {{RFC7519}} and {{RFC8725}} applies. 480 | 481 | ## Replay Attack Detection 482 | 483 | 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: 484 | 485 | - 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. 486 | - 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. 487 | - 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. 488 | 489 | 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. 490 | 491 | # Appendix A IANA Considerations 492 | 493 | ## OAuth Parameters Registration 494 | 495 | This specification requests registration of the following values in the IANA "OAuth Authorization Server Metadata" registry {{IANA.OAuth.Params}} established by {{RFC8414}}. 496 | 497 | * Metadata Name: client_attestation_pop_nonce_required 498 | * Metadata Description: An array of URLs that specify the endpoints supporting the nonce retrieval and expecting a Client Attestation bound to a server-provided nonce. 499 | * Change Controller: IETF 500 | * Reference: [](#nonce-retrieval) of this specification 501 | 502 | ## Registration of attest_jwt_client_auth Token Endpoint Authentication Method 503 | 504 | This section registers the value "attest_jwt_client_auth" in the IANA "OAuth Token Endpoint Authentication Methods" registry established by OAuth 2.0 Dynamic Client Registration Protocol {{RFC7591}}. 505 | 506 | * Token Endpoint Authentication Method Name: "attest_jwt_client_auth" 507 | * Change Controller: IESG 508 | * Specification Document(s): TBC 509 | 510 | ## HTTP Field Name Registration 511 | This section requests registration of the following scheme in the "Hypertext Transfer Protocol (HTTP) Field Name Registry" {{IANA.HTTP.Fields}} described in {{RFC9110}}: 512 | 513 | * Field Name: OAuth-Client-Attestation 514 | * Status: permanent 515 | * Reference: [](#headers) of this specification 516 | 517 |
518 | 519 | * Field Name: OAuth-Client-Attestation-PoP 520 | * Status: permanent 521 | * Reference: [](#headers) of this specification 522 | 523 |
524 | 525 | * Field Name: attestation-nonce-request 526 | * Status: permanent 527 | * Reference: [](#nonce-retrieval) of this specification 528 | 529 |
530 | 531 | * Field Name: attestation-nonce 532 | * Status: permanent 533 | * Reference: [](#nonce-retrieval) of this specification 534 | --- back 535 | 536 | # Document History 537 | 538 | -05 539 | 540 | * add nonce endpoint 541 | * add metadata entry for nonce 542 | * improve introduction 543 | * rename client backend to client attester 544 | * fix missing typ header in examples 545 | 546 | -04 547 | 548 | * remove key attestation example 549 | * restructured JWT Claims for better readability 550 | * added JOSE typ values for Client Attestation and Client Attestation PoP 551 | * add RATS relation 552 | * add concatenated representation without headers 553 | * add PAR endpoint example 554 | * fix PoP examples to include jti and nonce 555 | * add iana http field name registration 556 | 557 | -03 558 | 559 | * remove usage of RFC7521 and the usage of client_assertion 560 | * add new header-based syntax introducing Oauth-Client-Attestation and OAuth-Client-Attestation-PoP 561 | * add Client Instance to the terminology and improve text around this concept 562 | 563 | -02 564 | 565 | * add text on the inability to rotate the Client Instance Key 566 | 567 | -01 568 | 569 | * Updated eIDAS example in appendix 570 | * Removed text around jti claim in client attestation, refined text for its usage in the client attestation pop 571 | * Refined text around cnf claim in client attestation 572 | * Clarified how to bind refresh tokens to a Client Instance using this client authentication method 573 | * Made it more explicit that the client authentication mechanism is general purpose making it compatible with extensions like PAR 574 | * Updated acknowledgments 575 | * Simplified the diagram in the introduction 576 | * Updated references 577 | * Added some guidance around replay attack detection 578 | 579 | -00 580 | 581 | * Initial draft 582 | 583 | # Acknowledgments 584 | {:numbered="false"} 585 | 586 | We would like to thank 587 | Brian Campbell, 588 | Filip Skokan, 589 | Francesco Marino, 590 | Guiseppe De Marco, 591 | Kristina Yasuda, 592 | Michael B. Jones, 593 | Takahiko Kawasaki 594 | and 595 | Torsten Lodderstedt 596 | for their valuable contributions to this specification. 597 | --------------------------------------------------------------------------------