Partly. DPoP stops a token that was copied off a device from working elsewhere, because the thief lacks the private key. It does not protect you if hostile code runs inside the client itself. RFC 9449 says that in that case the security of DPoP is no longer guaranteed.
What DPoP adds
DPoP, or Demonstrating Proof of Possession, is an application level way to sender constrain OAuth tokens. The client creates a key pair and sends a signed JWT in a DPoP header with each request. The authorization server binds the issued tokens to the public key. The server then checks that the presenter also holds the matching private key.
The proof carries a handful of claims. The jti is a unique identifier for replay detection, htm and htu name the HTTP method and target URI, iat is the creation time, and when presenting an access token the proof also carries ath, a hash of that token. Because the proof names the method, URL and token, a proof made for one request is not valid for a different one.
Where it helps
If a token leaks from a log file, a proxy, a backup or an analytics SDK, a thief who has only the token cannot call the API. That is the main win for mobile apps, where tokens travel through many layers.
It also makes some refresh token theft harder, since the refresh token is bound to the key as well.
Where it does not help
RFC 9449 lists limits in its security considerations. Three matter for mobile.
| Situation | What RFC 9449 says |
|---|---|
| Hostile code in the app, such as injected or included code | DPoP security is no longer guaranteed |
| Private key in an exportable store | An attacker can copy the key and mint proofs anywhere |
| Private key in hardware or a security module, not exportable | Attacker cannot copy the key but can still create proofs while the client is online and use them with the tokens |
| Attacker controls the client and pre-generates proofs | What is proved is possession of a proof, not of the key |
The pre-generation point deserves attention. An attacker in control of the client can generate proofs for specific endpoints far into the future by choosing the iat value, and copy them to another machine. The specification notes the legitimate user could be that attacker. Servers can limit this by checking that iat is recent and by using the nonce mechanism the specification defines, where the server supplies a nonce that must appear in later proofs.
How to get the most from it on mobile
- Generate the DPoP key in hardware backed storage where the platform offers it, and mark it non exportable.
- Bind access and refresh tokens to that key.
- Keep access token lifetimes short and scopes narrow.
- Verify on the server that htm and htu match the request, that iat is recent, that ath matches the access token, and that jti has not been seen before.
- Use server provided nonces for high value endpoints.
- Treat DPoP as one layer, next to app integrity signals and anomaly detection.
What about malware that can use the app
If malware can run in the app's process or drive the app through accessibility features, it can ask the app to sign requests for it. DPoP cannot tell the difference. The defences there are platform level: keeping the device patched, limiting what the app exposes, and monitoring for unusual behaviour on the server.
Safeguard's asset discovery helps you find API hosts and versions you may have lost track of, and its SBOM and dependency scanning shows which libraries ship in your builds. You can start with the free scan at gold.safeguard.sh/scan.
Quick check
Does DPoP make a stolen access token useless?
For a token copied without the key, yes, the server will reject it. If the attacker also has the key or can use the app, no.
Is a non exportable key enough?
It prevents copying the key, but RFC 9449 notes an attacker running code in the client can still request proofs while the client is online.
Sources
Last reviewed: 19 October 2026.