Refresh Tokens in OAuth 2.0

Refresh Tokens in OAuth 2.0

Ever wonder why apps like Spotify or Slack keep you logged in for months without ever asking you to type your password again — yet a stolen session still can't last forever? Meet the quiet workhorse behind that balance: the refresh token.

Picture a hotel guest who’s staying for a month. The front desk doesn’t give her a keycard that lasts the entire thirty days — that would be dangerous if the card were ever lost or copied. Instead, they give her a keycard that expires every 24 hours, and a separate, more carefully guarded voucher she can bring back to the front desk each morning to get a brand-new keycard, no re-check-in required. In OAuth 2.0, that short-lived keycard is the access token, and that special voucher is the refresh token. This article explains exactly what refresh tokens are, why they exist, how they’re used, and what can go wrong if they’re handled carelessly.

01

TThe Problem: Short Tokens vs. Long Sessions

To understand why refresh tokens exist, you first need to understand a tension at the heart of OAuth 2.0: shorter-lived tokens are safer, but nobody wants to log in every hour.

Recall that in OAuth 2.0, once you approve an app’s access, the Authorization Server hands that app an access token — a small, digital permission slip the app presents to a Resource Server every time it wants your data. From a security standpoint, the ideal access token would expire almost immediately, so that if it were ever stolen, it would become useless within minutes. But from a user-experience standpoint, nobody wants to re-enter their password and click through a consent screen every fifteen minutes just to keep using an app.

This is a classic trade-off between security and convenience, and OAuth 2.0 resolves it with a clever split: issue an access token that’s short-lived and disposable, and issue a second, separate token — the refresh token — that’s longer-lived, more tightly protected, and used for exactly one purpose: getting a brand-new access token without bothering the user again.

i
Key Idea

A refresh token is never sent to a Resource Server to access data directly. Its only job is to be presented back to the Authorization Server in exchange for a fresh access token. Think of it as a “renewal voucher,” not a “key” in its own right.

2
TOKENS ISSUED IN A TYPICAL FLOW
0
RE-LOGINS NEEDED DURING REFRESH
1
SERVER TRUSTED TO ISSUE BOTH
02

WWhat a Refresh Token Actually Is

A refresh token is a credential issued by the Authorization Server, alongside the access token, that a Client can redeem later for a new access token — without requiring the Resource Owner to log in again.

Structurally, a refresh token is usually just an opaque string of random-looking characters, with no readable information inside it (unlike some access tokens, which can be structured and inspectable). Its opacity is intentional: since the Authorization Server is the only party that will ever need to understand it, there’s no reason to make it self-describing, and keeping it opaque makes it harder for an attacker to learn anything just by looking at it.

Everyday Analogy

Think of a laundromat that gives you a stack of coin tokens instead of letting you pay cash into the machine directly. Each individual token (the access token) works in the washing machine for exactly one cycle, then it’s spent and useless. But you’re also given a receipt (the refresh token) that you can bring back to the attendant’s counter to get more coin tokens, as many times as your receipt is valid for, without having to show your ID or pay again each time.

Access Token

Short-Lived, Used Often

Sent with every single API request to a Resource Server. Typically expires in minutes to a few hours.

Refresh Token

Long-Lived, Used Rarely

Sent only to the Authorization Server, only when the access token has expired or is about to. Typically valid for days, weeks, or until revoked.

Storage

Guarded More Tightly

Because a refresh token is so much more powerful over time, it must be stored more securely than an access token — never in a place readable by page scripts, for example.

Scope

Inherits, Never Expands

A refresh token can only be used to obtain new access tokens with the same or a narrower set of permissions than were originally approved — never broader ones.

03

HHow the Refresh Flow Works, Step by Step

Refresh tokens come into play after the very first login is already done. From that point forward, they quietly keep the session alive behind the scenes.

1

Initial Login Issues Both Tokens

The first time you log in and approve access, the Authorization Server sends the Client both an access token and a refresh token in the same response.

2

The Client Uses the Access Token Normally

For every request to the Resource Server, the Client attaches the current access token. Life goes on as usual, and you don’t notice anything happening in the background.

3

The Access Token Expires

After its short lifetime is up, the Resource Server starts rejecting the old access token with an “expired” or “unauthorized” response.

4

The Client Presents the Refresh Token

The Client, without involving you at all, quietly sends the refresh token to the Authorization Server’s token endpoint, asking for a new access token.

5

A Fresh Access Token Is Issued

The Authorization Server checks that the refresh token is still valid and hasn’t been revoked, then issues a brand-new access token — and, often, a brand-new refresh token as well.

sequenceDiagram
    participant C as Client (App)
    participant AS as Authorization Server
    participant RS as Resource Server

    Note over C,AS: Initial login already completed
    C->>RS: Request with Access Token
    RS-->>C: 401 Expired
    C->>AS: Send Refresh Token
    AS->>AS: Validate refresh token
    AS-->>C: New Access Token (+ new Refresh Token)
    C->>RS: Retry request with new Access Token
    RS-->>C: Data returned
        
FIG. 1 — Using a refresh token to renew an expired access token, with no user involvement
i
Why the User Sees Nothing

Because the refresh happens entirely between the Client and the Authorization Server, with no browser redirect and no consent screen, this whole exchange typically happens in the background in well under a second — which is exactly why you can leave an app open for weeks and never notice a re-authentication happening.

04

RRotation: Why Refresh Tokens Change Every Time

Many modern systems don’t just reuse the same refresh token forever — they replace it with a new one on every single use. This pattern is called refresh token rotation, and it exists purely to catch thieves.

Under rotation, every time a refresh token is redeemed, the Authorization Server immediately invalidates the old one and issues a brand-new refresh token alongside the new access token. The Client is expected to store this new refresh token and discard the old one. This might sound like a minor implementation detail, but it creates a powerful security trip-wire.

Everyday Analogy

Imagine a train pass that automatically becomes a brand-new pass, with a new serial number, every single time you tap it at the gate — and the old serial number stops working the instant the new one is issued. If a pickpocket ever copies your pass and tries to use their copy after you’ve already tapped in with the real one, their copy is instantly dead on arrival. And if the thief uses their copy first, your legitimate tap will fail, immediately signalling to the transit system that something is wrong with that pass family.

CONCEPT — TOKEN REUSE DETECTION SECURITY CONTROL
What It Catches

If an already-used (and therefore invalidated) refresh token is ever presented again, the Authorization Server treats this as strong evidence that the token was stolen and copied by an attacker at some point.

What Happens Next

A well-implemented Authorization Server responds by immediately revoking the entire chain of tokens tied to that session — not just the reused one — forcing a full re-login and locking out both the legitimate user and the attacker until fresh credentials are provided.

Why It Matters

Without rotation, a single stolen refresh token could quietly work forever, side by side with the legitimate one, since nothing would ever flag the duplication.

05

SStorage, Trade-offs & Common Mistakes

A refresh token is far more dangerous in the wrong hands than a single access token, simply because of how long it lasts and how much it can be exchanged for. Where and how it’s stored is one of the most consequential decisions in an OAuth implementation.

Benefits of Refresh Tokens

  • Keeps access tokens short-lived without forcing frequent re-logins
  • Sessions can last for weeks or months with strong security guarantees
  • Rotation makes stolen or copied tokens detectable, often in real time
  • Refresh tokens can be individually revoked to end one device’s session without logging out everywhere

Trade-offs to Manage

  • A stolen, un-rotated refresh token can grant an attacker long-term access
  • Public clients (mobile apps, single-page web apps) have no fully safe place to store a long-lived secret
  • Rotation adds implementation complexity — every client must correctly store the newest token every time
  • Revocation lists and reuse-detection logic add operational overhead for the Authorization Server
!
Common Mistake

Storing a refresh token in a browser’s local storage, where it’s readable by JavaScript, is one of the most frequent real-world OAuth mistakes. If a website has any cross-site scripting vulnerability, an attacker’s injected script can simply read local storage and steal the refresh token outright. Safer patterns include storing it in an HTTP-only cookie (unreadable by page scripts) or, on native mobile apps, in the operating system’s dedicated secure credential storage.

“An access token that leaks costs you minutes of exposure. A refresh token that leaks, left unrotated, can cost you months — which is exactly why it deserves a much stronger lock.”
06

FFrequently Asked Questions

Q1Does every OAuth 2.0 flow issue a refresh token?
No. Refresh tokens are typically only issued for flows expected to need long-lived access, such as the Authorization Code flow used by web and mobile apps. Some short-lived, machine-to-machine flows skip refresh tokens entirely and simply request a brand-new access token each time.
Q2Can a refresh token be used to access my data directly?
No. A refresh token is only ever accepted by the Authorization Server’s token endpoint, in exchange for a new access token. A Resource Server will always reject a refresh token if it’s mistakenly presented as if it were an access token.
Q3What happens if I revoke an app’s access — does the refresh token stop working immediately?
Yes, in a properly built system. Revoking access from your account settings page invalidates the refresh token (and any active access tokens) tied to that app right away, so the next refresh attempt or API call will fail.
Q4Why do refresh tokens sometimes last “forever” until manually revoked?
Some Authorization Servers issue refresh tokens with no fixed expiration, relying instead on rotation and reuse detection to catch misuse, plus an idle-timeout rule that expires the token if it hasn’t been used in a long stretch of time, such as 30 or 90 days.
Q5Is a refresh token the same thing as a “remember me” cookie?
They solve a similar problem — staying logged in without repeated passwords — but they’re different mechanisms. A “remember me” cookie usually keeps a website session alive directly, while a refresh token is a formal OAuth 2.0 credential exchanged specifically for new access tokens, often across multiple different apps and APIs.
07

SSummary and Key Takeaways

What to Remember

  • A refresh token is a long-lived credential used only to obtain new access tokens from the Authorization Server — never sent to a Resource Server directly.
  • Splitting tokens into a short-lived access token and a long-lived refresh token resolves the tension between strong security and a smooth, uninterrupted user experience.
  • The refresh exchange happens silently between the Client and the Authorization Server, with no browser redirect or consent screen needed.
  • Refresh token rotation issues a brand-new refresh token on every use and invalidates the old one, turning any reuse of an old token into an instant, detectable red flag.
  • Because refresh tokens are so powerful over such a long window, they require stronger storage protection than access tokens — HTTP-only cookies or OS-level secure storage, never plain browser local storage.
  • Revoking an app’s access should immediately invalidate its refresh token, cutting off both current and future access without requiring a password change.