What Is a Refresh Token in Keycloak? Staying Logged In Without Staying Exposed
A beginner-friendly explanation of Keycloak's refresh token — why access tokens expire so quickly, how a refresh token quietly keeps a user logged in anyway, and what can go wrong when it's handled carelessly.
Imagine a movie theater that only lets you inside for one screening at a time. Your ticket stub is checked at the door, and it expires the moment that specific showing ends — even if you’d love to keep watching another film right after. Rather than making you queue up and buy a brand-new full-price ticket every single time, the theater gives loyal guests a special voucher they can quietly exchange at the counter for a fresh ticket to the next showing, no new payment required, as long as the voucher itself hasn’t expired. In Keycloak, the Refresh Token plays exactly that voucher role — it doesn’t get you into anything directly, but it lets you quietly get a brand-new access token without logging in all over again.
1What Is a Refresh Token?
Let’s start with a clear, plain-English definition before exploring why it’s needed at all.
The Simple Definition
A Refresh Token is a special credential issued by Keycloak, alongside the access token and ID token, when a user successfully logs in. Its only job is to be exchanged, later on, for a brand-new access token, without requiring the user to type in their username and password again. It’s not used to directly prove identity to an application — it’s used strictly in private, background conversations between the application and Keycloak itself.
Think of the access token as a visitor badge that expires after fifteen minutes, and the refresh token as your appointment confirmation at the front desk. When your badge expires, you don’t have to redo the entire sign-in process from scratch — you show your confirmation quietly at the desk, and they print you a fresh badge, letting you continue your visit without interruption.
Why It Exists at All
Access tokens are deliberately short-lived, often valid for just a few minutes, because a stolen access token can be used by an attacker until it expires. Making them short-lived shrinks that risky window dramatically. But if access tokens alone expired every few minutes with nothing else to fall back on, users would be forced to log in again constantly, which would make any real application painfully unusable. The refresh token solves exactly this tension — it lets security stay tight on individual access tokens while keeping the overall login experience smooth and uninterrupted.
Refresh Token
A longer-lived credential used only to obtain a new access token, never sent directly to protected resources.
Access Token
The short-lived credential actually presented to applications and APIs to prove the user is logged in.
Token Endpoint
The specific address on the Keycloak server where refresh tokens are exchanged for new tokens.
Token Rotation
The practice of issuing a brand-new refresh token every time one is used, retiring the old one immediately.
A refresh token is not itself sent to your application’s business APIs the way an access token is. Its entire purpose is a private exchange with Keycloak’s own token endpoint — think of it as a backstage pass rather than a general-admission ticket.
2Why Short-Lived Access Tokens Need a Companion
To really understand refresh tokens, it helps to see the specific problem they’re solving.
There’s a fundamental tension in token-based security: the shorter a token’s lifetime, the smaller the damage if it’s ever stolen, but also the more often it needs replacing. Without any mechanism to replace it quietly, short expiry alone would create a miserable experience — a user filling out a long form could suddenly find themselves logged out mid-task, losing their work, just because a few minutes passed.
Problems Without a Refresh Token
- Users would need to log in again every few minutes as access tokens expire
- Long-lived access tokens would be needed instead, widening the risk window if stolen
- In-progress work could be lost the moment a session silently expired mid-task
- Mobile apps would need to constantly interrupt users for re-authentication
What the Refresh Token Solves
- Access tokens can stay short-lived, limiting damage from any single stolen token
- Users stay logged in seamlessly, with new access tokens fetched silently in the background
- Keycloak can revoke a compromised session by invalidating its refresh token centrally
- The overall login experience feels continuous, even though security stays tight underneath
It’s the difference between a subscription gym membership that renews automatically in the background versus one where you must physically re-register at the front desk every single day. The refresh token is that automatic renewal mechanism — quiet, convenient, and still ultimately controlled by rules the gym (Keycloak) can change or revoke at any time.
3Core Concepts: Lifetimes, Sessions, and Rotation
A few core ideas explain almost everything about how refresh tokens actually behave in practice.
SSO Session Idle Timeout
How long a user’s overall session can sit unused before Keycloak considers it fully expired, refresh token included.
SSO Session Max Lifespan
The absolute maximum length of a session, after which the user must fully log in again, regardless of activity.
Refresh Token Lifespan
How long an individual refresh token itself remains valid for exchange before it needs replacing.
Refresh Token Rotation
A security behavior where using a refresh token invalidates it and issues a new one, so each one can only be used once.
Tied to the Server-Side Session
Unlike an access token, which can technically be verified without contacting Keycloak again, a refresh token is always checked directly against Keycloak’s own server-side session record. This means Keycloak retains real, ongoing control over refresh tokens — it can revoke one immediately, at any time, simply by invalidating the associated session, something that isn’t possible with an already-issued access token until it naturally expires on its own.
An access token is like a printed boarding pass — once it’s in your hand, the airline can’t reach out and un-print it before it naturally expires. A refresh token is more like a reservation tied directly to the airline’s live booking system — they can cancel that reservation instantly, at any moment, simply by updating their own records.
People sometimes assume revoking a user’s access is instant no matter which token type is involved. In reality, an already-issued access token generally remains valid until it naturally expires, even after the underlying session is revoked — which is exactly why keeping access tokens short-lived matters so much.
4Architecture: Where Refresh Tokens Fit
Let’s zoom out and see exactly where the refresh token sits among the other moving pieces of a Keycloak-protected system.
flowchart TB
APP[Application Backend] -->|1 Holds Refresh Token| APP
APP -->|2 Sends Refresh Token When Access Token Expires| KC[Keycloak Token Endpoint]
KC -->|3 Validates Against Session| SESS[(Server-Side Session)]
KC -->|4 Issues New Access Token + New Refresh Token| APP
APP -->|5 Uses Fresh Access Token| API[Protected API]
Issued Once, Used Repeatedly
A refresh token is first handed out at the very end of the initial login flow, delivered together with the access token and ID token. From that point forward, it lives inside the application, ready to be exchanged whenever the current access token is about to expire or already has.
The Token Endpoint
Every refresh happens through a dedicated address on the Keycloak server called the token endpoint. The application sends its refresh token there directly, entirely behind the scenes, and receives back a freshly issued access token, a new ID token, and — depending on configuration — a brand-new refresh token as well.
Server-Side Session Validation
Unlike an access token’s fast, local signature check, refreshing always involves Keycloak looking up the live session tied to that refresh token. If that session has been revoked, expired, or exceeded its maximum lifespan, the refresh attempt fails, forcing the user back through a full login.
5The Full Lifecycle: From Login to Refresh to Expiry
Let’s trace a refresh token’s entire journey from the moment it’s born to the moment it’s retired.
User completes a full login
Keycloak issues an access token, an ID token, and a refresh token together, marking the start of a server-side session.
Access token is used normally
The application attaches the access token to requests, and every protected API accepts it until it naturally expires.
Access token expires
The application detects the access token is no longer valid, typically by checking its own recorded expiry time.
Application silently exchanges the refresh token
Without involving the user at all, the application calls Keycloak’s token endpoint with the refresh token to get a new access token.
Cycle repeats until the session truly ends
This exchange can happen many times over, until the refresh token itself expires, the session is revoked, or the user logs out.
sequenceDiagram
participant App as Application
participant KC as Keycloak
App->>KC: Login request
KC->>App: Access token + Refresh token
Note over App: Access token expires
App->>KC: Send refresh token to Token Endpoint
KC->>KC: Validate refresh token against session
KC->>App: New access token + new refresh token
Note over App: Cycle repeats until logout or session expiry
6Refresh Token Rotation and One-Time Use
Modern Keycloak deployments typically don’t reuse the same refresh token indefinitely — they rotate it on every use.
With rotation enabled, every time a refresh token is exchanged, Keycloak invalidates that exact refresh token and issues a brand-new one in its place, alongside the new access token. This means the application must always store and use the most recently issued refresh token going forward — the previous one becomes permanently useless the moment it’s exchanged.
It’s similar to a single-use claim ticket at a dry cleaner. Each time you use your ticket to pick up an item, they hand you a brand-new ticket for your next visit, and your old one is torn up immediately. If someone tried using an old, already-used ticket, it simply wouldn’t work anymore.
Why Rotation Improves Security
Rotation gives Keycloak a powerful way to detect certain kinds of theft. If a stolen refresh token is used by an attacker, and then the legitimate application later tries to use its own copy of that same, now-invalidated token, Keycloak can detect the reuse of an already-retired token as a strong signal something is wrong, and respond by revoking the entire session as a precaution.
Because refresh tokens rotate, application code must always update its stored copy after every refresh — continuing to reuse an old, already-rotated refresh token will simply fail, since it’s no longer valid.
7Where Refresh Tokens Should — and Shouldn’t — Live
Because a refresh token is powerful and longer-lived, where it’s stored matters just as much as how it’s used.
Safer Storage Patterns
- Kept entirely server-side, in a confidential backend application, never sent to the browser
- Stored in a secure, HTTP-only cookie that client-side JavaScript cannot read
- Held in a mobile app’s dedicated secure storage, isolated from other apps on the device
Riskier Storage Patterns
- Stored in browser local storage, easily readable by any injected malicious script
- Embedded directly in a single-page application’s in-memory JavaScript state long-term
- Logged accidentally in application debug output or error tracking tools
A stolen refresh token is generally far more dangerous than a stolen access token, precisely because it lasts longer and can be exchanged repeatedly for fresh access tokens. Treating its storage location casually undermines much of the security benefit that short-lived access tokens were designed to provide in the first place.
8Advantages, Disadvantages, and Trade-offs
Refresh tokens solve a real problem, but they introduce their own considerations worth weighing carefully.
Advantages
- Keeps users seamlessly logged in without repeated password entry
- Allows access tokens to stay short-lived, shrinking the risk of a stolen token
- Gives Keycloak real, ongoing control to revoke a session at any moment
- Rotation adds a built-in signal for detecting certain kinds of token theft
Disadvantages / Trade-offs
- A stolen refresh token carries more potential damage than a stolen access token
- Requires careful, deliberate storage decisions, especially in browser-based apps
- Adds implementation complexity around handling rotation and refresh failures gracefully
- Misconfigured lifespans can either frustrate users or leave sessions open too long
9Security Features Around Refresh Tokens
Keycloak includes several built-in protections specifically aimed at reducing refresh token risk.
Refresh Token Rotation
Invalidates each refresh token immediately after use, limiting how long a stolen copy would remain usable.
Configurable Lifespans
Administrators set exactly how long refresh tokens and overall sessions can last, tuned to their risk tolerance.
Session Revocation
An administrator can forcibly end a specific user’s session from the Admin Console, instantly invalidating its refresh token.
Signed and Bound Tokens
Refresh tokens are cryptographically signed and tied to their originating client, resisting tampering and misuse across applications.
10Monitoring, Logging, and Metrics
Because refresh tokens power ongoing sessions, keeping an eye on their behavior helps catch problems early.
| What to Monitor | Why It Matters |
|---|---|
| Refresh token failure rate | A sudden spike can indicate expired sessions, misconfigured lifespans, or an application storage bug |
| Reused-token detection events | Signals a possible stolen or duplicated refresh token being used by an attacker |
| Average session duration | Helps confirm whether configured lifespans actually match real user behavior |
| Token endpoint request volume | Unusually high refresh traffic from one client can indicate a bug or misuse |
Keycloak’s event logging can capture refresh token exchanges and failures, giving administrators visibility into how sessions actually behave in production, and an early warning system for the kind of reuse patterns that suggest token theft.
A rising trend of refresh failures right after a deployment is often a sign the new application code isn’t correctly storing and updating the rotated refresh token — worth checking before assuming it’s a Keycloak configuration issue.
11Design Patterns and Anti-Patterns
Practical experience running Keycloak in production has surfaced clear guidance around refresh token handling.
Pattern: Keep Refresh Tokens on the Backend
Where possible, hold refresh tokens only in a confidential backend server rather than in browser-accessible storage, minimizing exposure to client-side attacks.
Pattern: Handle Refresh Failures Gracefully
Design applications to redirect users cleanly to a fresh login when a refresh attempt fails, rather than showing a confusing error or a broken state.
Pattern: Match Lifespans to Actual Risk
Set shorter refresh token and session lifespans for highly sensitive applications, and more generous ones for lower-risk internal tools.
Problem
A single-page application stores its refresh token directly in browser local storage for simplicity.
Why It’s Harmful
Local storage is readable by any JavaScript running on the page, meaning a single cross-site scripting vulnerability could let an attacker steal a long-lived refresh token, not just a short-lived access token.
Correct Approach
Keep refresh tokens on a confidential backend when possible, or use secure, HTTP-only cookies that client-side scripts cannot directly access.
Problem
Setting an extremely long refresh token lifespan simply to avoid ever having to handle a re-login flow in application code.
Why It’s Harmful
This significantly widens the window during which a stolen refresh token remains valid and useful to an attacker, undermining much of the security benefit of the whole token-based design.
Correct Approach
Set a reasonable lifespan matched to actual risk, and properly implement the re-login flow rather than avoiding it by extending token lifetimes excessively.
12Best Practices and Common Mistakes
Concrete habits that keep refresh token handling both secure and reliable.
Always Update Stored Tokens After Rotation
Applications must immediately replace their stored refresh token with the newly issued one after every exchange, without exception.
Revoke Sessions on Suspicious Activity
Use administrator session revocation immediately if a compromised account is suspected, rather than waiting for natural expiry.
Log Out Properly, Not Just Locally
Ensure a “log out” action actually invalidates the refresh token at Keycloak, rather than simply deleting it from the application’s local memory.
Never Log Refresh Tokens
Keep refresh tokens out of application logs, error trackers, and debug output entirely, treating them with the same care as a password.
Assuming a “log out” button in an application automatically invalidates the refresh token at Keycloak. Unless the application explicitly calls Keycloak’s logout endpoint, the refresh token may technically remain valid even after the user believes they’ve logged out.
13Real-World and Industry Examples
Refresh tokens quietly power the “stay logged in” experience across a huge range of everyday applications.
Mobile Banking Apps
Banking apps often use short access token lifetimes with tightly scoped refresh tokens, balancing strong security with the convenience of not re-entering credentials on every app open.
Enterprise Web Dashboards
Internal business dashboards rely on refresh tokens to keep employees logged in through a full workday, without needing repeated logins between meetings and tasks.
Single-Page Applications
Modern SPAs commonly pair a backend-for-frontend pattern with securely stored refresh tokens, keeping sensitive credentials away from client-side JavaScript entirely.
API-Driven Microservice Platforms
Backend services that call other internal APIs on a user’s behalf use refresh tokens to maintain long-running, authenticated workflows without repeatedly involving the end user.
Anywhere an application feels like it “just remembers you’re logged in,” a refresh token is almost certainly working quietly in the background to make that experience possible.
14Frequently Asked Questions
No. An access token is presented directly to applications and APIs to prove identity, while a refresh token is used privately to obtain new access tokens and is never sent to business APIs itself.
The application can no longer silently obtain new access tokens, and the user is redirected back through a full login process to establish a fresh session.
Yes. Revoking the underlying session from the Admin Console immediately invalidates the associated refresh token, blocking any further silent renewal.
It depends on the client’s configuration and the authentication flow used — some flows, especially those designed for machine-to-machine communication, may not issue a refresh token at all.
This is called refresh token rotation, a security feature that invalidates each token after one use and helps detect potential theft if an old, already-used token is ever attempted again.
Generally, this is considered risky, since any malicious script running on the page could read it. Secure, HTTP-only cookies or backend-only storage are safer alternatives.
15Summary and Key Takeaways
A Refresh Token in Keycloak exists to solve a genuine tension between security and convenience — it allows access tokens to remain deliberately short-lived, shrinking the damage window if one is ever stolen, while still letting users stay seamlessly logged in through quiet, background token renewals. Unlike access tokens, refresh tokens are always checked against a live, server-side session, giving Keycloak real, ongoing power to revoke access instantly when needed, and rotation adds an additional layer of protection by invalidating each refresh token the moment it’s used. Because refresh tokens carry more risk if stolen than access tokens do, where and how they’re stored deserves careful, deliberate attention rather than an afterthought.
Key Takeaways
- A refresh token exists to renew access tokens silently, avoiding repeated logins as short-lived access tokens expire.
- It’s checked against a live, server-side session, unlike an access token, giving Keycloak real revocation power at any time.
- Rotation retires each refresh token after one use, issuing a fresh one and helping detect certain kinds of token theft.
- Storage location matters enormously — a stolen refresh token is generally more dangerous than a stolen access token.
- Lifespans are configurable, letting administrators balance security against convenience per realm.
- Proper logout must explicitly invalidate the refresh token at Keycloak, not just clear it from local application memory.
- Refresh tokens are never sent directly to protected business APIs — only ever exchanged privately at Keycloak’s token endpoint.