What Is a Refresh Token in Keycloak? Staying Logged In Without Staying Exposed

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.

Simple Analogy

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.

Term

Refresh Token

A longer-lived credential used only to obtain a new access token, never sent directly to protected resources.

Term

Access Token

The short-lived credential actually presented to applications and APIs to prove the user is logged in.

Term

Token Endpoint

The specific address on the Keycloak server where refresh tokens are exchanged for new tokens.

Term

Token Rotation

The practice of issuing a brand-new refresh token every time one is used, retiring the old one immediately.

i
Good To Know

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
Simple Analogy

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.

Concept

SSO Session Idle Timeout

How long a user’s overall session can sit unused before Keycloak considers it fully expired, refresh token included.

Concept

SSO Session Max Lifespan

The absolute maximum length of a session, after which the user must fully log in again, regardless of activity.

Concept

Refresh Token Lifespan

How long an individual refresh token itself remains valid for exchange before it needs replacing.

Concept

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.

Simple Analogy

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.

!
Common Misconception

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]
        
FIG 1 — The refresh token’s private round trip to Keycloak’s token endpoint, separate from ordinary API traffic

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.

Longer-Lived
than the access token it renews
Session-Bound
tied to a live, revocable session
Background Only
never sent to protected business APIs

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.

1

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.

2

Access token is used normally

The application attaches the access token to requests, and every protected API accepts it until it naturally expires.

3

Access token expires

The application detects the access token is no longer valid, typically by checking its own recorded expiry time.

4

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.

5

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
        
FIG 2 — The repeating refresh cycle that keeps a user logged in without repeated password entry

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.

Simple Analogy

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.

i
Good To Know

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
!
Security Warning

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.

Feature

Refresh Token Rotation

Invalidates each refresh token immediately after use, limiting how long a stolen copy would remain usable.

Feature

Configurable Lifespans

Administrators set exactly how long refresh tokens and overall sessions can last, tuned to their risk tolerance.

Feature

Session Revocation

An administrator can forcibly end a specific user’s session from the Admin Console, instantly invalidating its refresh token.

Feature

Signed and Bound Tokens

Refresh tokens are cryptographically signed and tied to their originating client, resisting tampering and misuse across applications.

“A refresh token trades a little more stored responsibility for a lot more everyday convenience — and Keycloak gives administrators real, ongoing control over that trade.”

10Monitoring, Logging, and Metrics

Because refresh tokens power ongoing sessions, keeping an eye on their behavior helps catch problems early.

What to MonitorWhy It Matters
Refresh token failure rateA sudden spike can indicate expired sessions, misconfigured lifespans, or an application storage bug
Reused-token detection eventsSignals a possible stolen or duplicated refresh token being used by an attacker
Average session durationHelps confirm whether configured lifespans actually match real user behavior
Token endpoint request volumeUnusually 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.

i
Practical Tip

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.

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.

ANTI-PATTERN-01 Avoid
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.

ANTI-PATTERN-02 Avoid
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.

Best Practice

Always Update Stored Tokens After Rotation

Applications must immediately replace their stored refresh token with the newly issued one after every exchange, without exception.

Best Practice

Revoke Sessions on Suspicious Activity

Use administrator session revocation immediately if a compromised account is suspected, rather than waiting for natural expiry.

Best Practice

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.

Best Practice

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.

!
Common Mistake

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

Q1Is a refresh token the same thing as an access token?

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.

Q2What happens if a refresh token expires?

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.

Q3Can an administrator forcibly log out a user who has a valid refresh token?

Yes. Revoking the underlying session from the Admin Console immediately invalidates the associated refresh token, blocking any further silent renewal.

Q4Does every Keycloak client automatically receive a refresh token?

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.

Q5Why does the refresh token change every time it’s used?

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.

Q6Is it safe to store a refresh token in browser local storage?

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.