Blog · July 5, 2026

What Is DPoP? Sender-Constrained Tokens in Plain English (and How Okta Supports It)

DPoP, short for Demonstrating Proof of Possession, is one of the quieter but more important upgrades to OAuth token security — and Okta supports it. This is a plain-English guide to what DPoP is, how sender-constrained tokens differ from ordinary bearer tokens, and why API service apps and non-human identities benefit the most.

The problem with bearer tokens

Most OAuth access tokens today are bearer tokens. The name is the whole story: whoever bears the token gets access, no questions asked. A bearer token is like cash. If it falls out of your pocket and someone picks it up, it spends exactly the same for them as it did for you. The resource server — the API you are calling — has no way to tell the legitimate holder apart from a thief, because possession alone is the proof.

That model is fine right up until a token leaks. Tokens end up in logs, in error traces, in a proxy that shouldn't have kept them, in a browser's memory, or in a compromised dependency. Once a valid access token is copied, an attacker can replay it against your API until it expires, and short lifetimes only shrink the window rather than closing it. This is the exact weakness that Demonstrating Proof of Possession is designed to remove.

What DPoP actually means

DPoP stands for Demonstrating Proof of Possession, and it is defined in the OAuth standard RFC 9449. The core idea is simple: instead of a token that works for anyone who holds it, DPoP produces a token that is bound to a cryptographic key the client holds. To use the token, you must prove you still control that key. Possession of the token is no longer enough on its own.

Tokens that carry this binding are called sender-constrained tokens, because the token is constrained to a specific sender — the client that proved it holds the key. A sender-constrained token behaves less like cash and more like a boarding pass with your name on it: holding the paper isn't enough, you also have to be the person it belongs to.

The DPoP proof: a small signed JWT

The mechanism behind all of this is a short-lived JSON Web Token called the DPoP proof. Before it asks Okta for a token, the client generates a public/private key pair and keeps the private key to itself. It then builds a small JWT, embeds its public key in that JWT's header, and signs the whole thing with the matching private key. This signed proof travels in an HTTP request header named, fittingly, DPoP.

When the authorization server issues the access token, it records a fingerprint of that public key inside the token. From that moment on, the token and the key are married. The private key never leaves the client and is never sent over the wire — only proofs signed by it are.

How the resource server checks it

On every call to your API, the client sends two things together: the access token and a fresh DPoP proof JWT signed with its private key. The resource server does two checks. First, it verifies the proof's signature using the public key embedded in the proof, which confirms the caller actually holds the private key. Second, it confirms that the public key in the proof matches the key fingerprint that was baked into the access token when it was issued.

If both checks pass, the caller has demonstrated proof of possession and the request is honored. If the token was presented without a valid, matching proof, it is rejected. The API is no longer trusting the mere presence of a token — it is trusting a live cryptographic demonstration that the caller still holds the right key.

Why a stolen DPoP token is useless

Here is the payoff. Suppose an attacker manages to copy a DPoP-bound access token from a log or a memory dump. They now hold the token — but they do not hold the private key, and the private key never appeared in any request they could have captured. When they try to call the API, they cannot produce a valid DPoP proof that matches the token's bound key, so the resource server turns them away. The stolen token is inert.

To make replay even harder, each DPoP proof carries a unique identifier, the jti, and servers can remember the identifiers they have already seen for a short window and reject any duplicate. Okta and other servers can also hand back an opaque nonce that a proof must include, which forces proofs to be recent and specific to the current interaction rather than something an attacker prepared in advance. The high-level takeaway is that replaying a captured proof is designed to fail.

How Okta lets a service app require DPoP

Okta supports DPoP as an application-level setting, and it fits especially cleanly with API service apps that use the OAuth 2.0 client credentials flow. For that flow Okta uses the private_key_jwt client authentication method, so a service app already proves who it is with a private key rather than a shared password. Turning on DPoP layers sender-constraining on top: the access tokens Okta issues to that app become bound to the app's DPoP key, and the app must present a matching proof on every call it makes.

In practice you configure the service app to require DPoP, the client generates and holds its key pair, and from then on Okta issues sender-constrained tokens instead of plain bearer tokens. Nothing about the app's actual permissions changes — DPoP only changes what it takes to use a token that has already been issued.

Why non-human identities benefit most

Human sign-ins already lean on strong session protections, phishing-resistant authenticators, and device signals. Machine-to-machine access is where bearer tokens quietly do the most damage, because a service account's token can grant broad, standing access to an API and often lives inside automation that runs unattended. If that token leaks, there is no human to notice anything is off.

This is exactly the surface that API service apps and other non-human identities occupy, and it is why DPoP matters so much for them. Sender-constraining a machine's tokens means a leaked token is no longer a usable credential on its own — a meaningful improvement for the identities that are hardest to watch. It is also worth pairing this post with our companion piece on how private key JWT and DPoP both beat a shared client secret, since the two techniques are complementary: one hardens how a service app proves who it is, the other hardens how its tokens can be used.

Where assessment fits in

Knowing DPoP exists is one thing; knowing which of your service apps are actually configured to use it, and which are still leaning on plain bearer tokens or shared secrets, is another. That gap is easy to lose track of as integrations pile up over the years, and it is exactly the kind of drift a read-only assessment is built to surface across an org.

Atomation itself practices what it checks: it connects to your Okta org with DPoP-bound tokens and no shared secret, and it only ever reads and flags — it never changes a setting. So the tool inspecting your token security is held to the same sender-constrained standard it is looking for elsewhere.

Bearer tokens trust whoever holds them. DPoP tokens don't. See how your own org's service apps and token settings hold up, the demo is open, no signup: demo.atomation.io.

Get started

Check your Okta token security in minutes

Request a scoped Okta assessment. We'll align the baseline around your org count, reporting needs, evidence requirements, and delivery model.