Standards

Refresh Token

A refresh token is a long-lived credential issued alongside an access token in OAuth 2.0; the client exchanges it for a new access token (and optionally a new refresh token) without prompting the user to re-authenticate.

Last reviewed 5/30/2026

Key points

  • Refresh tokens decouple session length from access-token TTL — short access tokens, longer refresh tokens.
  • MUST be stored securely (httpOnly cookie, secure storage, encrypted DB) — leakage means session takeover.
  • Refresh token rotation (issue a new RT on every use, invalidate the old one) detects theft (RFC 6749, OAuth 2.0 BCP).
  • Public clients (SPAs, mobile) require PKCE + refresh token rotation + short RT lifetimes — and many security teams disable RTs in SPAs entirely.
  • Revocable: the authorization server can invalidate a refresh token to terminate the session.

What is a refresh token?

A refresh token is the OAuth 2.0 credential that lets a client get a fresh access token without asking the user to sign in again. It's how "stay signed in for 30 days" works under the hood, and how server-to-server integrations stay connected across token expiries.

The pattern:

  1. User signs in. The authorization server returns an access token (short, e.g. 15 min) and a refresh token (longer, hours to days).
  2. The client uses the access token to call APIs.
  3. When the access token expires, the client calls /token with grant_type=refresh_token and gets a new one.
  4. If refresh token rotation is enabled, it also gets a new refresh token; the old one is invalidated.

Why rotation matters

Refresh tokens are long-lived. If one leaks (XSS, stolen device, malicious browser extension, stolen mobile backup) the attacker can keep refreshing forever — unless rotation is on. With rotation:

  • Each refresh issues a new RT and invalidates the previous one.
  • If the legitimate client and the attacker both try to use the same RT, the second use is detected as a refresh token reuse, and the entire token family is revoked — forcing both parties to re-authenticate.

This is mandatory for public clients per the OAuth 2.0 Security BCP.

Storage

  • Confidential web app — refresh token lives server-side, never reaches the browser.
  • Mobile — secure enclave / Keychain / Android Keystore.
  • SPA — controversial. Best practice: don't use refresh tokens in the browser; use BFF (backend-for-frontend) pattern + httpOnly cookies. If you must, use rotation + short TTLs + DPoP.

When buyers care

  • After incidents where stolen tokens enabled persistent access (LastPass, CircleCI, GitHub OAuth app compromise, midnight blizzard).
  • When evaluating IdPs: do they support refresh token rotation? Configurable RT lifetime? Revocation API?
  • For B2B integrations: how do you revoke a partner's access cleanly?

Editorial note

If a vendor's docs tell you to "store the refresh token in localStorage," close the tab. That's been a known anti-pattern for years.

Standards & references