openid-connect-key-binding August 2026
Hardt & Heilman Standards Track [Page]
Workgroup:
OpenID Connect
Published:
Authors:
D. Hardt
Hellō
E. Heilman
Cloudflare

OpenID Connect Key Binding 1.0 - draft 03

Abstract

This specification defines how to bind a public key to an OpenID Connect ID Token using mechanisms defined in [RFC9449], OAuth 2.0 Demonstrating Proof of Possession (DPoP).

Table of Contents

1. Introduction

OpenID Connect [OpenID.Core] enables a Relying Party (RP) to obtain End-User authentication and identity claims from an OpenID Provider (OP) in the form of an ID Token. An RP initiates the protocol by making an authentication request to the OP. The OP authenticates the End-User and returns an ID Token, signed by the OP, containing claims about the End-User.

An RP is often composed of multiple components, such as an RP Authenticating Component that obtains the ID Token from the OP and an RP Consuming Component that checks the ID Token presented to it by the RP Authenticating Component. To prove it has authenticated an End-User, the RP Authenticating Component may present the ID Token to the RP Consuming Component as a bearer token. However, bearer tokens are vulnerable to theft and replay attacks: an attacker who obtains the ID Token can impersonate the authenticated End-User.

An RP may register more than one client_id with an OP, commonly one per application, such as an Android app, an iOS app, and a web app, so that an RP Consuming Component can identify which application obtained the ID Token. All such registrations belong to the same RP, and an RP Consuming Component accepts ID Tokens issued to any of the client_id values it is configured to accept.

By binding a cryptographic key to the ID Token, the RP Authenticating Component can prove to RP Consuming Components not only that an End-User has been authenticated, but that the RP Authenticating Component itself was the original recipient of that authentication. This provides stronger security guarantees, preventing token theft and replay attacks, by transforming the ID Token from a bearer token into a proof-of-possession token.

Use cases for this include:

The Use Cases appendix describes how key binding is applied in each of these scenarios.

This specification profiles OpenID Connect 1.0 [OpenID.Core], RFC8628 - OAuth 2.0 Device Authorization Grant [RFC8628], and RFC9449 - OAuth 2.0 Demonstrating Proof of Possession (DPoP) [RFC9449] to enable cryptographically bound ID Tokens that resist theft and replay attacks while maintaining compatibility with existing OpenID Connect infrastructure.

1.1. Requirements Notation and Conventions

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119].

In the .txt version of this specification, values are quoted to indicate that they are to be taken literally. When using these values in protocol messages, the quotes MUST NOT be used as part of the value. In the HTML version of this specification, values to be taken literally are indicated by the use of this fixed-width font.

1.2. Terminology

This specification uses the following terms:

  • OP: The OpenID Provider as defined in [OpenID.Core].

  • RP: The Relying Party as defined in [OpenID.Core].

  • End-User: The End-User as defined in [OpenID.Core].

  • RP Authenticating Component: The component of an RP that makes the Authentication Request to the OP and receives the ID Token.

  • RP Consuming Component: A component of an RP to which an RP Authenticating Component presents an ID Token.

  • RP Trust Boundary: The components and applications operated by, or under the control of, a single RP. An RP MAY register more than one client_id with an OP, commonly one per application, so that an RP Consuming Component can identify which application obtained the ID Token. All such registrations belong to the same RP and are within the same RP Trust Boundary.

The parameters dpop_jkt and DPoP as defined in [RFC9449]

1.3. OpenID Connect Metadata

The OP's OpenID Connect Metadata Document [OpenID.Discovery] SHOULD include:

  • the bound_key scope in the scopes_supported

  • the dpop_signing_alg_values_supported property containing a list of supported algorithms as defined in [IANA.JOSE.ALGS]

1.4. Protocol Profile Overview

This specification works by adding parameters and headers to the Authentication Request and Token Request and then validating these fields such that the ID Token returned in the Token Response contains a cnf claim for a public key. The RP signals to the OP that it is requesting a key-bound ID Token by including the scope bound_key in the Authentication Request.

This specification extends OpenID Connect with the addition of a parameter, dpop_jkt, to the Authentication Request, and the addition of a DPoP header to the Token Request and Refresh Request. If the OP chooses to issue a key-bound ID Token it validates the dpop_jkt parameter and DPoP header and returns an ID Token in the Token Response which includes a cnf claim for the public key. This specification does not add new messages, requests or responses. It preserves the current OpenID Connect flows and interactions.

For the Authorization Code Flow the following changes are made:

  1. adding the bound_key scope and dpop_jkt parameter to the OpenID Connect Authentication Request

  2. receiving the authorization code as usual in the Authentication Response

  3. adding the DPoP header that includes the SHA-256 hash of the code as the claim c_s256 in the Token Request to the OP token_endpoint

  4. adding the cnf claim containing the public key to the returned ID Token

+------+                              +------+
|      |-- Authentication Request --->|      |
|  RP  |   (1) bound_key & dpop_jkt   |  OP  |
|      |                              |      |
|      |<-- Authentication Response --|      |
|      |   (2) authorization code     |      |
|      |                              |      |
|      |-- Token Request ------------>|      |
|      |   (3) DPoP header w/ c_s256  |      |
|      |                              |      |
|      |<-- Token Response -----------|      |
|      |   (4) cnf claim containing   |      |
|      |   the public key in ID Token |      |
+------+                              +------+

The Device Authorization Flow follows the pattern of the Authorization Code Flow but sets the claim c_s256 to the SHA-256 of the device_code in place of the authorization code, making the following changes:

  1. adding the bound_key scope and dpop_jkt parameter to the OpenID Connect Authentication Request

  2. receiving the device_code as usual in the Device Authentication Response

  3. adding the DPoP header that includes the SHA-256 hash of the device_code, c_s256, as a claim in the Token Request to the OP token_endpoint

  4. adding the cnf claim containing the public key to the returned ID Token

+----------+                                +------+
|          |-- Authentication Request ----->|      |
|    RP    |   (1) bound_key & dpop_jkt     |  OP  |
| (device  |                                |      |
| client)  |<-- Authentication Response ----|      |
|          |   (2) device_code, user_code   |      |
|          |       & Verification URI       |      |
|          |                                |      |
|          |   [polling]                    |      |
|          |-- Token Request -------------->|      |
|          |   (3) DPoP header w/ c_s256    |      |
|          |   c_s256 = SHA256(device_code) |      |
|          |                                |      |
|          |<-- Token Response -------------|      |
|          |   (4) cnf claim containing     |      |
|          |   the public key in ID Token   |      |
+----------+                                +------+

This specification defines key binding for the Authorization Code Flow and the Device Authorization Flow only. The Implicit Flow [OpenID.Core] MUST NOT be used to obtain a key-bound ID Token. The Implicit Flow returns the ID Token from the Authorization Endpoint without a Token Request, so the RP Authenticating Component has no opportunity to demonstrate possession of the key identified by dpop_jkt, and the OP cannot bind the ID Token to a key it has no proof the requester controls. The Hybrid Flow [OpenID.Core] MUST NOT be used to obtain a key-bound ID Token. While the Authorization Code returned by the Hybrid Flow permits an ID Token to be obtained from the Token Endpoint, an ID Token returned from the Authorization Endpoint in the same response cannot be key-bound, and this specification does not define how an RP Authenticating Component distinguishes the two. Support for other flows is out of scope of this specification.

2. Authorization Code Flow

2.1. Authentication Request

If the RP Authenticating Component is running on a device that supports a web browser, it makes an authorization request per [OpenID.Core] 3.1. In addition to the scope parameter containing openid, and the response_type having the value code, the scope parameter MUST also include bound_key, and the request MUST include the dpop_jkt parameter having the value of the JWK Thumbprint [RFC7638] of the proof-of-possession public key using the SHA-256 hash function, as defined in [RFC9449] section 10.

Following is a non-normative example of an authentication request using the authorization code flow:

GET /authorize?
response_type=code
&dpop_jkt=dnfb1T9jil_gOhti60baHs_WD_a4D8JN9VDJXbmBmGw
&scope=openid%20profile%20email%20bound_key
&client_id=s6BhdRkqt3
&state=af0ifjsldkj
&nonce=2a50f9ea812f9bb4c8f7
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1
Host: server.example.com

If the OP does not support the bound_key scope, it SHOULD ignore it per [OpenID.Core] 3.1.2.1.

2.2. Authentication Response

If the key provided was not previously bound to the client, the OP SHOULD inform the End-User and obtain consent that a key binding will be done.

On successful authentication of, and consent from the End-User, the OP returns an authorization code.

Following is a non-normative example of a response:

HTTP/1.1 302 Found
Location: https://client.example.org/cb?
    code=SplxlOBeZQQYbYS6WxSbIA
    &state=af0ifjsldkj

2.3. Token Request

To obtain the ID Token, the RP Authenticating Component:

  1. generates c_s256 by computing SHA256 hash of the authorization code encoded as BASE64URL(SHA256(ASCII(code)))

  2. generates a DPoP header, including the c_s256 claim in the DPoP header JWT. This binds the authorization code to the token request. The typ of the DPoP header JWT MUST be dpop+jwt.

Non-normative example of a confidential client setting Authorization: Basic per [OpenID.Core] 3.1.3.1:

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
DPoP: eyJhbGciOiJFUzI1NiIsImp3ayI6eyJjcnYiOiJQLTI1NiIsImt0eSI6\
 IkVDIiwieCI6InVrcHYzZlU2dHFRS2FVd2NkQkFRb0szSUh2SklXX185eU5kMW\
 9SN3F2WmMiLCJ5IjoibkJCeFhyeDBOeml3Z19ldmZVTVVVZ25HS0tVZjJBVHBX\
 RzlFb2puVW9VNCJ9LCJ0eXAiOiJkcG9wK2p3dCJ9.eyJjX3MyNTYiOiJvMXVCc\
 DllU2UzRHNtU2NOMGpZcmlGZ0tLRmRLLUJMeXdDOVdScFY1R0c4IiwiaHRtIjo\
 iUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuI\
 iwiaWF0IjoxNzYxOTM3NDQ5LCJqdGkiOiJJUVM1dFlQLWJwQlB0SnNvclQ0ejd\
 nIn0.ay7H-sV7o_NE19Qfdq7oFNZ_oH-8LRw7_dgiTRQAUusLjEhgzNYR1ZU1T\
 6IZGopiTEk55LPu_g0gKKku96d4kA

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb

Authorization: Basic HTTP header is only included if a confidential client is used.

If a DPoP header is included in the token request to the OP, and the dpop_jkt parameter was not included in the authentication request, the OP MUST NOT include the cnf claim in the ID Token.

  • This prevents an existing deployment using DPoP for access token from having key-bound ID Tokens issued accidentally.

The OP MUST:

  • perform all verification steps as described in [RFC9449] section 5.

  • calculate the c_s256 from the authorization code just as the RP component did.

  • confirm the c_s256 in the DPoP JWT matches its calculated c_s256

3. Device Authorization Flow

3.1. Authentication Request

If the RP Authenticating Component is running on a device that does not support a web browser, it makes an authorization request per [RFC8628] 3.1. In the request, the scope parameter MUST contain both openid and bound_key. The request MUST include the dpop_jkt parameter having the value of the JWK Thumbprint [RFC7638] of the proof-of-possession public key using the SHA-256 hash function, as defined in [RFC9449] section 10.

Following is a non-normative example of an authentication request using the device authorization flow:

POST /device_authorization HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
dpop_jkt=dnfb1T9jil_gOhti60baHs_WD_a4D8JN9VDJXbmBmGw
&scope=openid%20profile%20email%20bound_key
&client_id=s6BhdRkqt3
&nonce=KDOmGsiiMaiq-ZhBE-RmPgCsrH-bs-wqbqD2FsRWf7g

If the OP does not support the bound_key scope, it SHOULD ignore it per [OpenID.Core] 3.1.2.1.

3.2. Authentication Response

As per [RFC8628], the OP in response to the Authentication Request, generates and returns to the RP Authenticating Component the required parameters device_code, user_code, verification_uri and expires_in and may return the optional parameters verification_uri_complete and interval.

Following is a non-normative example of an authentication response using the device authorization flow:

{
"device_code":"GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS",
"user_code":"059-461-148",
"verification_uri":"https://client.example.org/device",
"verification_uri_complete":"https://client.example.org/?user_code=059-461-148",
"expires_in": 1800
}

3.3. Token Request

As per [RFC8628] the RP Authenticating Component makes token requests to OP at regular intervals. Prior to the OP authenticating and obtaining consent from the End-User, the OP returns an error. Once the OP has authenticated and obtained consent from the End-User, the OP responds by returning the ID Token.

In addition to the parameters required by [RFC8628] the token request to the OP must contain a DPoP header. The RP Authenticating Component computes this DPoP header as follows:

  1. generates c_s256 by computing SHA-256 hash of the authorization device_code encoded as BASE64URL(SHA256(ASCII(device_code)))

  2. generates a DPoP header, including the c_s256 claim in the DPoP header JWT. This binds the authorization device_code to the token request. The typ of the DPoP header JWT MUST be dpop+jwt.

Non-normative example of a token request:

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
DPoP: eyJhbGciOiJFUzI1NiIsImp3ayI6eyJjcnYiOiJQLTI1NiIsImt0eSI6\
 IkVDIiwieCI6InVrcHYzZlU2dHFRS2FVd2NkQkFRb0szSUh2SklXX185eU5kMW\
 9SN3F2WmMiLCJ5IjoibkJCeFhyeDBOeml3Z19ldmZVTVVVZ25HS0tVZjJBVHBX\
 RzlFb2puVW9VNCJ9LCJ0eXAiOiJkcG9wK2p3dCJ9.eyJjX3MyNTYiOiJ6LTZLS\
 k1GNjcxUFFLWFN1SUhBVlFmbkVWUjJ4MUFVc2ZIbHZDNTB2YTM4IiwiaHRtIjo\
 iUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuI\
 iwiaWF0IjoxNzYxOTM3NDQ5LCJqdGkiOiJJUVM1dFlQLWJwQlB0SnNvclQ0ejd\
 nIn0.9t65IuqqvabsJp4v9CpY_pj7ad97KCdR9LXXF-pFvUokP_h2OZ2KqlM10\
 O-l-vebFVHk0qbm1pcw3MWH_VhO7A

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code
&device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS
&client_id=app_fzr7iWr50CWQkGDrLCZBYQc4_2Ak

If a DPoP header is included in the token request to the OP, and the dpop_jkt parameter was not included in the authentication request, the OP MUST NOT include the cnf claim in the ID Token.

  • This prevents an existing deployment using DPoP for access token from having key-bound ID Tokens issued accidentally.

The OP MUST:

  • perform all verification steps as described in [RFC9449] section 5.

  • calculate the c_s256 from the authorization device_code just as the RP component did.

  • confirm the c_s256 in the DPoP JWT matches its calculated c_s256

4. Token Response

If the token request was successful, the OP MUST return an ID Token containing the cnf claim as defined in [RFC7800] set to the jwk of the End-User's public key and with typ set to dpop+id_token in the ID Token's protected header.

Non-normative example of the ID Token payload:

{
    "iss": "https://server.example.com",
    "sub": "24400320",
    "aud": "s6BhdRkqt3",
    "nonce": "n-0S6_WzA2Mj",
    "exp": 1311281970,
    "iat": 1311280970,
    "cnf":
        {
            "jwk": {
                "crv": "P-256",
                "kty": "EC",
                "x": "ukpv3fU6tqQKaUwcdBAQoK3IHvJIW__9yNd1oR7qvZc",
                "y": "nBBxXrx0Nziwg_evfUMUUgnGKKUf2ATpWG9EojnUoU4"
            }
        }
}

The OP MAY return a Refresh Token. If a Refresh Token is returned, it MUST be bound to the public key of the DPoP proof used in the Token Request i.e. the same public key bound to the ID Token.

5. Refresh Request

If a Refresh Token was returned in the Token Response, the RP may use the Refresh Token to make Refresh Requests to the OP's Token Endpoint and receive a refreshed ID Token ([OpenID.Core] 12). This Refresh Token MUST be bound to the same public key as the ID Token and the OP MUST validate a DPoP proof ([RFC9449] 5) for this public key on each refresh request.

To refresh the ID Token, the RP Authenticating Component:

  1. generates a DPoP header. The typ of the DPoP header JWT MUST be dpop+jwt.

  2. makes a POST request to the OP's Token Endpoint with the DPoP header and the Refresh Token as a parameter.

Non-normative example:

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
DPoP: eyJhbGciOiJFUzI1NiIsImp3ayI6eyJjcnYiOiJQLTI1NiIsImt0eSI6\
 IkVDIiwieCI6InVrcHYzZlU2dHFRS2FVd2NkQkFRb0szSUh2SklXX185eU5kMW\
 9SN3F2WmMiLCJ5IjoibkJCeFhyeDBOeml3Z19ldmZVTVVVZ25HS0tVZjJBVHBX\
 RzlFb2puVW9VNCJ9LCJ0eXAiOiJkcG9wK2p3dCJ9.eyJodG0iOiJQT1NUIiwia\
 HR1IjoiaHR0cHM6Ly9zZXJ2ZXIuZXhhbXBsZS5jb20vdG9rZW4iLCJpYXQiOjE\
 3NjE5Mzc4MjMsImp0aSI6ImJHOXpaV1psYm1ObFkyaHZiM05sY20ifQ.NVmGXw\
 opPNYiN7CpITgR0Fl1PYFFgIAbxPxs8N1llDPoQmR60il35b-Zez71eMkdM9gd\
 oqJkee3oKrimdrsCfA

grant_type=refresh_token&refresh_token=8xLOxBtZp8

The OP MUST validate the Refresh Token and MUST validate the DPoP header presented. The OP MUST reject the DPoP header if it is not signed with the public key that was bound to the presented Refresh Token in the initial Token Request. Unlike the Token Request, no c_s256 claim is required in the DPoP header for the Refresh Request.

If an ID Token is returned as a result of a Refresh Request, an additional requirement applies:

If a new Refresh Token is returned as a result of a Refresh Request, the newly issued Refresh Token MUST continue to be bound to the same public key as the original Refresh Token.

6. RP Trust Boundary

An RP MUST NOT present a key-bound ID Token to a party outside its RP Trust Boundary.

An RP Consuming Component MUST verify that the aud claim of a key-bound ID Token is one of the client_id values it is configured to accept. The aud claim identifies the application that obtained the ID Token, not the component consuming it.

7. ID Token Proof of Possession

The mechanism for how an RP Authenticating Component proves to an RP Consuming Component that it possesses the private keys associated with the cnf claim in the ID Token is out of scope of this document.

8. Privacy Considerations

An RP Authenticating Component SHOULD only share an ID Token with an RP Consuming Component when such sharing is consistent with the original purpose for which the identity data was collected and the scope of consent obtained from the End-User.

An RP Authenticating Component MUST NOT share an ID Token with an RP Consuming Component when the ID Token contains claims that the RP Consuming Component should not have access to.

An ID Token contains claims the OP released to the RP for the purpose the End-User consented to. This is why an RP MUST NOT present a key-bound ID Token outside its RP Trust Boundary: doing so discloses those claims to a party the OP did not release them to, and that the End-User can neither discover nor revoke. Where identity claims are needed beyond the RP Trust Boundary, the receiving party should obtain its own ID Token for the End-User.

9. Security Considerations

9.1. Public Key Substitution Attacks

A public key substitution attack is a type of Unknown Key Share (UKS) attack in which an adversary binds the adversary identity to another party's key.

To protect against such attacks, the DPoP header JWT sent in the Token Request MUST include the c_s256 claim which contains the SHA-256 of the authorization code, or in the case of the Device Authorization Flow the SHA-256 of the device_code. This prevents replaying of the DPoP header JWTs between authentication sessions as each DPoP header JWT in a Token Request is now strictly bound to that session.

9.2. Require Proof of Possession

An RP Consuming Component MUST NOT trust an ID Token with a cnf claim without a corresponding proof of possession from the RP Authenticating Component.

9.3. ID Token Reverification

In addition to verifying the signature created by the RP Authenticating Component to prove possession of the private key associated with the cnf claim in the ID Token, an RP Consuming Component MUST independently verify the signature and validity of the ID Token, that the aud claim in the payload is one of the client_id values it is configured to accept as described in the RP Trust Boundary section, and that the typ claim in the protected header is dpop+id_token.

9.4. Accepted Audience Values

An RP Consuming Component MUST accept only the client_id values of the applications it is intended to serve. Accepting any client_id registered at the OP allows an application of another RP to present an ID Token as the RP's own. Accepting any client_id of the RP allows a less trusted application to act with the authorization of a more trusted one.

9.5. Use as Access Token

The ID Token MUST NOT be used as an access token to access resources. The RP MAY exchange the ID Token with a proof of possession for an access token that can then be used to access resources.

9.6. Unique Key Pair

To prevent token confusion attacks, the RP Authenticating Component SHOULD bind a unique key pair to its ID Tokens, and not use it for other purposes.

9.7. Using cnf as a User Claim

The cnf claim in the ID Token MUST be verified together with a proof of possession and MUST NOT be treated as proof on its own. A proof of possession is REQUIRED to establish that a party controls the key identified by cnf. The cnf claim SHOULD only be used to bind a signed object with the other claims in the ID Token.

10. IANA Considerations

The following entry should be added to the "Media Types" registry for the new JWT type:

Type name: application

Subtype name: dpop+id_token

11. References

11.1. Normative References

[OpenID.Core]
Sakimura, N., Jones, M., and J. Bradley, "OpenID Connect Core 1.0 (incorporating errata set 2)", , <https://openid.net/specs/openid-connect-core-1_0.html>.
[OpenID.Discovery]
Sakimura, N., Jones, M., Bradley, J., and E. Jay, "OpenID Connect Discovery 1.0 (incorporating errata set 2)", , <https://openid.net/specs/openid-connect-discovery-1_0.html>.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
[RFC7638]
Jones, M. and N. Sakimura, "JSON Web Key (JWK) Thumbprint", RFC 7638, DOI 10.17487/RFC7638, , <https://www.rfc-editor.org/info/rfc7638>.
[RFC7800]
Jones, M., Bradley, J., and H. Tschofenig, "Proof-of-Possession Key Semantics for JSON Web Tokens (JWTs)", RFC 7800, DOI 10.17487/RFC7800, , <https://www.rfc-editor.org/info/rfc7800>.
[RFC8628]
Denniss, W., Bradley, J., Jones, M., and H. Tschofenig, "OAuth 2.0 Device Authorization Grant", RFC 8628, DOI 10.17487/RFC8628, , <https://www.rfc-editor.org/info/rfc8628>.
[RFC9449]
Fett, D., Campbell, B., Bradley, J., Lodderstedt, T., Jones, M., and D. Waite, "OAuth 2.0 Demonstrating Proof of Possession (DPoP)", RFC 9449, DOI 10.17487/RFC9449, , <https://www.rfc-editor.org/info/rfc9449>.

11.2. Informative References

[IANA.JOSE.ALGS]
IANA, "IANA JSON Web Signature and Encryption Algorithms Registry", , <https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms>.

Appendix A. Use Cases

This appendix is non-normative. It describes how the mechanisms defined in this specification are applied in representative scenarios. The mechanism by which an RP Authenticating Component proves possession of the private key to an RP Consuming Component is out of scope of this specification (see the ID Token Proof of Possession section); each use case below notes how that proof is typically realized.

A.1. Exchanging an ID Token for an Access Token

An application, such as a mobile app, obtains a key-bound ID Token and exchanges it, together with a proof of possession, for an access token at an authorization service. The application and the authorization service are within the same RP Trust Boundary; the OP that issued the ID Token may be a third party. Because the exchange is within the RP Trust Boundary, the End-User is not delegating access to a third party and no authorization step is required.

Because the ID Token carries a cnf claim, the authorization service can confirm that the party requesting the access token is the same party the OP authenticated, rather than a bearer that obtained the ID Token in transit. Without key binding, an intercepted ID Token could be replayed to obtain an access token.

The ID Token conveys which End-User the OP authenticated and which application obtained it, not what that application is authorized to do. The authorization service determines the scopes of the access token from its own policy for that End-User and application, not from the ID Token or the Authentication Request.

The proof of possession is a DPoP proof computed over the exchange request. The authorization service verifies it against the cnf claim of the ID Token before issuing the access token.

A.2. Distributed Relying Party Components

A Relying Party is often composed of multiple components, for example a frontend that authenticates the End-User and one or more backends that act on the End-User's behalf. The RP Authenticating Component obtains the ID Token and presents it to an RP Consuming Component to prove which End-User the OP authenticated.

When the ID Token is key-bound, the RP Consuming Component requires a proof of possession alongside the ID Token. An attacker who captures the ID Token in transit between components cannot use it, because the attacker cannot produce the proof of possession.

The RP Authenticating Component proves possession on each request to an RP Consuming Component, for example with a DPoP proof over that request, and the RP Consuming Component verifies the proof against the cnf claim before trusting the ID Token.

A.3. Peer-to-Peer Authentication

In a peer-to-peer application, such as video conferencing or messaging, one instance proves to another which End-User is operating it. The instances are typically operated by different End-Users and communicate without a shared backend. This specification addresses the case where the instances are instances of the same application and therefore within the same RP Trust Boundary; peer-to-peer authentication between applications of different RPs is out of scope.

Consider Alice authenticating to Bob over WebRTC. With a bearer ID Token, an attacker who relays Alice's ID Token to Bob could impersonate Alice. With a key-bound ID Token, Alice signs a value that ties her authenticated identity to the connection, such as the DTLS certificate fingerprint of her media channel, using the key in the cnf claim. Bob verifies that signature against the cnf claim and is assured both that the OP authenticated Alice and that she controls the channel he is connected to.

The step that is not obvious to an implementer is binding the OpenID Connect identity to the application's own identity or channel: the value signed under the cnf key must be something the consuming instance can independently associate with the session, such as a WebRTC certificate fingerprint, a messaging device key, or a per-message signature. How that value is chosen and verified is application-specific and out of scope of this specification.

Appendix B. Acknowledgements

The authors would like to thank early feedback provided by Andrii Deinega, Filip Skokan, Frederik Krogsdal Jacobsen, George Fletcher, Jacob Ideskog, Jonas Primbs, Karl McGuinness, Kosuke Koiwai, Michael Jones, and Rohan Harikumar.

Appendix C. Notices

Copyright (c) 2026 The OpenID Foundation.

The OpenID Foundation (OIDF) grants to any Contributor, developer, implementer, or other interested party a non-exclusive, royalty free, worldwide copyright license to reproduce, prepare derivative works from, distribute, perform and display, this Implementers Draft, Final Specification, or Final Specification Incorporating Errata Corrections solely for the purposes of (i) developing specifications, and (ii) implementing Implementers Drafts, Final Specifications, and Final Specification Incorporating Errata Corrections based on such documents, provided that attribution be made to the OIDF as the source of the material, but that such attribution does not indicate an endorsement by the OIDF.

The technology described in this specification was made available from contributions from various sources, including members of the OpenID Foundation and others. Although the OpenID Foundation has taken steps to help ensure that the technology is available for distribution, it takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this specification or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any independent effort to identify any such rights. The OpenID Foundation and the contributors to this specification make no (and hereby expressly disclaim any) warranties (express, implied, or otherwise), including implied warranties of merchantability, non-infringement, fitness for a particular purpose, or title, related to this specification, and the entire risk as to implementing this specification is assumed by the implementer. The OpenID Intellectual Property Rights policy (found at openid.net) requires contributors to offer a patent promise not to assert certain patent claims against other contributors and against implementers. OpenID invites any interested party to bring to its attention any copyrights, patents, patent applications, or other proprietary rights that may cover technology that may be required to practice this specification.

Appendix D. Document History

[[ To be removed from the final specification ]]

-03

-02

-01

-00

Authors' Addresses

Dick Hardt
Hellō
Ethan Heilman
Cloudflare