What is Refresh Token Rotation in Keycloak?

What is Refresh Token Rotation in Keycloak?

A refresh token that never changes is a single key that works forever. Rotation swaps that one permanent key for a fresh one every single time it's used — turning a static secret into a moving target.

Imagine a library card that, instead of staying the same forever, gets automatically replaced with a brand-new card number every single time you check out a book, with the old number immediately deactivated. If a stranger ever copied your old card number, it would already be useless the very next time you visited the library — you’d have quietly moved on to a new one. This is essentially what Refresh Token Rotation does inside Keycloak: every time a refresh token is used to get a new access token, Keycloak can be configured to also hand back a brand-new refresh token, immediately retiring the old one. This guide explains what refresh tokens are, why rotating them matters, what happens internally on every refresh, and how real deployments configure and monitor this behavior safely. No prior background in token systems is assumed.

1Core Concepts

Before rotation makes sense, you need a clear picture of what a refresh token actually does, and why it’s treated so differently from an access token.

What is a refresh token, and why does it exist?

Access tokens are deliberately short-lived — often valid for just a few minutes — to limit how long a stolen one remains useful. But asking a user to fully log in again every few minutes would be unbearable. The refresh token solves this: it’s a longer-lived credential that lets an application quietly obtain a brand-new access token, behind the scenes, without bothering the user at all. As long as the refresh token remains valid, the user’s session effectively continues seamlessly, even though each individual access token expires quickly.

What does “rotation” actually mean here?

Without rotation, a single refresh token can be used over and over again, for as long as it remains valid — sometimes for hours, days, or even longer, depending on configuration. Refresh Token Rotation changes this: every time the refresh token is used, Keycloak issues both a new access token and a brand-new refresh token, and immediately invalidates the one that was just used. The refresh token, in other words, is single-use — spend it once, and a fresh replacement takes its place.

Analogy

Think of a subway system that issues a fresh, single-use transfer ticket every time you tap through a gate, immediately voiding the ticket you just used. If someone photographs your ticket while it’s in your hand, the photograph becomes worthless the moment you actually tap through, because a new ticket has already replaced it. A system that instead let the same ticket be tapped indefinitely would make a single photographed copy dangerous for as long as that ticket remained valid.

Why does rotation matter for security?

If a refresh token is somehow copied — through a compromised device, a logging mistake, or intercepted network traffic — and rotation is not in place, that stolen copy remains just as valid as the legitimate one, for as long as it hasn’t expired. With rotation enabled, the moment either the legitimate client or the attacker uses the token, a new one is issued and the old one is dead. This doesn’t just limit a stolen token’s usefulness — it creates a detectable signal: if the token that was already used and invalidated is presented again, Keycloak knows something is wrong.

i
Where you’d meet this

Single-page applications running entirely in a browser, mobile apps storing tokens on a device, and any client where a refresh token might realistically be exposed to logging, caching, or interception are exactly where refresh token rotation is most valuable.

Key vocabulary, explained simply

Term

Refresh Token

A longer-lived credential used to obtain new access tokens without requiring the user to log in again.

Term

Token Rotation

The practice of issuing a brand-new refresh token every time the current one is used, immediately invalidating the one just used.

Term

Refresh Token Reuse Detection

Keycloak’s mechanism for spotting when an already-invalidated, previously used refresh token is presented again — a strong signal of token theft.

Term

Grace Period

A brief window during which a just-rotated, technically old refresh token may still be accepted, accommodating minor timing issues without treating every retry as an attack.

Term

Session

The underlying server-side login record that a chain of rotated refresh tokens are all ultimately tied back to.

Term

Public Client

A client type (typical of single-page apps and mobile apps) that cannot securely hold a permanent secret, making refresh token protection especially important.

2Architecture & Components

Refresh token rotation is implemented as a specific behavior of Keycloak’s token endpoint, backed by session-tracking logic that remembers exactly which refresh token is currently the valid one for a given session.
graph TB
    C[Client] -->|presents refresh token| TE[Keycloak Token Endpoint]
    TE --> CHK{Is this the current
valid refresh token
for the session?} CHK -->|yes| ISSUE[Issues new access token
+ new refresh token] ISSUE --> SS[Updates Session Store
with new valid token reference] ISSUE --> INV[Invalidates old refresh token] CHK -->|no - already used| REUSE[Reuse Detected] REUSE --> REVOKE[Revokes entire session
as a precaution]
FIG 1 — Every refresh either advances the session to a new valid token, or triggers reuse detection

Component breakdown

Component

Token Endpoint Refresh Logic

The specific part of Keycloak’s token endpoint responsible for handling refresh-grant requests, checking token validity, and issuing rotated replacements.

Component

Session Store’s Current-Token Reference

Keycloak’s session record keeps track of which refresh token is currently the valid, “live” one for that session, updating it with every successful rotation.

Component

Realm/Client Rotation Policy

A configuration setting controlling whether rotation is enabled at all, and related behaviors like the grace period for near-simultaneous refresh attempts.

Component

Reuse Detection and Response

Logic that recognizes an already-invalidated refresh token being presented again, and decides how to respond — typically by revoking the entire underlying session as a precaution.

Where this is configured in the admin console

Inside the Keycloak Admin Console, refresh token behavior, including rotation-related settings, is typically found under Realm Settings → Tokens, or in specific client advanced settings for per-client overrides. Administrators can control whether refresh tokens are reused or rotated, and tune related session and token lifetime settings that interact with rotation behavior.

A common real setup

A single-page application, classified as a public client since it can’t securely store a permanent secret, is configured with refresh token rotation enabled. Every time the browser-based app silently refreshes its access token in the background, it also receives and stores a new refresh token, discarding the old one, so even if browser storage were somehow inspected by malicious code, only the currently valid token — not a long history of still-usable ones — would be exposed at any given moment.

Why is this handled at the session level, not just the token level?

Tracking “which specific refresh token is currently valid” has to be tied to the broader session record, not just evaluated in isolation per token, because rotation is fundamentally about maintaining a single, continuously advancing chain of trust for one login. The session is the anchor; the rotating refresh tokens are simply the current “state” of that anchor at any given moment, updated with each legitimate use.

3Internal Working

Two internal behaviors define rotation: the normal, successful refresh path, and the exceptional, security-critical reuse-detection path that fires when something looks wrong.

The normal refresh path

When a client sends a valid, currently-live refresh token to Keycloak’s token endpoint, Keycloak checks that this token matches the one it has on record as the current valid token for that session. If it matches, Keycloak generates a new access token and a new refresh token, updates the session record to mark this new refresh token as the current valid one, and returns both to the client. The refresh token that was just presented is now considered spent — any future attempt to use it again will not match the session’s updated record.

The reuse-detection path

If a refresh token is presented that Keycloak recognizes as having already been used and replaced — meaning it no longer matches the session’s current valid token — this is treated as a red flag. The most likely explanations are either a legitimate but delayed retry (handled gracefully within a short grace period) or, more seriously, an attacker attempting to use a stolen, already-superseded token. Because Keycloak generally cannot distinguish these two cases with certainty, its typical response is to revoke the entire session as a precaution, forcing both the legitimate user and any potential attacker to re-authenticate from scratch.

“Rotation doesn’t just limit how long a stolen token works — it turns any attempted reuse into a detectable event.”

Why the grace period exists

In real-world network conditions, a client might occasionally send two refresh requests in quick succession — due to a retry after a slow or dropped response, for example — even though only one was truly intended. Without any tolerance, this could cause Keycloak to treat a harmless double-request as an attack and needlessly revoke a legitimate session. A short grace period allows a very recently superseded refresh token to still be accepted briefly, reducing false positives while still closing the door on any meaningfully delayed reuse attempt.

!
Gotcha

A grace period that’s set too generously weakens the security benefit of rotation, since it widens the window during which a genuinely stolen, already-used token could still be replayed successfully — this setting deserves deliberate tuning, not just a default left unexamined.

Step-by-step: a single refresh cycle with rotation enabled

1

Access token nears expiry

The client detects its current access token is about to expire and prepares to refresh.

2

Refresh request sent

The client sends its current refresh token to Keycloak’s token endpoint.

3

Keycloak validates against session record

Keycloak checks that the presented refresh token matches the session’s current valid one.

4

New tokens issued

A fresh access token and a fresh refresh token are generated and returned to the client.

5

Session record updated

Keycloak updates its record of the current valid refresh token to the newly issued one.

6

Old refresh token retired

The token just used becomes invalid for any future refresh attempt, outside the brief grace period.

4Data Flow & Lifecycle

Seeing a normal refresh chain alongside a theft scenario side by side makes clear exactly how rotation converts an invisible risk into a visible, actionable security event.
sequenceDiagram
    participant Client as Legitimate Client
    participant Keycloak
    participant Attacker

    Client->>Keycloak: Refresh Token A
    Keycloak-->>Client: New Access Token + Refresh Token B
    Note over Attacker: Somehow obtains a copy
of Refresh Token A Attacker->>Keycloak: Refresh Token A (already used) Keycloak->>Keycloak: Detects reuse of superseded token Keycloak-->>Attacker: Rejected Keycloak->>Keycloak: Revokes entire session as precaution Client->>Keycloak: Refresh Token B (now also invalid) Keycloak-->>Client: Rejected - must log in again
FIG 2 — A theft attempt using an already-rotated token triggers detection and full session revocation

Notice the outcome in that diagram: both the attacker and the legitimate client end up needing to log in again once reuse is detected. This is an intentional, if slightly inconvenient, trade-off — Keycloak cannot reliably tell which party is the legitimate one once an already-superseded token has been replayed, so the safest response is to end the session for everyone and force a fresh, verified login.

The lifecycle of a rotating refresh-token chain

A

Initial issuance at login

The first refresh token in the chain is issued alongside the first access token, right after a successful login.

B

Repeated rotation during active use

Each subsequent refresh replaces the current token with a new one, extending the session’s usable life without requiring re-login.

C

Chain continues until session ends

This rotation cycle repeats indefinitely, as long as the session itself remains active and within its overall timeout limits.

D

Chain broken by logout, timeout, or detected reuse

A logout, an idle or absolute session timeout, or a detected reuse event ends the chain entirely, requiring a fresh login to start a new one.

i
Worth noting

Rotation extends how long a session can silently continue without requiring re-authentication, but it doesn’t remove the underlying session’s own absolute or idle timeout limits — those still apply on top of, and independently from, the refresh-token rotation mechanism itself.

5Advantages, Disadvantages & Trade-offs

Rotation meaningfully narrows the window a stolen refresh token remains useful, but that narrower window comes with its own operational and reliability considerations.

Advantages

  • Sharply limits how long a stolen refresh token remains usable — often to a single use, rather than its full remaining lifetime
  • Converts silent token theft into a detectable event, since reuse of a superseded token is a clear signal something is wrong
  • Particularly valuable for public clients (browser and mobile apps) that cannot securely hold long-lived secrets
  • Requires no change to how a well-behaved client already refreshes tokens — the rotation happens transparently as part of the normal refresh response

Disadvantages & Trade-offs

  • A poorly written client that doesn’t correctly store and use the newest returned refresh token can accidentally lock itself out
  • Legitimate retry logic (from flaky networks) can occasionally trigger unnecessary reuse-detection responses without a well-tuned grace period
  • Applications running multiple tabs or processes sharing one refresh token without careful coordination can race against each other, each thinking it holds the current valid token
  • Adds a small amount of extra state management complexity to Keycloak’s session tracking compared to a simple, unrotated refresh token
Analogy

Rotation is like a relay race baton that must be handed off cleanly at each exchange point. If every runner passes it correctly, the race continues smoothly and quickly. But if two runners try to grab the same baton handoff moment at once — say, two browser tabs both trying to refresh using the same stale token — confusion and dropped batons become a real, if manageable, engineering problem to design around.

6Security

Rotation is one of the more effective, relatively low-cost improvements available for reducing the real-world risk of long-lived refresh tokens, but its protection depends on a few details being handled correctly.

Why rotation matters especially for public clients

Public clients — typically single-page applications and mobile apps — cannot hold a client secret securely, since anything embedded in browser-accessible code or a distributed app binary can, in principle, be extracted. This makes their refresh tokens comparatively more exposed to theft through cross-site scripting, malicious browser extensions, or a compromised device, compared to a confidential backend client that can better protect its credentials. Rotation specifically compensates for this weaker baseline protection by ensuring even an exposed refresh token has a very short useful lifespan.

SEC-09Recommended
Context

Public clients face a materially higher risk of refresh token exposure than confidential backend clients, yet some deployments apply the same, unrotated refresh token configuration across all client types by default.

Decision

Enable refresh token rotation specifically for public clients, and treat it as a baseline security requirement rather than an optional enhancement for any browser-based or mobile client.

Consequence

The realistic risk of token exposure for these client types is directly compensated for by sharply limiting how long any single exposed token remains useful to an attacker.

What reuse detection should trigger, beyond just rejection

Simply rejecting a reused, superseded refresh token is the minimum response; a more security-conscious deployment also treats detected reuse as a genuine incident signal worth investigating — potentially notifying the user of the forced session termination, logging the event prominently for security review, and in some cases prompting additional verification on the next login, rather than silently forcing a quiet re-login with no further follow-up.

!
Common mistake

Treating a reuse-detection event purely as a routine error to be silently handled by the client’s normal “please log in again” flow, missing the opportunity to flag what might be a genuine, active token-theft attempt worth security attention.

Rotation complements, but doesn’t replace, other token protections

Rotation specifically limits the window of usefulness for a stolen refresh token; it doesn’t prevent theft in the first place, nor does it address access token theft directly. Combining rotation with secure storage practices, short access token lifetimes, and mechanisms like DPoP for especially sensitive clients provides a more complete defense than relying on rotation alone.

7Monitoring, Logging & Metrics

Reuse-detection events are exactly the kind of signal that deserves active monitoring — each one is a strong, specific indicator that something worth investigating just happened.
1
reuse detection is a strong, specific signal of possible token theft, unlike vague anomaly scores
2
parties affected by a detected reuse event: the legitimate user and, potentially, an attacker
0
tolerance built into rotation for reuse outside the configured grace period
Metric

Reuse-detection event rate

Tracking how often Keycloak detects and responds to superseded refresh token reuse, since any meaningful rate here deserves investigation as a potential sign of active credential theft.

Metric

Grace-period-triggered acceptances

Monitoring how often a technically-superseded token is still accepted within the grace period, to ensure this window isn’t being unintentionally exploited or overly relied upon by flaky client behavior.

Metric

Refresh failure rate by client

Comparing refresh failure rates across different client applications, since a client with a buggy token-storage implementation will show up as an outlier with unusually frequent forced re-logins.

Metric

Session revocations triggered by reuse detection

Specifically isolating how many session terminations were caused by reuse detection versus normal logout or timeout, to separately track this as a distinct security-relevant category.

A practical monitoring habit

Security teams often set up an alert specifically for any spike in refresh-token reuse-detection events concentrated around a single user account or a narrow time window, since this pattern is far more consistent with an active, deliberate theft attempt than the occasional, randomly distributed false positive a poorly tuned grace period might otherwise produce.

8Design Patterns & Anti-patterns

Teams that implement refresh token rotation reliably across real client applications converge on a handful of dependable patterns, and repeatedly trip over the same predictable implementation mistakes.

Proven patterns

Pattern

Always store the latest returned refresh token

Design client code to immediately and reliably persist the newest refresh token from every response, treating the previous one as immediately discarded.

Pattern

Centralized token management for multi-tab apps

For browser-based applications running across multiple tabs, coordinate refresh attempts through a single shared mechanism (like a shared worker or a designated leader tab) to avoid multiple tabs racing to refresh with the same stale token.

Pattern

Well-tuned, narrow grace period

Set the grace period just wide enough to absorb genuine network retry scenarios, without so wide a window that it meaningfully weakens rotation’s security benefit.

Pattern

Treating reuse detection as an incident, not just an error

Route reuse-detection events into security monitoring and incident-response processes, rather than only handling them as an ordinary client-side “please re-login” case.

Anti-patterns to avoid

Anti-pattern

  • Caching an old refresh token in multiple places within a client application, risking an outdated one being accidentally reused
  • Letting multiple browser tabs or app instances independently attempt to refresh using the same shared token without coordination
  • Setting an overly generous grace period that substantially weakens rotation’s core security benefit
  • Ignoring reuse-detection events as routine noise rather than a meaningful security signal

Instead, do this

  • Always replace the stored refresh token immediately and consistently with the latest one received
  • Coordinate refresh attempts across multiple tabs or processes within one client application
  • Keep the grace period narrow, tuned specifically to accommodate realistic retry scenarios only
  • Feed reuse-detection events into active security monitoring and investigation processes

9Best Practices & Common Mistakes

Getting rotation right in practice comes down to disciplined client-side token handling and realistic testing under the exact conditions where race conditions and retries actually occur.

Best practices

1

Test multi-tab and multi-process scenarios explicitly

Deliberately test what happens when a browser-based application has several tabs open simultaneously, all potentially attempting to refresh around the same time.

2

Log and alert on reuse detection distinctly

Ensure reuse-detection events are logged with enough detail to distinguish them clearly from ordinary logouts or expired sessions during later review.

3

Enable rotation as a default for new public clients

Make rotation the standard, default configuration for any newly registered public client, rather than something that needs to be remembered and manually enabled each time.

4

Communicate forced re-logins clearly to users

When reuse detection forces a session termination, present the user with a clear, non-alarming explanation rather than a confusing, unexplained logout.

Common mistakes

!
Mistake

Enabling rotation without updating client-side code to correctly store and use the newest refresh token from every response, causing legitimate users to be unexpectedly logged out during normal use.

!
Mistake

Not accounting for multi-tab browser scenarios, leading to seemingly random, hard-to-reproduce logout issues that are actually caused by two tabs racing to refresh with the same soon-to-be-superseded token.

!
Mistake

Widening the grace period significantly to “fix” perceived reliability issues without first properly diagnosing whether the real problem was a client-side storage or coordination bug rather than a genuinely too-narrow grace window.

10Real-world & Industry Examples

Refresh token rotation has become a widely recommended baseline practice across the industry, particularly as single-page applications and mobile apps have become the dominant way people interact with modern services.
Industry

Consumer-facing single-page applications

Modern web applications built as single-page apps commonly enable refresh token rotation as a standard security baseline, given how exposed browser-stored tokens can be to client-side vulnerabilities.

Industry

Mobile banking and fintech apps

Financial mobile applications frequently combine refresh token rotation with additional protections like secure device storage, treating any detected reuse as a serious, actively investigated security event.

Industry

Enterprise SaaS platforms

B2B software platforms serving many customer organizations often enable rotation across their public-facing client applications as part of a broader security certification and compliance posture expected by enterprise customers.

Industry

API-first platforms with long-lived mobile sessions

Platforms designed to keep mobile users logged in for extended periods without repeated re-authentication rely on rotation to make that convenience safer, limiting how long any individual exposed token remains a real risk.

A representative scenario

A company running a popular single-page web application discovered, through routine monitoring, an unusual spike in refresh-token reuse-detection events concentrated on a small handful of user accounts. Investigation revealed a malicious browser extension some affected users had installed was silently exfiltrating locally stored tokens. Because rotation was already enabled, the actual damage was limited to a narrow window per stolen token, and the reuse-detection alerts gave the security team an early, specific signal to investigate and notify affected users well before the issue might otherwise have been noticed.

11FAQ

Q1Does refresh token rotation require any change to the login process itself?
No. Rotation only affects what happens during a refresh, not the initial login. Users experience no visible difference during a normal, successful login and refresh cycle.
Q2What happens to my session if reuse is detected?
Keycloak typically revokes the entire underlying session as a precaution, since it cannot reliably distinguish a legitimate delayed retry from an actual theft attempt once a superseded token has been reused outside the grace period.
Q3Is rotation necessary for confidential (backend) clients too?
It can still add value, but the risk profile is generally lower for confidential clients that can securely store secrets server-side, so the trade-off between added complexity and security benefit may weigh differently than for public, browser- or device-based clients.
Q4Why did my application suddenly log users out after enabling rotation?
This usually indicates the client isn’t correctly storing and using the newest refresh token from each response, or multiple tabs/processes are racing to refresh with an already-superseded token — both are common integration issues rather than problems with rotation itself.
Q5Does rotation change how long a session can last overall?
Not directly. Rotation governs how the refresh token itself is replaced on each use; the session’s own idle and absolute timeout settings independently determine the overall maximum lifespan.
Q6Can a legitimate user accidentally trigger reuse detection?
It’s possible in edge cases, such as a very delayed network retry falling outside the configured grace period, which is why tuning that grace period appropriately for realistic network conditions matters.

12Summary and Key Takeaways

Key Takeaways

  • Refresh Token Rotation issues a brand-new refresh token with every use, immediately invalidating the one just presented, turning a long-lived secret into a single-use credential.
  • It’s especially valuable for public clients — browser-based single-page applications and mobile apps — that cannot securely hold long-lived secrets.
  • Presenting an already-used, superseded refresh token triggers reuse detection, a strong signal that something — likely token theft — has gone wrong.
  • A carefully tuned grace period absorbs realistic network retries without meaningfully weakening rotation’s core security benefit.
  • Reuse detection typically results in full session revocation as a precaution, since Keycloak cannot reliably distinguish a legitimate retry from an actual attack after the grace period.
  • Correct client-side implementation — always storing the newest returned token and coordinating refreshes across multiple tabs or processes — is essential to avoid unnecessary, confusing forced logouts.
  • Rotation complements, but doesn’t replace, other token security practices like short access token lifetimes and secure storage.
  • Treating reuse-detection events as genuine security incidents, not just routine errors, turns rotation from a passive protection into an active early-warning system.