openid-connect-key-binding | August 2025 | |
Hardt & Heilman | Standards Track | [Page] |
OpenID Key Binding specifies how to bind a public key to an OpenID Connect ID Token using mechanisms defined in RFC 9449, OAuth 2.0 Demonstrating Proof of Possession (DPoP).¶
OpenID Connect is a protocol that enables a Relying Party (RP) to delegate authentication and obtain identity claims to an OpenID Connect Provider (OP).¶
When authenticating with OpenID Connect, RP provides a nonce in its authentication request. The ID Token signed and returned by the OP contains the nonce and claims about the user. When verifying the ID Token, the RP confirms it contains the nonce, binding the session that made the request to the response.¶
When an RP wants to prove to another system that it has authenticated a user, it may present the ID Token as a bearer token. However, bearer tokens are vulnerable to theft and replay attacks - if an attacker intercepts the ID Token, they can impersonate the authenticated user to downstream systems that accept a ID Token as a bearer token.¶
By binding a cryptographic key to the ID Token, the RP can prove to downstream systems not only that a user has been authenticated, but that the RP itself was the original recipient of that authentication. This transforms the ID Token from a vulnerable bearer token into a proof-of-possession token that provides stronger security guarantees.¶
This specification profiles OpenID Connect 1.0, RFC8628 - OAuth 2.0 Device Authorization Grant, and RFC9449 - OAuth 2.0 Demonstrating Proof of Possession (DPoP) to enable cryptographically bound ID Tokens that resist theft and replay attacks while maintaining compatibility with existing OpenID Connect infrastructure.¶
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.¶
This specification uses the following terms:¶
OP: The OpenID Provider as defined in {{OpenID.Core}}.¶
RP: The Relying Party as defined in {{OpenID.Core}}.¶
The parameters dpop_jkt and DPoP as defined in {{RFC9449}}¶
This specification profiles how to bind a public key to an ID Token by:¶
adding the dpop
scope and dpop_jkt
parameter to the OpenID Connect Authentication Request¶
receiving the authorization code
as usual in the Authentication Response¶
adding the DPoP
header that includes the hash of the code
, c_hash
, as a claim in the Token Request to the OP token_endpoint
¶
adding the cnf
claim containing the public key to the returned ID Token¶
+------+ +------+ | |-- Authentication Request --->| | | RP | (1) dpop & dpop_jkt | OP | | | | | | |<-- Authentication Response --| | | | (2) authorization code | | | | | | | |-- Token Request ------------>| | | | (3) DPoP header w/ c_hash | | | | | | | |<-- Token Response -----------| | | | (4) cnf claim containing | | | | the public key in ID Token | | +------+ +------+¶
The OP's OpenID Connect Metadata Document ({{OpenID.Discovery}})SHOULD include":¶
If the key provided was not previously bound to the client, the OP SHOULD inform a user and obtain consent that a key binding will be done.¶
On successful authentication of, and consent from the user, the OP returns an authorization code
.¶
Following is a non-normative example of a response:¶
TBD¶
To obtain the ID Token, the RP:¶
generates a c_hash
by computing a SHA256 hash of the authorization code
¶
converts the hash to BASE64URL¶
generates a DPoP
header, including the c_hash
claim in the DPoP
header JWT. This binds the authorization code to the token request.¶
Non-normative example:¶
POST /token HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW DPoP: eyJhbGciOiJFUzI1NiJ9.eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkV\ TMjU2IiwiandrIjp7ImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ4IjoibWptR\ m1MZm9wVmkwZXRfYTZmZFhUTnJqYVUwR1dlZFN0Y3NfRzU4OEkyMCIsInkiOiJ\ sMFZwRXlSYzdTdUpfdHFhd2NaQ2VLLXVUOEVPVnF4N3NqTHJGeUJTUllZIn0sI\ m5vbmNlIjoiU3BseGxPQmVaUVFZYllTNld4U2JJQSJ9.cp8uN3kHAMS9fhGH7T\ vTSKwH5oNJzAeMhIrgD_HQHGhgt_N1xQHdHiMkn7AMj3UDkwoNOW4Qqak grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb¶
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 them included in ID Tokens accidentally.¶
The OP MUST:
- perform all verification steps as described in {{RFC9449}} section 5.
- calculate the c_hash
from the authorization code
just as the RP id.
- confirm the c_hash
in the DPoP JWT matches its calculated c_hash
¶
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 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": { "alg":"ES256", "crv": "P-256", "kty": "EC", "x": "mjmFmLfopVi0et_a6fdXTNrjaU0GWedStcs_G588I20", "y": "l0VpEyRc7SuJ_tqawcZCeK-uT8EOVqx7sjLrFyBSRYY" } } }¶
To be completed.¶
Proof of possession authentication provides a greater level of security than bearer token authentication. To authenticate with a bearer token, the authentication secret must be sent over the internet to the authenticating party. This presents a risk that the authentication secret be stolen is transit or stolen at the server endpoint and replayed. With proof of possession, the authentication secret, i.e. the private key, never needs to leave the client. This reduces the chance of exposure and allows the client to use additional security mechanisms to protect the private key such as HSMs (Hardware Security Modules) or web browser based SSMs (Software Security Modules).¶
Public key bound ID Tokens provide a higher level security than bearer ID Tokens by using proof of possession rather than bearer authentication. For this reason public key bound ID Tokens MUST NOT be accepted as a form of bearer token authentication. If bearer token authentication is desired, bearer ID Tokens should be used instead.¶
Media Type Registry The following entry should be added to the "Media Types" registry for the new JWT type: Type name: application Subtype name: dpop+id_token¶
[RFC2119] Bradner, S. “Key words for use in RFCs to Indicate Requirement Levels,” RFC 2119, March 1997.¶
[RFC7549] W. Mills, P. Saint-Andre, T. Hardie, “The OAuth 2.0 Authorization Framework: Bearer Token Usage,” RFC 7549, May 2015. Available at https://datatracker.ietf.org/doc/html/rfc7549.¶
[RFC7638] M. Jones, “JSON Web Key (JWK) Thumbprint,” RFC 7638, September 2015. Available at https://datatracker.ietf.org/doc/html/rfc7638.¶
[RFC7800] M. Jones, J. Bradley, N. Sakimura, “Proof-of-Possession Key Semantics for JSON Web Tokens (JWTs),” RFC 7800, April 2016. Available at https://datatracker.ietf.org/doc/html/rfc7800.¶
[RFC8628] W. Denniss, J. Bradley, “OAuth 2.0 Device Authorization Grant,” RFC 8628, June 2019. Available at https://datatracker.ietf.org/doc/html/rfc8628.¶
[RFC9449] D. Fett, B. Campbell, J. Bradley, “OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP),” RFC 9449, July 2023. Available at https://datatracker.ietf.org/doc/html/rfc9449.¶
OpenID.Core – “OpenID Connect Core 1.0 incorporating errata set 2,” available at https://openid.net/specs/openid-connect-core-1_0.html.¶
OpenID.Discovery – “OpenID Connect Discovery 1.0,” available at https://openid.net/specs/openid-connect-discovery-1_0.html.¶
IANA JSON Web Token Claims Registry, available at https://www.iana.org/assignments/jwt/jwt.xhtml.¶
IANA OAuth Parameters, available at https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#client-metadata.¶
The authors would like to thank early feedback provided by Filip Skokan, Jacob Ideskog, and Kosuke Koiwai.¶
To be completed if adopted.¶
[[ To be removed from the final specification ]]¶
-00¶
initial draft¶