What is DPoP in Keycloak?
A regular access token works for whoever holds it — steal the token, steal the access. DPoP changes the rule: the token only works in the hands of the exact device that originally requested it.
Imagine a train ticket that works for anyone holding it versus a ticket that’s only valid when scanned alongside the exact fingerprint of the person who bought it. The first kind is convenient but risky — drop it, and a stranger rides for free. The second kind is dramatically harder to misuse, because possession of the paper alone isn’t enough anymore. Standard OAuth access tokens behave like the first kind of ticket: a “bearer” token, usable by anyone who has a copy of it, regardless of how they got it. DPoP — Demonstrating Proof of Possession — is how Keycloak upgrades a token to behave like the second kind, cryptographically binding it to the specific device that requested it. This guide explains what DPoP actually is, how Keycloak implements it, what happens internally on every request, and how real deployments decide when the extra protection is worth the extra complexity. No prior background in tokens or cryptography is assumed.
1Core Concepts
What is a bearer token?
The standard access token Keycloak issues by default is called a bearer token. The name describes its behavior exactly: whoever “bears,” or holds, the token is treated as authorized, full stop. An API receiving a bearer token checks that it’s genuinely signed by Keycloak and hasn’t expired, but it never asks “did the entity presenting this token right now actually get it originally?” This is efficient and simple, but it means a bearer token is exactly as dangerous to lose as cash — if it’s copied or stolen, whoever has it can spend it, with no further questions asked.
What problem does DPoP solve?
If an attacker manages to intercept or steal a bearer token — through a compromised browser extension, a poorly secured mobile app, a leaked server log, or a network-level attack — they can replay that exact token against the API and be treated as the legitimate user, with no way for the API to tell the difference. DPoP closes this gap by requiring the client to prove, on every single request, that it actually possesses the specific private key associated with that token — not just that it happens to have a copy of the token text itself.
Think of a hotel safe-deposit box that requires both a physical key and a second key held only by the hotel manager, used together to open it. A bearer token is like a system with only the physical key — copy the key, and you’re in. DPoP is like requiring the person opening the box to also prove, right there in front of the manager, that they know a secret only the original key-holder would know. Simply having a copy of the physical key is no longer enough on its own.
How does DPoP actually prove possession?
DPoP works using public-key cryptography, the same general technique behind WebAuthn. The client generates a key pair — a private key it keeps secret and never sends anywhere, and a public key it can share freely. When requesting a token, the client tells Keycloak about its public key. Keycloak then cryptographically ties the issued token to that specific public key. On every subsequent request to an API, the client must attach a small, freshly signed proof, created using its private key, demonstrating it still controls the matching key — something a thief who only stole the token text, but not the private key, simply cannot produce.
Financial APIs, healthcare systems, and any application handling especially sensitive actions where a stolen token alone should never be enough to gain access are the natural places to find DPoP enabled in a Keycloak deployment.
Key vocabulary, explained simply
Bearer Token
A standard access token usable by anyone who holds a copy of it, with no further proof of legitimate possession required.
DPoP Proof
A small, freshly signed JWT the client creates and attaches to each request, demonstrating it holds the private key tied to the token being used.
Key Binding
The process of cryptographically associating an issued token with a specific client-held public key, so the token only “works” alongside proof from the matching private key.
Token Theft / Replay Attack
An attack where a stolen or intercepted token is reused by someone other than its original, legitimate holder — exactly what DPoP is designed to defeat.
JWK (JSON Web Key)
A standard JSON format for representing a cryptographic key, used to describe the client’s public key both during token issuance and inside each DPoP proof.
Access Token Hash (ath)
A claim inside a DPoP proof containing a hash of the access token itself, tying the proof specifically to that one token rather than any token from the same client.
2Architecture & Components
graph TB
C[Client] --> KG[Generates Key Pair
private + public key]
C -->|token request + DPoP proof| KC[Keycloak Token Endpoint]
KC --> BIND[Binds token to
client's public key]
BIND --> TOK["DPoP-bound
Access Token"]
TOK --> C
C -->|API call + token + fresh DPoP proof| API[Resource Server]
API --> VER[Verifies proof signature
matches token's bound key]
VER --> DEC{Match?}
DEC -->|yes| ALLOW[Request Processed]
DEC -->|no| REJECT[Request Rejected]
Component breakdown
Client-Side Key Generation
The application itself (a browser-based app, a mobile app, a backend service) is responsible for generating and securely storing its own DPoP key pair, since the private key must never leave the client.
Keycloak’s DPoP Support
Realm and client-level settings that enable DPoP enforcement, controlling whether it’s required, optional, or disabled for a given client’s tokens.
Token Endpoint Binding Logic
The part of Keycloak’s token issuance process that reads the client’s supplied public key (via an initial DPoP proof) and embeds a reference to it into the issued token.
Resource Server Verification
The backend API code responsible for checking, on every request, that the attached DPoP proof is fresh, correctly signed, and matches the key the presented token was bound to.
Where this is configured in the admin console
Inside the Keycloak Admin Console, DPoP support is typically configured at the client level, under a client’s advanced or security-related settings, where an administrator can require DPoP for that specific client’s tokens. Realm-wide policy settings may also influence whether DPoP is available or mandatory across multiple clients, depending on the deployment’s overall security posture.
A common real setup
A banking application’s mobile app is configured as a Keycloak client with DPoP required. The app generates a device-specific key pair on first launch, stores the private key in the device’s secure hardware enclave, and includes a DPoP proof with every token request and every subsequent API call — meaning a stolen access token extracted from the app’s memory or network traffic is useless without also somehow extracting the private key from the device’s secure hardware.
Why isn’t DPoP just turned on for everyone by default?
Adding DPoP introduces real complexity — clients must generate, securely store, and correctly use cryptographic keys, and every resource server must add proof verification logic. For lower-sensitivity applications, this overhead may not be justified, since ordinary token security controls (short expiry, HTTPS, secure storage) are often sufficient. Keycloak makes DPoP an opt-in capability specifically so organizations can apply the extra protection where the risk genuinely warrants it.
3Internal Working
Binding a token to a key at issuance
When a DPoP-enabled client requests a token, it includes a specially crafted proof — a small, signed JWT containing its public key, a timestamp, a unique identifier, and details about the specific request being made. Keycloak verifies this proof is well-formed and freshly generated, then, upon issuing the access token, embeds a reference to the client’s public key directly into the token itself (typically as a thumbprint or hash of the key, inside a confirmation claim). From that moment on, this specific token is permanently, cryptographically tied to that specific public key.
Proving possession on every subsequent request
Every time the client wants to use the token against a resource server, it must generate a brand-new DPoP proof for that specific request — signed with the same private key, including a hash of the access token being presented, the HTTP method and URL of the request, and a fresh timestamp and unique identifier. The resource server checks this proof’s signature against the public key embedded in the token’s confirmation claim; if they match, and the proof is fresh and correctly tied to this exact request, the token is accepted as genuinely being used by its rightful holder.
Why a fresh proof is needed for every request, not just once
If a single DPoP proof could be reused indefinitely, an attacker who captured one specific proof-token pair could simply replay both together forever, defeating much of the point. Requiring a brand-new, uniquely identified proof for every single request — checked against a short validity window and a record of recently used proof identifiers — prevents this kind of replay, ensuring that even a captured, valid proof from one moment in time cannot be reused later.
Because each DPoP proof includes a timestamp and must fall within a tight validity window, significant clock drift between a client’s device and the Keycloak server (or resource server) can cause otherwise legitimate requests to be incorrectly rejected — accurate time synchronization becomes an operational requirement, not just a nicety.
Step-by-step: from key generation to a verified API call
Key pair generated
The client generates a private and public key pair, ideally stored in secure, tamper-resistant storage.
Initial DPoP proof created
The client builds a signed proof containing its public key, to accompany the token request.
Token issued and bound
Keycloak verifies the proof and issues an access token with the client’s public key thumbprint embedded inside it.
New proof generated per API call
Before each request, the client signs a fresh proof specific to that exact request’s method, URL, and the token being used.
Resource server verifies both together
The API checks the token’s validity as usual, plus verifies the accompanying proof matches the token’s bound key and is fresh.
Request accepted or rejected
Only requests passing both the standard token check and the DPoP proof check are processed.
4Data Flow & Lifecycle
sequenceDiagram
participant Client
participant Keycloak
participant API as Resource Server
Client->>Client: Generates key pair (once)
Client->>Keycloak: Token request + DPoP proof (public key)
Keycloak->>Keycloak: Binds token to public key
Keycloak-->>Client: Issues DPoP-bound access token
loop Every API call
Client->>Client: Creates fresh DPoP proof
Client->>API: Sends token + fresh proof
API->>API: Verifies proof matches bound key
alt Valid
API-->>Client: Processes request
else Invalid or stolen token alone
API-->>Client: Rejects request
end
end
Notice the loop in this diagram: unlike a bearer token, which is checked once per request purely by its own signature and expiry, a DPoP-bound token requires this extra proof-generation-and-verification cycle on literally every single API call. This is the direct cost of the added security — more cryptographic work happening continuously, in exchange for meaningfully closing the token-theft gap that plain bearer tokens leave open.
The lifecycle of a DPoP key pair
Generated once per client instance
A key pair is typically created once when an application first initializes, not regenerated for every single login.
Reused across multiple tokens
The same key pair can be used to bind multiple tokens obtained over time by the same client instance, as long as it persists.
Persisted securely on the device
The private key is stored, ideally in hardware-backed secure storage, for as long as the client application remains installed and active.
Retired on uninstall or reset
If the application is uninstalled or the user resets it, the key pair is lost, and any future login requires generating a fresh one.
Because the key pair, not the token, is what actually persists across a client’s lifetime, losing the private key (through a device reset, for example) simply means the client needs to generate a new one and go through the binding process again on its next login — it does not compromise any previously issued tokens.
5Advantages, Disadvantages & Trade-offs
Advantages
- Dramatically reduces the value of a stolen token alone, since it’s useless without the matching private key
- Works without requiring specialized hardware, unlike some alternative token-binding approaches that depend on specific network-layer features
- Standardized, meaning DPoP-aware clients and servers can interoperate across different implementations, not just within Keycloak
- Can be applied selectively, only to the clients and APIs that genuinely need this stronger protection
Disadvantages & Trade-offs
- Requires every client application to correctly generate, securely store, and consistently use cryptographic keys
- Every resource server must add proof verification logic, not just accept a token check as before
- Adds computational overhead to every single API request, not just at login
- Sensitive to clock synchronization issues, since proof freshness depends on accurate timestamps
Upgrading from a simple door lock to a lock requiring both a key and a live fingerprint scan is a real security improvement, but it also means every door needs a fingerprint reader installed, and every key must be paired correctly with its owner’s fingerprint data ahead of time. The security gain is genuine, but so is the added infrastructure and operational complexity required to make it actually work correctly everywhere it’s deployed.
6Security
The specific threat DPoP defends against
DPoP is specifically designed to defend against token exfiltration — scenarios where an attacker gains access to a copy of a valid access token through means other than legitimately obtaining it, such as a cross-site scripting vulnerability, a misconfigured logging system that accidentally records tokens, or network interception. Without DPoP, such an attacker can simply replay the stolen token. With DPoP correctly implemented, the same stolen token is useless without also somehow extracting the private key, which never travels over the network and, ideally, lives in hardware-backed secure storage.
Context
DPoP’s protection depends entirely on the private key genuinely staying private; storing it in easily accessible application memory or unencrypted local storage significantly undermines the whole mechanism.
Decision
Store DPoP private keys in the strongest secure storage available on the client platform — a hardware security module, a mobile device’s secure enclave, or an equivalent — rather than plain application memory or ordinary file storage.
Consequence
An attacker who compromises the application’s general memory or storage still cannot easily extract the private key, preserving DPoP’s core protection even in a partially compromised environment.
Replay protection and proof freshness
Resource servers must track recently seen DPoP proof identifiers within their validity window, rejecting a proof that’s been seen before — otherwise, an attacker who captures a single valid proof-and-token pair could replay it repeatedly within that brief validity window. Correctly implementing this replay-detection logic, alongside strict timestamp checking, is essential to DPoP actually delivering its intended protection rather than only appearing to.
Implementing DPoP verification that checks the proof’s signature and timestamp but forgets to track and reject reused proof identifiers, leaving a narrow but real replay window open within the proof’s validity period.
DPoP does not replace other token security practices
DPoP specifically addresses token theft and replay — it does not, on its own, address other concerns like short expiry times, proper session revocation, or transport security. A complete token security posture still requires HTTPS everywhere, sensible expiry times, and the revocation mechanisms covered elsewhere; DPoP is a powerful additional layer, not a replacement for these fundamentals.
7Monitoring, Logging & Metrics
DPoP proof rejection rate
Tracking how often proofs fail verification, since a rising rate can indicate clock synchronization issues, a client-side bug, or active attack attempts using stolen tokens without a valid matching key.
Clock skew incidents
Logging rejections specifically attributable to timestamp validity failures, helping distinguish legitimate infrastructure issues from genuine security concerns.
Replayed proof detection count
Monitoring how often a resource server catches and rejects a reused proof identifier, since any non-zero rate here deserves investigation as a potential active token-theft attempt.
DPoP-enabled client coverage
Tracking what proportion of an organization’s sensitive clients actually have DPoP enabled and correctly configured, as an ongoing security-posture measurement.
A practical monitoring habit
Security teams operating DPoP-protected APIs often build a specific dashboard panel tracking proof rejection reasons broken down by category — expired timestamp, key mismatch, replayed identifier — since each category points to a different root cause, from a simple infrastructure clock issue to a genuinely serious security event worth immediate investigation.
8Design Patterns & Anti-patterns
Proven patterns
Selective DPoP adoption
Enable DPoP specifically for the clients and APIs handling the most sensitive actions, rather than applying it universally where the added complexity isn’t justified by the actual risk.
Hardware-backed key storage wherever available
Prefer platform-provided secure storage (a device’s secure enclave, a hardware security module) for the DPoP private key over plain in-memory or file-based storage.
Centralized proof verification logic
Build DPoP proof verification into a shared library or middleware used across all resource servers, rather than letting each team implement subtly different, potentially inconsistent verification logic.
Robust time synchronization
Ensure all clients, Keycloak, and resource servers rely on accurate, synchronized time sources, given how sensitive DPoP proof validation is to clock drift.
Anti-patterns to avoid
Anti-pattern
- Storing the DPoP private key in easily accessible, unencrypted application storage
- Verifying only a proof’s signature and timestamp while ignoring replay protection for proof identifiers
- Applying DPoP universally across every client regardless of actual sensitivity, adding complexity without proportional benefit everywhere
- Assuming DPoP alone is sufficient security, neglecting other fundamentals like short token expiry and proper session revocation
Instead, do this
- Use the strongest available secure storage for private keys on each client platform
- Implement full proof verification, including replay-identifier tracking, consistently across every resource server
- Reserve DPoP for genuinely sensitive clients and APIs where the added protection is worth the complexity
- Treat DPoP as one layer among several complementary token security practices, not a standalone solution
9Best Practices & Common Mistakes
Best practices
Use well-tested DPoP libraries
Rely on established, widely reviewed libraries for generating and verifying DPoP proofs rather than implementing the cryptographic details from scratch.
Test clock synchronization across environments
Verify that client devices, Keycloak, and resource servers all maintain accurate, closely synchronized time, especially across distributed or mobile deployments.
Plan for key loss scenarios
Design the client application’s login flow to gracefully handle a lost or reset private key, generating a fresh key pair and re-establishing a new token binding as needed.
Regularly audit which clients actually enforce DPoP
Periodically confirm that DPoP remains correctly enabled and enforced for every client it was intended to protect, since configuration drift over time is a real risk.
Common mistakes
Enabling DPoP on the client side but forgetting to implement corresponding proof verification on the resource server, meaning tokens are correctly bound but the API never actually checks the binding, providing a false sense of security.
Regenerating a fresh key pair on every single app launch instead of persisting it, unnecessarily forcing a full re-binding process far more often than needed and adding friction without any real security benefit.
Underestimating the operational impact of strict timestamp validation, only discovering in production that a subset of devices with meaningfully inaccurate clocks are being incorrectly rejected.
10Real-world & Industry Examples
Open banking and financial APIs
Financial services standards increasingly favor sender-constrained tokens like those DPoP provides, specifically to protect high-value transaction APIs from token theft scenarios that plain bearer tokens can’t defend against.
Healthcare data platforms
Systems handling sensitive patient data adopt DPoP for APIs where a stolen token could otherwise expose protected health information, adding a meaningful extra barrier beyond standard token controls.
Mobile-first applications with secure hardware
Applications on modern smartphones, which typically include hardware-backed secure key storage, are well-positioned to adopt DPoP with strong private-key protection built directly into the device itself.
Government and defense-adjacent systems
Organizations subject to strict security requirements around credential and token handling use DPoP as part of a broader defense-in-depth strategy against token exfiltration risks.
A representative scenario
A healthcare technology company handling patient records discovered, during a security review, that a third-party JavaScript library used on one of their pages had a vulnerability that could allow an attacker to read tokens stored in browser memory. Rather than relying solely on shortening token lifetimes, they enabled DPoP for their most sensitive API, requiring proof of key possession on every call — meaning even if the vulnerable library did leak a token, an attacker still couldn’t use it without also somehow extracting a private key that never left the browser’s secure key-storage mechanism.
11FAQ
12Summary and Key Takeaways
Key Takeaways
- DPoP cryptographically binds an access token to the specific client that requested it, upgrading it from a “bearer” token to a “sender-constrained” one.
- It defends specifically against token theft and replay attacks, where a stolen token alone would otherwise be enough for an attacker to gain access.
- Every request requires a fresh, signed DPoP proof, generated with the client’s private key and verified by the resource server against the token’s bound public key.
- The protection is only as strong as the secrecy of the private key — hardware-backed secure storage significantly strengthens DPoP’s real-world security value.
- Resource servers must implement full verification, including replay-identifier tracking, not just signature and timestamp checks, for the protection to be complete.
- DPoP adds real complexity and overhead — key management, verification logic, and sensitivity to clock synchronization — making it best suited to genuinely sensitive clients and APIs rather than universal adoption.
- It is a complementary layer, not a replacement, for other token security fundamentals like HTTPS, short expiry, and proper session revocation.
- Real-world adoption concentrates in high-sensitivity domains — financial services, healthcare, government systems — where the consequences of token theft justify the added implementation effort.