Skip to content
Authreads

Protocols and how-tos

Refresh token rotation and reuse detection, explained

How rotating refresh tokens on every use turns a stolen token into a detectable event, how token families work, and the race conditions to plan for.

The short answer

Refresh token rotation means the authorization server issues a new refresh token every time one is used and invalidates the old one. If an old token is ever presented again, either the legitimate client or an attacker is replaying it — the server cannot tell which, so it revokes the whole token family and forces re-authentication. RFC 9700 recommends rotation or sender-constraining for refresh tokens issued to public clients.

Sources last reviewed .

Why refresh tokens need special handling

Access tokens are short-lived, so a stolen one expires quickly. Refresh tokens are long-lived by design and can mint new access tokens for days or weeks. For a public client — a browser or mobile app — there is no client secret, so possession of the refresh token alone is enough to use it.

RFC 9700 section 4.14 gives two acceptable protections for public clients: sender-constrain the refresh token (DPoP or mutual TLS), or rotate it.

How a token family works

Every refresh token descends from one original grant. The server records that lineage. When token N is used, token N+1 is issued and N is marked used. If N is presented again, the server revokes N+1 and every token in the family. The attacker who stole N and the client who holds N+1 both lose access; the user signs in again, and the incident is visible in the logs rather than silent.

The race condition you will hit

Two browser tabs, or a retry after a network timeout, can present the same refresh token twice legitimately. Strict reuse detection then logs the user out. Options: serialise refreshes in the client (one in-flight refresh, shared by all callers); or allow a very short grace window in which the previous token's immediate successor is returned again. A grace window weakens detection slightly, so keep it to seconds and log every use of it.

Checklist

  • Store refresh tokens hashed server-side; they are credentials.
  • Bind each refresh token to the client it was issued to (RFC 6749 section 6 requires the server to verify this).
  • Give the family an absolute lifetime so rotation cannot extend a session forever.
  • Revoke the family on sign-out, password reset and administrator revocation, and support RFC 7009 revocation from the client.

In Authreads

How this applies to Authreads

Per the Authreads developer documentation, refresh tokens are opaque, stored hashed, rotated on every use, and bound to the client and token family; reuse revokes the family, and the revocation endpoint revokes a refresh token family.

Authreads is a multi-tenant identity platform in beta. Capability status is maintained on /roadmap as Available, In progress or Planned.

Questions

Is a JWT refresh token better than an opaque one?

Rarely. A refresh token is only ever read by the authorization server that issued it, so self-contained claims buy nothing, and an opaque handle can be revoked and rotated by a simple database lookup.

Building on any of this?

Tell us what you're putting together. We'll tell you plainly whether Authreads fits it.