What Is an Offline Token in Keycloak?
A complete, beginner-friendly walkthrough of Keycloak's offline tokens — what they are, how they're issued, how they're stored, and how to use them safely in real applications.
Imagine you hand your house keys to a trusted house-sitter before leaving for a two-month trip. You don’t want to be woken up at 3 a.m. every time they need to water a plant, so instead of calling you for permission every single time, you give them a key that keeps working the whole time you’re away — until you explicitly ask for it back. In the world of identity and access management, Keycloak’s offline token is exactly that kind of key. It lets an application keep working on a user’s behalf long after that user has closed the browser tab and gone to sleep. This post walks through, step by step, what an offline token actually is, how Keycloak builds and manages it internally, and how to use it the right way.
1What Is an Offline Token, Really?
Before diving into Keycloak specifics, let’s build a plain-English mental model of the problem an offline token solves.
Keycloak is an open-source Identity and Access Management (IAM) server. It handles logging users in, issuing proof of who they are, and issuing proof of what they’re allowed to do. Every time a user logs in, Keycloak hands out a small bundle of tokens: an access token (a short-lived pass that says “this request is allowed”), an ID token (a statement of who the user is), and a refresh token (a way to get new access tokens without asking the user to log in again).
Normally, a refresh token is tied to the user’s login session. The moment that session ends — because the browser closed, the SSO session timed out, or the user simply stopped being active — the refresh token stops working too. That’s perfectly fine for a web app that only needs to act while the user is sitting in front of the screen. But plenty of real applications need to keep doing work after the user has left: a nightly batch job that syncs a user’s calendar, a background service that processes an uploaded video, or a mobile app that wants to silently refresh data overnight.
An offline token is Keycloak’s answer to exactly that need. It is a special kind of refresh token that is intentionally decoupled from the browser session. Once issued, it keeps working — even after the user logs out of their browser, closes their laptop, or the normal session expires — until one of three things happens: the token is explicitly revoked, it becomes idle for too long, or an administrator deletes it.
A regular refresh token is like a movie-theater stub that only works while the movie you bought a ticket for is still playing — once the film ends, the stub is worthless. An offline token is like a season pass: it keeps letting you in long after any single showing has ended, until you cancel the pass or the theater cancels it for you.
The word “offline” doesn’t mean the app works without internet access. It means the token keeps working while the user is offline — not actively present or authenticated in a browser session.
2Tokens in Keycloak: A Quick Refresher
To see why the offline token is special, it helps to line it up next to the other tokens Keycloak issues.
Keycloak follows the OAuth 2.0 and OpenID Connect standards, which define a small family of tokens. Each one has a distinct job, a distinct lifetime, and a distinct level of trust attached to it.
ID Token
A signed statement describing who the user is — their name, email, and other profile claims. It is meant to be read by the application, not sent to other services.
Access Token
A short-lived (often 1–5 minute) credential sent with every API request to prove the request is authorized. It expires quickly on purpose, to limit damage if it leaks.
Refresh Token
Used to obtain a brand-new access token without forcing the user to log in again. Normally tied to the user’s SSO session and expires when that session does.
Offline Token
A special refresh token that survives beyond the SSO session, requested with the offline_access scope, and persisted independently in Keycloak’s storage.
Notice that an offline token is not a fourth, entirely separate token type from a protocol point of view — technically it is a refresh token. What makes it “offline” is the scope used to request it and the special lifecycle rules Keycloak applies once that scope is present.
| Token | Typical Lifetime | Tied to Browser Session? | Main Use |
|---|---|---|---|
| Access Token | 1–5 minutes | No (but short-lived anyway) | Authorizing individual API calls |
| Refresh Token (standard) | Minutes to hours | Yes — dies with SSO session | Silently renewing access tokens during active use |
| Offline Token | Days, months, or indefinite | No — survives logout | Background/unattended access after the user has left |
3The offline_access Scope and Role
Nothing about offline tokens happens by accident — a client has to explicitly ask for one.
Keycloak ships with a built-in OAuth scope called offline_access. This scope exists specifically so that a client application can say, in its authorization request, “please give me a refresh token that keeps working even after this session ends.” When a login request includes this scope, Keycloak marks the resulting refresh token as an offline token internally and treats it under a different set of rules from that point forward.
Behind that scope sits a realm-level client scope also named offline_access, and behind that sits a composite realm role of the same name. For a user to be granted an offline token, three conditions generally need to line up: the client must be allowed to request the offline_access scope, the user must be permitted to have that role (directly, through a group, or through a default role mapping), and the authorization request itself must include scope=offline_access alongside the usual openid scope.
Why gate it behind a role at all?
Not every user should be able to create a credential that keeps working indefinitely. By tying offline access to a role, administrators can restrict which users — or which client applications — are trusted enough to hold a long-lived key to the user’s identity.
Requesting the offline_access scope does not automatically make every token issued during that login “offline.” Only the refresh token gains the special offline lifecycle; the access token issued alongside it still expires in the usual short window.
4How Offline Tokens Work Internally
Under the hood, Keycloak treats an offline token less like a self-contained secret and more like a claim ticket.
A Keycloak refresh token — offline or not — is a signed JWT (JSON Web Token), but the important part isn’t what’s printed inside it; it’s what Keycloak does when that token is presented back to the server. Keycloak looks up the session the token points to in its own storage. If that session record exists, is still valid, and matches what the token claims, Keycloak issues a fresh access token (and usually a fresh refresh token too, depending on rotation settings).
What makes this “offline” behavior possible is that Keycloak creates a special kind of session for it: an offline user session, separate from the normal, memory-resident SSO session. A regular SSO session lives mostly in a fast in-memory cache (Infinispan) and disappears once the user logs out or the session times out. An offline session, by contrast, is written to Keycloak’s persistent database from the moment it’s created, precisely so it can outlive the transient in-memory session it was born alongside.
flowchart LR
A["User logs in with
scope=offline_access"] --> B["Keycloak creates a
regular SSO session"]
B --> C["Keycloak also creates an
Offline User Session"]
C --> D[("Persisted in the
Keycloak database")]
B --> E["Access Token issued
(short-lived)"]
C --> F["Offline (Refresh) Token issued
(long-lived)"]
F -. "later, user is gone" .-> G["Client presents Offline Token"]
G --> H["Keycloak looks up
Offline User Session in DB"]
H --> I["New Access Token issued"]
This separation is the whole trick. The regular SSO session can time out, the browser can be closed, cookies can be cleared — none of that touches the offline session record sitting safely in the database. As long as that record exists and hasn’t expired or been revoked, the offline token tied to it keeps working.
5Requesting an Offline Token: The Flow
Getting an offline token is not a separate endpoint — it’s a small addition to a login flow you likely already know.
Most commonly, offline tokens are obtained through the standard OAuth 2.0 Authorization Code flow, the same flow used for ordinary browser logins. The only change is a single word added to the scope parameter.
User is redirected to Keycloak
The client application sends the user to Keycloak’s login page, and includes offline_access in the requested scopes alongside the usual openid scope.
User authenticates and consents
The user logs in as normal. If consent screens are enabled for the client, Keycloak may show a prompt explaining that the application is requesting long-lived, offline access.
Authorization code is returned
Keycloak redirects back to the client with a short-lived authorization code, exactly as in a normal login.
Client exchanges the code for tokens
The client’s backend exchanges the code at the token endpoint and receives an access token, an ID token, and — because the offline scope was requested — an offline refresh token.
Offline token is stored securely
The client saves the offline token in a secure, persistent location (an encrypted database column, a secrets manager) so it can be used later, unattended.
This is like checking a box marked “keep me signed in for background updates” during a one-time setup. You go through the normal sign-in screen once, but that single checkbox changes what kind of key you walk away with.
6Offline Sessions vs. Regular Sessions
It’s worth dwelling on this distinction because it explains almost every quirk of offline token behavior you’ll run into.
Regular SSO Session
- Lives mainly in fast in-memory storage
- Tied to browser cookies and idle/max timeouts
- Dies immediately on logout
- Powers “single sign-on” across multiple apps
Offline Session
- Persisted directly to the database on creation
- Governed by its own, separate idle/max timeout settings
- Survives normal browser logout
- Exists purely to back one client’s offline token
One subtlety trips up a lot of newcomers: logging a user out of Keycloak’s normal SSO session does not automatically kill their offline sessions. If you want a “log this user out everywhere, permanently” button, you must explicitly revoke offline tokens too — Keycloak’s admin console and Admin REST API both expose ways to do this, covered later in the Revocation chapter.
A single user can have multiple offline sessions at once — typically one per client application they’ve granted offline access to. Revoking one doesn’t affect the others.
7Data Flow & Lifecycle of an Offline Token
Let’s trace a token from birth to eventual death.
sequenceDiagram
participant U as User
participant C as Client App
participant K as Keycloak
participant DB as Keycloak DB
U->>C: Logs in, grants offline_access
C->>K: Authorization Code exchange
K->>DB: Create Offline User Session
K-->>C: Access Token + Offline (Refresh) Token
Note over C: User closes browser and leaves
C->>K: Later — present Offline Token
K->>DB: Look up Offline User Session
DB-->>K: Session found and valid
K-->>C: New Access Token (+ new Offline Token if rotation enabled)
Note over K,DB: Weeks pass, still within max lifespan
C->>K: Present Offline Token again
K->>DB: Session still valid?
DB-->>K: Yes
K-->>C: New Access Token
Three settings, all configurable per realm, decide when that session record finally expires:
Offline Session Idle
If the offline token is not used to request a new access token within this window, the session expires. This is the setting that most often surprises teams whose background job runs less frequently than they expected.
Offline Session Max Lifespan
An absolute cap on how long the session can live, no matter how often it’s refreshed. Some realms disable this entirely to allow indefinite offline access; most enable it as a security backstop.
Periodic Expired-Session Cleanup
Keycloak runs a background task that periodically sweeps expired offline sessions out of the database so storage doesn’t grow forever with dead entries.
8Storage & Persistence Architecture
Where exactly does all of this state live, and what does it mean for running Keycloak at scale?
In a small, single-node Keycloak deployment, this distinction between “in-memory” and “persisted” sessions might feel academic — everything is on one machine anyway. The difference becomes very real in a clustered deployment, which is how most production Keycloak setups run.
Regular SSO sessions live in Infinispan, Keycloak’s embedded distributed cache, replicated across cluster nodes for fast access but not necessarily written to disk. Offline sessions, by contrast, are written straight into Keycloak’s relational database (PostgreSQL, MySQL, MariaDB, and so on, depending on deployment). That single design choice is what lets an offline token survive a full restart of the entire Keycloak cluster — something a purely in-memory session could never do.
Every offline token a system hands out corresponds to a row that sits in the database until it’s revoked or expires. Applications that mint thousands of offline tokens for background workers or IoT devices should actively plan for database growth and set sensible idle/max lifespans rather than leaving them unbounded.
9Refreshing an Offline Token
“Long-lived” doesn’t mean “never changes” — most deployments rotate the token every time it’s used.
By default, Keycloak issues a new refresh token every time an old one is exchanged for a new access token — this applies to offline tokens too. Practically, that means a well-behaved client shouldn’t treat its offline token as a single, unchanging string to hard-code once. Instead, every time it uses the token, it should store whichever new token comes back in the response, replacing the old one.
Why rotate at all?
Rotation limits the value of a stolen token. If an old, already-used offline token is stolen and replayed, Keycloak can detect the reuse and, depending on configuration, invalidate the whole session as a precaution — a property called refresh token reuse detection.
10Revoking Offline Tokens
Because an offline token can outlive a browser session entirely, Keycloak gives administrators — and users — several deliberate ways to kill one early.
Account Console
End users can view every application they’ve granted offline access to, from their own Keycloak account console, and revoke individual grants themselves.
Admin Console / Admin REST API
Administrators can look up a specific user’s sessions, including offline ones, and revoke them directly — useful when offboarding an employee or responding to a compromised device.
Revoke by Client
An administrator can invalidate every offline token ever issued to a specific client application at once — helpful if that application’s own credentials are compromised.
Idle / Max Timeout Expiry
Even without any manual action, a session quietly expires once it crosses its configured idle or maximum lifespan.
Because revocation is deliberate and separate from ordinary logout, any application relying on offline tokens should build a clear “disconnect this integration” action for users — not just rely on Keycloak’s own account console.
11Security Considerations
Long-lived credentials are powerful, and power always comes with a bigger blast radius if something goes wrong.
An offline token is, functionally, a standing credential that can act as the user indefinitely. That makes it categorically more sensitive than a short-lived access token. If an attacker steals a valid offline token, they gain a renewable way to impersonate the user until someone notices and revokes it — potentially for weeks or months.
Never store in plaintext
Offline tokens should be encrypted at rest, wherever they’re kept, and never logged, printed to console output, or embedded in client-side code such as mobile app binaries or browser JavaScript.
Request the narrowest scope possible
Combine offline_access only with the specific permissions the background task actually needs, rather than a broad, all-purpose scope.
Always use TLS
Every exchange involving the offline token — issuance and later refresh — must travel over an encrypted connection, since intercepting it in transit is functionally the same as stealing the user’s long-term access.
Restrict which clients can request it
Only clients that genuinely need unattended access should be permitted to request the offline_access scope at all — most clients should never see it.
Problem
A team requests offline access for every client “just in case it’s useful later,” without a concrete background use case.
Why It’s Harmful
Each unnecessary offline token is a standing, renewable credential — more attack surface, more database rows to secure, and more grants for users to have to understand and manage.
Correct Approach
Reserve offline_access strictly for clients with a genuine, documented need for unattended, background operation.
12Advantages, Disadvantages & Trade-offs
Offline tokens solve a real problem, but they aren’t free of cost.
Advantages
- Enables genuine background processing without repeatedly prompting the user to log in
- Built on the standard OAuth refresh-token mechanism — no proprietary protocol to learn
- Session-backed, so revocation is centralized and immediate once triggered
- Configurable idle and max lifetimes per realm give administrators fine control
- Rotation and reuse detection provide meaningful protection if a token leaks
Disadvantages / Trade-offs
- A stolen offline token is far more damaging than a stolen access token
- Every issued token adds a persistent row that must be secured and eventually cleaned up
- Users often forget which apps hold long-lived access, creating a “silent trust” risk over time
- Misconfigured, unbounded max lifespans can leave forgotten integrations with access forever
13Design Patterns & Anti-Patterns
A few recurring good and bad habits show up again and again in teams adopting offline tokens.
Pattern: One Offline Token per Integration, Not per User Action
Request the offline grant once, during a clear “connect this integration” step, rather than sprinkling offline scope requests across many unrelated login flows.
Pattern: Store Alongside an Explicit Revocation Path
Whenever an offline token is saved, also record enough metadata (which user, which purpose, when granted) to support a clean “revoke access” feature later.
Pattern: Treat Idle Timeout as a Design Input
If a background job runs monthly, the offline session’s idle timeout needs to comfortably exceed that interval — otherwise the token silently dies between runs.
Problem
Treating the offline token as a static, one-time secret and never updating it after each rotation.
Why It’s Harmful
Once rotation kicks in, the old token value becomes invalid; a client that keeps using the stale value will start failing unpredictably, often described as “the token randomly stopped working.”
Correct Approach
Always persist whichever token value comes back in the most recent refresh response, and design storage to be updated on every use.
14Best Practices & Common Mistakes
A short, practical checklist for teams about to implement offline tokens for the first time.
Restrict the offline_access role
Only assign it to the specific users or clients that genuinely need background access.
Set realistic idle and max timeouts
Match them to how often the background process actually runs, with some safety margin.
Encrypt at rest, restrict access
Store offline tokens like any other long-lived secret — encrypted, access-controlled, and excluded from logs.
Handle rotation correctly
Always persist the freshest token returned from each refresh call, never a value cached from the original grant.
Give users visibility and control
Surface which integrations hold offline access and let users revoke it easily, both in your app and by pointing them to Keycloak’s account console.
Assuming that logging a user out of the application also revokes their offline token. Unless your logout flow explicitly calls Keycloak’s revocation endpoint or admin API for the offline session, the token remains valid.
15Real-World Use Cases
Offline tokens show up wherever software needs to act for a user without the user being present.
Calendar / Email Sync Services
A service that periodically fetches new calendar events or emails on a user’s behalf uses an offline token to authenticate each sync run, without prompting the user every time.
Developer Command-Line Tools
A CLI that a developer logs into once, then uses for weeks, typically relies on an offline token stored locally so the developer isn’t forced to re-authenticate for every command.
Video/File Processing Pipelines
A pipeline that processes an uploaded file over several hours can hold an offline token to check status and write results back under the original uploader’s identity, long after the upload page was closed.
Headless Devices
A device provisioned once during setup can keep reporting data under the owning user’s account using an offline token, without a screen to log in through again.
16Monitoring, Logging & Metrics
Because offline tokens represent standing access, operators generally want visibility into how many exist and how they’re being used.
Track active offline session counts
A sudden spike in offline sessions for a single client can indicate a bug causing repeated re-grants, or, in the worst case, abuse.
Audit issuance and revocation events
Keycloak’s event logging can be configured to record when offline tokens are granted and revoked, giving security teams an audit trail to review during incident response.
Watch for refresh failures
A rising rate of failed refresh attempts against offline sessions often points to a client not handling token rotation correctly, or to sessions expiring earlier than an application expects.
Periodically reviewing and pruning long-unused offline sessions — even before their max lifespan is reached — is good hygiene, especially for clients that integrate with many third-party users.
17Frequently Asked Questions
No. An offline token is a special kind of refresh token used to obtain new access tokens later; it is never sent directly to a resource server as proof of authorization the way an access token is.
Yes, unless a realm is specifically configured for indefinite offline access. Idle timeout and maximum lifespan settings both apply, and Keycloak’s cleanup job removes expired sessions automatically.
Yes. Keycloak’s account console lists a user’s granted applications, including offline sessions, and lets the user revoke access directly.
Typically yes — an administrator needs to make the offline_access client scope available to the client, and the user (or a role mapping) must be permitted to hold the offline_access role.
Nothing happens to the token. Because offline sessions are persisted in the database rather than the in-memory cache, they survive restarts, upgrades, and node failures cleanly.
No. It should be reserved for clients that have a genuine, documented need for unattended background access, since each grant creates a long-lived, higher-value credential.
18Summary and Key Takeaways
An offline token is Keycloak’s purpose-built mechanism for letting an application act on a user’s behalf long after that user has stepped away — powered under the hood by a persisted, database-backed offline session that lives independently of the ordinary, memory-resident SSO session. It’s requested with a single extra scope, governed by realm-level roles and timeouts, and revocable at any time by the user or an administrator. Used deliberately — narrow in scope, properly secured, and paired with clear revocation paths — offline tokens make genuinely useful background integrations possible without ever forcing the user to sit and wait through repeated logins.
Key Takeaways
- It’s a special refresh token — requested via the
offline_accessscope, not a separate protocol concept. - It’s backed by a persisted session — stored in Keycloak’s database, not the fast in-memory cache used for regular sessions.
- It outlives normal logout — a regular SSO logout does not revoke it; that must be done explicitly.
- Its lifetime is configurable — governed by realm-level idle timeout and maximum lifespan settings.
- It rotates on use — clients must always store the freshest token value returned from each refresh.
- It carries real risk — treat it as a high-value, long-lived secret: encrypt it, scope it narrowly, and restrict which clients can request it.
- It powers real background work — sync services, CLI tools, long-running pipelines, and headless devices all rely on it to act without the user present.