PE
Protocol Explorer
OAuth 2.0 DPoP

OAuth 2.0 DPoP — Full Flow

Demonstrating Proof-of-Possession (DPoP) at the application layer. The client generates a DPoP proof to bind the access token to a private key, preventing token replay.

Client ApplicationAuthz ServerResource Server1POST /token2002POST /protected
POST https://auth.example.com/token200

The client requests an access token and includes a DPoP header. The DPoP header is a signed JWT containing the client's public key (in the jwk header) and the HTTP request details (htm, htu in payload).

• The Authorization Server validates the DPoP proof's signature.

• It then binds the issued access token to the public key by embedding its JWK Thumbprint (RFC 7638) in the 'cnf' claim of the token.

• The token_type in the response is 'DPoP' rather than 'Bearer'.

1 / 2
speed

Step 1: POST /token

Request / response
POSThttps://auth.example.com/token
Content-Type?

application/x-www-form-urlencoded

DPoP

eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6IkVDIiwieCI6Imw4QkZk…

Body
grant_type=authorization_code&code=SPLIT_123&client_id=my_client
Cryptographic Signature

Construction Steps

1. 1. Build JWT Header (includes Public Key)
{
  "typ": "dpop+jwt",
  "alg": "ES256",
  "jwk": {
    "kty": "EC",
    "x": "l8BFdamQrm6UmuEPY6r1qyJDlb3Ut3jXWiuKn4-GR3A",
    "y": "_eKPsI_use_2fkzDjhhqq8qVe_2oVvIo5jLQ3Mh41uM",
    "crv": "P-256"
  }
}
2. 2. Build JWT Payload
{
  "jti": "-BwC0eAMZea5GpZD",
  "htm": "POST",
  "htu": "https://auth.example.com/token",
  "iat": 1562262616
}
3. 3. Sign JWT
ES256(Base64Url(Header) + "." + Base64Url(Payload), PrivateKey) → Signature

Signature Base String

eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6IkVDIiwieCI6Imw4QkZkYW1Rcm02VW11RVBZNnIxcXlKRGxiM1V0M2pYV2l1S240LUdSM0EiLCJ5IjoiX2VLUHNJX3VzZV8yZmt6akRqaHFxOHFWZV8yb1Z2SW81akxRM01oNDF1TSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiItQndDMGVBTVplYTVHcFpEIiwiaHRtIjoiUE9TVCIsImh0dSI6Imh0dHBzOi8vYXV0aC5leGFtcGxlLmNvbS90b2tlbiIsImlhdCI6MTU2MjI2MjYxNn0

Signing Key

Client's ES256 Private Key

Signature Output

2-G04T...
DPoP Proofdpop+jwt
Header
{
"typ"?:"dpop+jwt",
"alg":"ES256",
"jwk"?:{
"kty":"EC",
"x":"l8BFdamQrm6UmuEPY6r1qyJDlb3Ut3jXWiuKn4-GR3A",
"y":"_eKPsI_use_2fkzDjhhqq8qVe_2oVvIo5jLQ3Mh41uM",
"crv":"P-256"
}
}
Payload
{
"jti"?:"-BwC0eAMZea5GpZD",
"htm":"POST",
"htu":"https://auth.example.com/token",
"iat"?:1562262616
}
sig: 2-G04T...…
Access Tokenat+jwt
Header
{
"typ"?:"at+jwt",
"alg":"ES256"
}
Payload
{
"iss"?:"https://auth.example.com",
"sub"?:"user123",
"aud"?:"https://api.example.com",
"exp"?:1562266216,
"iat"?:1562262616,
"cnf"?:{
"jkt":"0Zhm7PMUXy83vmvouFfHFa2tYqMwYUh7iCpVXjRo6Sc"
}
}
sig: mock_sig…