RFC 9700 says refresh tokens for public clients must be sender constrained or use refresh token rotation. Rotation detects theft after the fact by invalidating reused tokens. Sender constraint, such as DPoP, prevents use of a stolen token in the first place. Using both gives the best coverage.
Why refresh tokens need extra care
An access token is short lived. A refresh token can mint new ones for days or weeks, so it is a more valuable target. Public clients such as browser and mobile apps cannot authenticate with a secret, which means a stolen refresh token is usable by anyone who has it.
Approach 1: refresh token rotation
Each time the client uses a refresh token, the server returns a new refresh token and invalidates the old one. If a thief and the real client both use tokens from the same family, one of them will present an already used token.
When the server sees a reused token, the common response is to revoke the whole family so that neither party can continue. The user signs in again.
Strengths:
- No client key management.
- Works with any public client.
Limits:
- Detection happens after a theft, not before. A thief who uses the token first gets a working session until the real client's next refresh triggers the revoke.
- Flaky networks can cause a legitimate retry to look like reuse. Some servers allow a short grace window to tolerate it.
Approach 2: sender constrained tokens
With DPoP or mutual TLS, the refresh token is bound to a client key. Presenting it without a valid proof fails. See DPoP explained.
Strengths:
- A stolen token alone is useless.
- Prevents the first use, not just later ones.
Limits:
- Needs support in the authorization server and client library.
- Does not help if malicious code can use the key inside the client.
Comparison
| Rotation | Sender constraint | |
|---|---|---|
| Stops first use of stolen token | No | Yes |
| Detects theft | Yes, on reuse | Not by itself |
| Client complexity | Low | Moderate |
| Server support needed | Common | Newer, growing |
Practical advice
- Turn on rotation for every public client now. It is widely supported.
- Add sender constraint where your stack supports it.
- Set an absolute session lifetime, so a refresh chain cannot run forever.
- Revoke the family on reuse and log the event as a security signal.
- Store refresh tokens in the most protected storage the platform offers, and avoid browser local storage where you can.
Quick check
Do confidential clients need rotation?
They authenticate with a secret, which already limits use of a stolen token. The RFC requirement is specific to public clients, though rotation is still cheap protection.
What if rotation locks out honest users on bad networks?
Some servers allow a brief grace period for the previous token. Treat that as a tuning decision and keep it short.
Sources
- RFC 9700, Best Current Practice for OAuth 2.0 Security
- RFC 9449, OAuth 2.0 Demonstrating Proof of Possession
Last reviewed: 19 October 2026.