Start with Identity
SWI-T008 · Session and tokens

Refresh token abuse

A refresh token exists to let an app get new access tokens without bothering the user again. Stolen, it lets an attacker do the same thing indefinitely, surviving password resets along the way.

WidespreadHard to detect to detect
First observed: 2018ATT&CK T1528

How it works

OAuth access tokens are deliberately short-lived, often valid for an hour or less, to limit the damage if one leaks. A refresh token is what makes that usable: it is a longer-lived credential the client presents to the identity provider to get a fresh access token without asking the user to sign in again. Refresh tokens are what device-code phishing, AITM proxies, and malicious OAuth consent grants are actually after, because a stolen access token expires quickly on its own, while a stolen refresh token keeps producing new ones for as long as it stays valid, which for many identity providers means weeks or months, renewed automatically every time it is used.

Once an attacker holds a refresh token, they run it through the same token endpoint the legitimate application uses, requesting new access tokens on their own schedule. The requests look like normal application behavior at the protocol level, because they are the same requests the real client makes.

Why it works

Refresh tokens exist specifically to reduce user friction, and reducing friction means reducing the number of checkpoints where a defender or the user could notice something wrong. A stolen refresh token requires no further interaction from the victim at all: no MFA prompt, no login screen, nothing for the user to see or approve, because the exchange happens entirely between the attacker's client and the token endpoint. Many implementations also do not bind the refresh token to the specific device or client that first received it, so it works identically wherever it is presented. A password reset addresses the credential that produced the original tokens, not the tokens already issued, so it frequently does nothing to stop ongoing refresh token use.

How to detect it

  • Refresh token exchanges from an IP, client ID, or device that differs from the one the original grant was issued to.
  • Token refresh activity continuing at a normal cadence after a password reset or account lockout, which indicates the reset did not reach the standing tokens.
  • Access patterns that continue for weeks with no corresponding new interactive sign-in event in the logs.

Be honest about the limits: legitimate refresh token use from a new IP happens constantly, when a user travels, changes networks, or uses a mobile device with a rotating carrier address, so IP change alone is a weak signal. The stronger signal is refresh activity that survives a credential reset, since that is the behavior a legitimate client's tokens should not show.

How to stop it

  • Revoke refresh tokens explicitly as part of password reset and incident response, not just the password itself; a reset that leaves tokens standing has not actually removed access.
  • Shorten refresh token lifetimes and require re-authentication periodically rather than allowing indefinite silent renewal.
  • Bind tokens to a device or client using DPoP so a copied refresh token fails when replayed from a different device.
  • Rotate refresh tokens on every use and invalidate the entire family if an old, already-rotated token is presented again, which flags a replay attempt.
  • Monitor OAuth application consents and grants for unfamiliar apps requesting offline access, since that scope is what produces a long-lived refresh token in the first place.

Seen in the wild

Sources

Last reviewed By SWI Community TeamSuggest a correctionHow we research
Seeing this technique used differently, or have a detection rule that works better? Email [email protected]. See all briefs in the technique catalog, or volunteer as a CVE Analyst.
Mapped to MITRE ATT&CK where a technique ID exists. Independent, community-driven analysis, not a substitute for the ATT&CK knowledge base. See the disclaimer.