Keycloak Offline Tokens Explained

Guilliano Molaire Guilliano Molaire 11 min read

Last updated: June 2026

A Keycloak offline token is a special refresh token that does not expire when the user’s session goes idle — it survives logout and long periods of inactivity, letting a client obtain new access tokens on the user’s behalf without them being online. You request it with the offline_access scope; it is meant for long-running background and daemon use cases like syncing or scheduled jobs, not everyday browser sessions.

Most OAuth 2.0 flows assume the user is present. They log in, receive tokens, interact with your application, and eventually log out. When the SSO session times out, the refresh token becomes invalid and the user must re-authenticate. That model breaks the moment you need a process to run at 3 AM on the user’s behalf — polling an API, syncing data, or processing a job queue.

Keycloak’s offline token feature solves exactly this problem. This post explains what offline tokens are, how they differ from regular refresh tokens, how the offline session lifecycle works, and the security trade-offs you should weigh before reaching for them. If you are new to the Keycloak token model overall, start with the JWT token lifecycle guide and come back here.

What is an offline token in Keycloak?

An offline token is a refresh token issued with an extended, user-session-independent lifetime. The OpenID Connect Core specification defines the offline_access scope as the mechanism clients use to request this kind of long-lived credential. When Keycloak sees offline_access in the authorization request scope, it issues a refresh token that:

  • Is stored persistently in the Keycloak database against the user’s offline session record
  • Is not invalidated when the user’s browser SSO session expires or when the user logs out of other clients
  • Has its own idle and maximum lifetime settings, separate from the standard SSO session timers

The resulting token looks like any other refresh token — it is a signed JWT or an opaque string, depending on your Keycloak version and configuration. The difference is entirely in the lifecycle rules Keycloak applies when the client presents it.

When your background service needs a fresh access token, it sends the offline refresh token to the token endpoint. Keycloak validates the token, checks that the offline session has not exceeded its own idle or max lifetime, and issues a new access token. The user does not need to be online or have an active browser session for any of this to work.

How offline tokens differ from regular refresh tokens

Understanding the distinction requires knowing how Keycloak ties regular tokens to sessions. A standard refresh token is bound to the user’s SSO session. The moment that session violates SSO Session Idle (the realm setting for how long a session can go without activity) or SSO Session Max (the absolute ceiling on session lifetime), the refresh token stops working.

Offline tokens follow a completely separate set of rules governed by two realm-level settings:

  • Offline Session Idle — how long an offline session can sit without any token refresh activity before it is invalidated. Defaults to 30 days in Keycloak 26.x.
  • Offline Session Max — the absolute maximum lifetime of an offline session regardless of activity. This is disabled by default (Offline Session Max Limited is off), meaning offline sessions can theoretically live forever as long as they are used before the idle timeout.

The table below summarizes the key differences:

Property Regular refresh token Offline refresh token
Bound to SSO session Yes No
Survives user logout No Yes
Idle timer applies SSO Session Idle Offline Session Idle
Max timer applies SSO Session Max Offline Session Max
Stored in Keycloak DB Transiently Persistently
offline_access scope required No Yes
Visible in User Account Console No Yes
Can be revoked individually No Yes

This separation is what makes offline tokens suitable for unattended processes. A user can close their browser, have their SSO session expire overnight, and log in fresh the next morning — all while a background sync process continues using the offline token without interruption.

For a detailed walkthrough of how standard refresh tokens behave under Keycloak’s rotation settings, see the Keycloak refresh token rotation guide.

Requesting an offline token

Offline tokens are requested through the standard OAuth 2.0 flows. The only difference is adding offline_access to the scope parameter. Keycloak only issues an offline token when all of the following are true:

  1. The offline_access scope is present in the authorization request
  2. The client has offline_access enabled in the Keycloak admin console (Clients > [your client] > Settings > Authentication flow > Standard flow and the offline_access scope is assigned or the client is not restricted from using it)
  3. The user has the offline_access role, which is a realm-level role Keycloak manages automatically when the feature is enabled

Authorization code flow

This is the preferred approach for interactive applications where the user can authenticate once and then grant long-term access to a background process.

GET /realms/{realm}/protocol/openid-connect/auth
  ?client_id=my-background-client
  &response_type=code
  &scope=openid%20offline_access
  &redirect_uri=https://myapp.example.com/callback
  &state=random-state-value

After the user authenticates and consents, Keycloak redirects to your callback with an authorization code. You exchange the code for tokens:

curl -s -X POST 
  "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token" 
  -H "Content-Type: application/x-www-form-urlencoded" 
  -d "grant_type=authorization_code" 
  -d "client_id=my-background-client" 
  -d "client_secret=your-client-secret" 
  -d "code=AUTH_CODE_FROM_REDIRECT" 
  -d "redirect_uri=https://myapp.example.com/callback"

The response will contain a refresh_token field. If the offline_access scope was granted, this is your offline token. Inspect the decoded payload — it will have "typ": "Offline" in the token claims.

Direct grant (resource owner password credentials)

For machine-to-machine scenarios where an interactive user login is not possible, you can use the direct grant flow. Note that this flow should only be used when the client is highly trusted and the authorization code flow is genuinely not feasible:

curl -s -X POST 
  "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token" 
  -H "Content-Type: application/x-www-form-urlencoded" 
  -d "grant_type=password" 
  -d "client_id=my-background-client" 
  -d "client_secret=your-client-secret" 
  -d "[email protected]" 
  -d "password=user-password" 
  -d "scope=openid offline_access"

The response will include both an access token and an offline refresh token. Store the offline refresh token securely — this is the credential your background service will use going forward.

Using the offline token to get a new access token

When the access token expires, your service exchanges the offline refresh token exactly as it would any refresh token:

curl -s -X POST 
  "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token" 
  -H "Content-Type: application/x-www-form-urlencoded" 
  -d "grant_type=refresh_token" 
  -d "client_id=my-background-client" 
  -d "client_secret=your-client-secret" 
  -d "refresh_token=OFFLINE_REFRESH_TOKEN"

Keycloak returns a fresh access token. If refresh token rotation is enabled on the client, it will also return a new offline refresh token — discard the old one and store the new one. See the token expiration troubleshooting guide if you encounter invalid_grant errors during this exchange.

The offline session model and storage

When Keycloak issues an offline token, it creates a persistent offline session record in its database. This is distinct from the transient SSO session record that backs ordinary browser sessions.

Each offline session is associated with:

  • The user who granted access
  • The client that requested the token
  • A creation timestamp and last-activity timestamp
  • The serialized offline token value

These records persist even through Keycloak restarts. In a clustered deployment, they are replicated across nodes (for embedded Infinispan) or stored in the shared database (for external Infinispan or the JPA session provider). This persistence is what enables offline tokens to survive indefinitely — unlike in-memory SSO sessions, which are lost on node failure or restart.

You can configure the offline session limits under Realm Settings > Sessions in the Keycloak admin console. Key settings:

  • Offline Session Idle: Time after which an unused offline session is automatically purged (default 30 days in Keycloak 26.x)
  • Offline Session Max Limited: Toggle to enforce an absolute maximum
  • Offline Session Max: If the toggle above is on, the ceiling in seconds for any offline session regardless of activity

If your use case requires the offline token to outlive the 30-day default idle period, you must either increase Offline Session Idle or ensure the background service performs a token refresh before the idle window closes. A service that refreshes access tokens every hour will comfortably reset the idle timer.

For a broader look at all session settings and their interactions, refer to the Keycloak session timeout configuration guide.

Revocation: how to invalidate an offline token

Because offline tokens are long-lived and stored in Keycloak’s database, they need an explicit revocation mechanism. Keycloak provides three ways to revoke them:

User Account Console

Users can see and manage their own offline sessions at /realms/{realm}/account. Under the Device Activity or Applications section (depending on your Keycloak version), they can see which clients hold offline sessions and revoke individual ones with a single click. This is the self-service path and aligns with good consent management practice.

Admin REST API

Administrators can revoke offline sessions programmatically. First, retrieve the offline sessions for a user:

curl -s 
  -H "Authorization: Bearer ADMIN_ACCESS_TOKEN" 
  "https://keycloak.example.com/admin/realms/myrealm/users/{userId}/offline-sessions/{clientId}"

Then delete the specific offline session:

curl -s -X DELETE 
  -H "Authorization: Bearer ADMIN_ACCESS_TOKEN" 
  "https://keycloak.example.com/admin/realms/myrealm/users/{userId}/offline-sessions/{clientId}"

Realm-wide session logout

The Admin API endpoint POST /admin/realms/{realm}/logout-all invalidates all sessions, including offline sessions. Use with caution — this is a blunt instrument that will require all users and services to re-authenticate.

You can also set a realm-wide Not Before policy under Realm Settings > Sessions > Not Before and click Push. Any token issued before that timestamp will be rejected, which effectively revokes all outstanding offline tokens without deleting the session records.

Security trade-offs

Offline tokens are powerful, and that power comes with risk. Before issuing them, weigh these considerations:

They are high-value, long-lived credentials. A stolen offline token gives an attacker the ability to impersonate a user for potentially months. Unlike an access token, which expires in minutes, a compromised offline token has a much larger blast radius.

Store them like secrets. An offline token must never be stored in a browser cookie, localStorage, or any location accessible to client-side JavaScript. Use server-side secret stores, environment variables, or a secrets manager such as HashiCorp Vault or AWS Secrets Manager.

Rotate them when refresh token rotation is on. If the Keycloak client has Refresh Token Rotation enabled, each successful token refresh will issue a new offline refresh token and invalidate the old one. This limits the exposure window of a stolen token to the interval between refreshes — a significant security improvement. See the OAuth 2.0 developer visual guide for how rotation fits into the broader token security picture.

Audit offline session counts. An unexpected spike in offline sessions for a client may indicate that tokens are being issued inadvertently or that a service is not properly reusing existing offline tokens. Monitor the admin console or query the Admin API periodically.

Limit the scope. When requesting the offline token, request only the scopes the background process actually needs. A narrow scope limits what an attacker can do with a stolen token.

Do not use offline tokens for browser applications. SPAs and traditional web apps should use standard refresh tokens within normal SSO session bounds. Offline tokens in a browser are nearly impossible to protect adequately.

When to use offline tokens

Offline tokens are the right tool in these scenarios:

  • Background services and daemons: A data pipeline that calls an API on behalf of a user nightly, a report generator that runs on a schedule, or any service where the user cannot be present to re-authenticate.
  • Mobile applications with “stay logged in” requirements: A mobile app where the user expects to remain authenticated across long periods of inactivity. Mobile platforms have secure storage (Keychain on iOS, Keystore on Android) suited for long-lived credentials.
  • IoT and embedded devices: A device registered to a user account that needs to push telemetry or receive commands without interactive logins.
  • Data synchronization services: Backup or sync clients that run in the background on behalf of a specific user account.

Offline tokens are not appropriate when:

  • The user is present and expected to interact with the application regularly — use standard sessions instead.
  • You are building a pure machine-to-machine integration with no user delegation — use client credentials flow, which does not involve offline tokens at all.
  • You cannot securely store the token on the client side — do not issue an offline token if you cannot protect it.

If you are building any of these background integrations and want to reduce the operational overhead of managing Keycloak’s session database, token endpoints, and replica configuration, Skycloak handles the infrastructure so you can focus on the integration logic itself. See managed Keycloak pricing.

Frequently asked questions

What is an offline token in Keycloak?

A Keycloak offline token is a refresh token issued when a client requests the offline_access scope. It is stored persistently in Keycloak’s database and is not bound to the user’s SSO session, so it continues to work even after the user logs out or the SSO session expires. The client uses it to obtain new access tokens without requiring the user to be present.

What is the offline_access scope?

The offline_access scope is an OAuth 2.0 and OpenID Connect scope defined in the OpenID Connect Core specification. When included in an authorization request, it signals to the authorization server that the client needs an offline token — a long-lived refresh token suitable for use in background processes. In Keycloak, the scope must be assigned to the client and the user must have the offline_access realm role (granted automatically when the feature is in use).

Do Keycloak offline tokens expire?

Yes, but the expiration rules are different from standard refresh tokens. An offline token expires if the offline session has been idle for longer than the realm’s Offline Session Idle setting (default 30 days in Keycloak 26.x) or if Offline Session Max is enabled and exceeded. If the background service performs a token refresh before the idle window closes, the idle timer resets and the offline session remains valid. The token expiration troubleshooting guide covers how to diagnose invalid_grant errors related to expired offline sessions.

How do I revoke an offline token in Keycloak?

There are three paths. Users can revoke their own offline sessions from the Keycloak Account Console at /realms/{realm}/account under the Applications or Device Activity section. Administrators can use the Keycloak Admin REST API to delete specific offline sessions for a user and client. Finally, setting a realm-wide Not Before policy under Realm Settings and pushing it will invalidate all tokens — including offline tokens — issued before that timestamp.

Can I use offline tokens with a public client?

Yes, but with significant caution. Public clients (SPAs, native apps without a backend) cannot securely authenticate to Keycloak’s token endpoint, which means the offline token is the only long-lived secret protecting user access. In practice, mobile applications can use offline tokens safely when combined with platform secure storage (iOS Keychain, Android Keystore) and PKCE in the authorization code flow. Browser-based SPAs should not use offline tokens because there is no secure way to store them on the client side.

Tired of running Keycloak yourself?

Skycloak runs real upstream Keycloak for you with a 99.99% SLA. No fork, no lock-in, just managed Keycloak that stays patched and on call so you don't have to.

Guilliano Molaire
Written by
Founder

Guilliano is the founder of Skycloak and a cloud infrastructure specialist with deep expertise in product development and scaling SaaS products. He discovered Keycloak while consulting on enterprise IAM and built Skycloak to make managed Keycloak accessible to teams of every size.

Start Free Trial Talk to Sales
© 2026 Skycloak. All Rights Reserved. Design by Yasser Soliman