Sender constraining tokens using Demonstrating Proof-of-Possession (DPoP) is currently in Early Access. To request access to this feature, contact your Auth0 representative.
- The client’s public key (
jwk
). - The payload referencing the access token request, including the method (
htm
) and URI (htu
). - A signature created using the client’s private key.
- A unique ID (
jti
) for replay prevention. - For every API request, a base64url-encoded SHA-256 hash (
ath
) of the access token. - Optional: For , a
nonce
claim to ensure the client application recently generated the DPoP Proof JWT.
Common use cases
Learn about some common DPoP use cases:- Single Page Applications (SPAs) and mobile applications: As public clients, SPAs and mobile applications lack a trusted, confidential environment like a backend server to securely store , which makes them vulnerable to token theft. DPoP addresses this security vulnerability by binding access tokens to the client application’s public key, creating a DPoP Proof JWT. The client application signs the DPoP Proof JWT with its private key and sends in an authorization request. The Auth0 Authorization Server validates the DPoP Proof JWT, and, if valid, binds the issued access token to the client’s public key.
- Third-party API integrations: If an AI agent integrated with your client application calls a third-party API on the user’s behalf using a DPoP Proof JWT, then the can cryptographically validate that the request is coming from the AI agent and not an unauthorized third party.
Supported application grant types
Auth0 supports the following application grant types for sender constraining with DPoP:Grant type | Description |
---|---|
authorization_code | Authorization Code Grant |
client_credentials | Client Credentials Grant |
password | Resource Owner Password Grant |
refresh_token | Refresh Token Grant |
urn:ietf:params:oauth:grant-type:device_code | Device Authorization Grant |
http://auth0.com/oauth/grant-type/password-realm | Use an extension grant similar to the Resource Owner Password Grant that includes the ability to indicate a specific realm |
http://auth0.com/oauth/grant-type/passwordless/otp | Passwordless Grant Request |
http://auth0.com/oauth/grant-type/mfa-oob | Multi-factor Authentication OOB Grant Request |
http://auth0.com/oauth/grant-type/mfa-otp | Multi-factor Authentication OTP Grant Request |
http://auth0.com/oauth/grant-type/mfa-recovery-code | Multi-factor Authentication Recovery Grant Request |
urn:ietf:params:oauth:grant-type:token-exchange | Custom Token Exchange Grant Request |
urn:okta:params:oauth:grant-type:webauthn | WebAuthn Grant Request |
How it works
The following sequence diagram illustrates the high-level steps in the Auth0 DPoP flow:
- When requestingan access token from the Auth0 Authorization Server, the client application generates a unique cryptographic key pair and uses the public key to prove its possession of the private key.
- The client application generates the DPoP Proof JWT and sends it to the /token endpoint on the Auth0 Authorization Server.
- The Auth0 Authorization Server verifies the DPoP Proof JWT, and if valid, issues the access token and binds it to the client’s public key.
- Before calling the Customer API, the client application generates a new DPoP Proof JWT to prove it possesses the private key associated with the token. The client application sends the DPoP Proof JWT and the sender-constrained access token to the resource server.
- The resource server verifies the DPoP Proof JWT, ensuring that only the valid owner of the token, or the original client application,can successfully use it to access protected resources. To request an access token from a refresh token, the client application generates a new DPoP Proof JWT, ensuring the refresh token is bound to the client’s public key.
Sender constrain tokens using DPoP in Auth0
The following diagram shows the end-to-end flow for sender constraining tokens using DPoP in Auth0:
- Prerequisites
- Step 1: Client application generates a DPoP key pair
- Step 2: Client application creates DPoP Proof JWT
- Step 3: Client application requests a DPoP-bound token
- Step 4: Auth0 Authorization Server validates the DPoP Proof JWT
- Step 5: Client application calls API with the DPoP-bound token and DPoP Proof JWT
- Step 6: Handle token refresh with DPoP
Prerequisites
Before you begin, make sure you:- Configure sender constraining for your client application and resource server.
Step 1: Client application generates a DPoP key pair
For DPoP, the client application must generate an asymmetric cryptographic key pair. Auth0 supports the use of Elliptic Curve, such as in ES256 keys. This key pair is unique to your client application and should be securely stored, for example, in a hardware-backed keystore. The client application keeps the private key secret while including the public key in the DPoP Proof JSON Web Token (JWT) that serves as the “proof of possession” in Step 2.Step 2: Client application creates a DPoP Proof JWT
Before requesting a DPoP-bound access token from the Auth0 Authorization Server’s/token
endpoint, your client application must create a DPoP Proof JWT. A DPoP Proof JWT is a JSON Web Token (JWT) signed by your client’s private key that serves as the “proof of possession.”
The DPoP Proof JWT consists of a JWT header and payload that contains claims linked to the token request:
JWT header claims
DPoP Proof JWT Claim | Description |
---|---|
typ | Set to dpop+jwt . |
alg | The asymmetric signing algorithm used, such as RS256 or ES256 . |
jwk | A JSON Web Key (JWK) representation of your client’s public key. |
JWT payload claims
DPoP Proof JWT Claim | Description |
---|---|
jti | A unique identifier for the JWT to prevent replay attacks. |
htm | The HTTP method of the request the DPoP proof is for, such as POST for token requests and GET for API calls. |
htu | The HTTP URI of the request the DPoP Proof JWT is for, without the fragment and query parameters. For example: https://api.example.com/data?param=1#section1 becomes https://api.example.com/data . |
iat | The creation timestamp of the JWT. |
ath | For API calls with an access token, a base64url-encoded SHA-256 hash of the access token. |
nonce | For public clients requiring a nonce , a server-provided nonce value. |
Step 3: Client application requests a DPoP-bound token
When your client application requests an access token from the Auth0 Authorization Server’s/token
endpoint, it includes the DPoP Proof JWT in the HTTP header of the request:
- Populates the DPoP HTTP header with a signed DPoP Proof JWT.
- Sends the DPoP HTTP header with a signed DPoP Proof JWT in an access token request to the
/token
endpoint. - Processes the response from the Auth0 Authorization Server.
Public clients
If a public client, such as a single-page application (SPA) or mobile app, requests a DPoP-bound access token, you won’t have a client secret or other client authentication parameters. In this case, Auth0 requires your DPoP HTTP header to have a value to ensure the client application recently generated the DPoP Proof JWT. If a public client makes a/token
request and doesn’t include a nonce
value in the DPoP HTTP header, Auth0 responds with an HTTP 400
code and an error message like the following:
DPoP-Nonce
header in the response headers. You must use the value of the DPoP-Nonce
header and regenerate the DPoP proof (as in Step 2), include a nonce
claim with that value, and resubmit the request to the /token
endpoint.
The following code sample shows the end-to-end flow when making and then retrying a /token
request with a nonce claim from a public client:
Step 4: Auth0 Authorization Server validates the DPoP Proof JWT
When the Auth0 Authorization Server receives the token request, it does the following:- Extracts the DPoP Proof JWT, its public key, and signature.
- Verifies the signature using the provided public key.
- Validates the
htm
,htu
,jti,
andiat
claims. - If valid, it issues an access token. The Auth0 Authorization Server includes a confirmation claim,
cnf
, in the access token. Thecnf
claim contains the thumbprint (hash) of the public key taken from the DPoP Proof JWT. By including it in the access token, the Auth0 Authorization Server binds the access token to that specific public key, or “sender-constrains” the access token. - Sets the
token_type
in theAuthorization
header toDPoP
instead ofBearer
in the token response. Traditionally, when the access token is passed in theAuthorization
header, it is set toBearer
. However, because we’re passing an access token bound to a public key using DPoP, it is set toDPoP
instead. - The Auth0 Authorization Server then issues the DPoP sender-constrained access token to your client application.
Step 5: Client application calls API with the DPoP-bound token and DPoP Proof JWT
For every API call to a resource server that enforces DPoP, your client application must present both the DPoP-bound access token and a new DPoP Proof JWT. By requiring a DPoP Proof JWT with every API request, DPoP ensures that only the client application that possesses the private key can use the access token. For a new API request, the client application:- Generates a new DPoP Proof JWT with the following claims:
- The
htm
claim is the API request’sHTTP
method, such asGET
orPOST
. - The
htu
claim is the API request’s URI. - The
ath
claim is the base64url-encoded SHA-256 hash of the DPoP-bound access token you received in Step 3.
- Cryptographically signs the new DPoP Proof JWT with the client’s private key.
-
Includes the DPoP-bound access token in the
Authorization
header using theDPoP
authentication scheme:
- Includes the newly generated DPoP Proof JWT in the
DPoP
HTTP header:
DPoP
HTTP header must include an additional ath
claim. The ath
claim is a base64url encoded SHA256 hash of the issued access token.
The resource server:
- Receives the API request and extracts the access token, DPoP JWT proof, public key, and signature.
- Verifies the DPoP Proof JWT’s signature using the public key from its
jwk
header. - Validates the
htm
,htu
,jti
,iat
, andath
claims. - Verifies that the public key indicated in the DPoP Proof JWT via its
jwk
header matches the public key bound to the access token via thecnf.jkt
claim in the access token.
/userinfo
endpoint using a DPoP-bound access token:
Step 6: Handle token refresh with DPoP
When your DPoP-bound access token expires, you can use a to get a new one. A refresh token request requires a DPoP Proof JWT generated using the same key pair used in the original token request. The following describes the refresh token flow with DPop in Auth0: The client application:- Makes a refresh token request to the Auth0 Authorization Server’s
/token
endpoint. - Generates a DPoP Proof JWT for the refresh token request (similar to Step 2, with
htm
asPOST
andhtu
as the URI). - Includes the DPoP Proof JWT in the
DPoP
HTTP header.
- Validates the DPoP Proof JWT (like in Step 4) and issues a new DPoP-bound access token.
Important considerations
When implementing DPoP in your client applications, consider the following:- Private key security: The security of your DPoP implementation depends on the security of your client’s private key, so you must protect it from unauthorized access. Private keys should be generated and stored in a hardware-backed medium and marked as non-exportable.
- Replay protection (****
jti
anddpop-nonce
****): Thejti
claim in the DPoP Proof JWT helps prevent replay attacks for protected resources, such as the/userinfo
endpoint. The Auth0 Authorization Server currently does not checkjti
reuse on the/userinfo
endpoint. The Auth0 Authorization Server issues aDPoP-Nonce
HTTP header in its response, which public clients must include as anonce
claim in subsequent DPoP Proof JWTs for enhanced replay protection. - Error handling: You are responsible for implementing logic to handle DPoP-specific errors from the Auth0 Authorization Server or resource server, such as
invalid_dpop_proof
oruse_dpop_nonce
. - Client types: Use DPoP for public clients, such as Single Page Applications (SPAs) or mobile apps that cannot securely store a client secret. For , such as backend services with client secrets, DPoP adds a layer of security, but they already have other sender-constraining mechanisms.
- Performance: Because generating and signing DPoP Proof JWTs for every API call adds a small overhead, ensure your client application’s cryptographic operations are efficient.
- Key rotation: Implement a strategy for rotating your DPoP key pairs for enhanced security. Make sure you use the same key pair for the same session.
- Persistence: For client applications that need to maintain a session and reuse DPoP-bound access tokens, such as long-lived SPAs, securely persist and retrieve the original generated key pair across application reloads. If a new key pair is generated or a different key pair is used, the DPoP-bound access token becomes invalid, as it is cryptographically tied to the public key of the original pair. You can persist the key pair, for example, in a browser’s
IndexedDB
or a mobile app’s secure storage.