Keycloak session errors are the most common source of unexpected logouts. Your application works perfectly in development, then users report being logged out randomly in production. The token refresh returns invalid_grant with a cryptic error_description like “Session not active” — and the Keycloak admin console shows no obvious misconfiguration.

This guide explains every Keycloak session type, how their timeouts interact, and how to fix each session error.

Quick Diagnostic: Which Error Are You Seeing?

error_descriptionJump To
Session not activeSSO Session Expired
Token is not activeRefresh Token Expired
Session doesn't have required clientCache Eviction
Offline session not activeOffline Session Expired
Client session not activeClient Session Expired
authentication_expired in redirect URLAuthentication Session Timeout

All of these appear as invalid_grant in the OAuth error response:

{
  "error": "invalid_grant",
  "error_description": "Session not active"
}

For a complete guide to all invalid_grant causes across Keycloak, Auth0, Okta, Azure AD, and Google, see the OAuth invalid_grant Troubleshooting Guide.

Understanding Keycloak Session Types

Keycloak has four session types, each with its own timeout. Understanding the hierarchy is critical to debugging session errors.

Session Hierarchy

SSOSesCCCsllliiiioeeennnnttt(USSSseeeesssrsssiiiSoooennnss(((iaaaopppnppp)---fbmraoocbnkitelenend)d))ReOIEannxledpmei-pprweeeirnsddeaei,pnnptdolenitpecieamnptedeioerounnttulsapyecercrelscoslgeiidennt

Key rule: When the SSO session expires, ALL client sessions under it expire immediately — regardless of their individual timeout settings.

All Session Types and Defaults

Session TypeIdle DefaultMax DefaultScope
SSO Session30 minutes10 hoursRealm-wide
Client SessionInherits SSOInherits SSOPer-client override available
Offline Session30 daysUnlimited (unless limited)Per-client override available
Authentication Session5 min (action) / 30 min (total)N/ATemporary, during login only
Remember Me SessionInherits SSO (unless overridden)Inherits SSO (unless overridden)Realm-wide

Where to Configure Each Timeout

Realm-wide: Admin Console → Realm Settings → Sessions tab

SettingDescription
SSO Session IdleInactivity timeout before session expires
SSO Session MaxAbsolute maximum session duration
Client Session IdleDefault idle timeout for all clients
Client Session MaxDefault max timeout for all clients
Offline Session IdleIdle timeout for offline sessions
Offline Session Max LimitedToggle to enable absolute offline max
Offline Session MaxAbsolute max for offline sessions (when toggle is ON)
Login TimeoutTotal time to complete login flow
Login Action TimeoutTime for a single login action

Per-client override: Clients → [client] → Advanced → Advanced Settings

SettingDescription
Client Session IdleOverride realm default for this client
Client Session MaxOverride realm default for this client
Client Offline Session IdleOverride realm offline idle
Client Offline Session MaxOverride realm offline max
Access Token LifespanOverride realm access token lifespan

Timeout Interaction Rules

This is the most misunderstood aspect of Keycloak session management. Timeouts follow a strict hierarchy:

SSOSesSsSiOonSeCMslasixieon(ntCalbISisdeeolsnlestAuict(oSceineensscaMssecaiitxoTlinoiv(knipIegtedn,yrl-eLdtcieil(ffmipeaeeesuonrplut-attcn,cl1ei(0diemhelnu)fitsantugil,nbtaemc3ut0simtvC)ilbtieye,ntmSuSSseOtssSbieeosnsiIoSdnSlOeM)aSxe)ssionIdle)

Rules:

  1. SSO Session Max is the hard ceiling. No amount of refresh activity extends a session beyond this.
  2. Refreshing a token resets the SSO Session Idle timer. This is a sliding window.
  3. Client timeouts must be ≤ realm timeouts. Keycloak 26.5+ rejects configurations that violate this; older versions silently ignore the client override.
  4. Keycloak adds a ~2-minute buffer to configured idle timeouts (e.g., 30 minutes configured ≈ 32 minutes actual).
  5. When the SSO session expires, ALL client sessions expire immediately, even if the client session itself hasn’t timed out.

Practical Example

RCTT0000021eloi::::::0aikm001110:leee0555500mnnl0:t:i:n-------eSCA:UANUBCSSlcscosulSOicecetiOeereareSnsscSnSetslstcStesoilOssSTgtviSsieosoicseioskktkesonseieysssninnnsiIoobioMdnLenuonalixtnxeIfSpttMdeSihoia=lsOrinsxepesf3asssru0=nectelslrialm1=sielci5iaeflhrn5opnree,mnptevd-imsaaSni+rhluS,neitOcfCfdchClrLaleSlieIiineiesEletsenhNsunisnteT:stcitseaoss"rmtnSeeCuiesslrsoMssSsietnasiSie-xioOonarronntuee=nit-qcdeshau1Mrlxeeui0aeepsntrxaisthehtrriido=eeeocudssnar2etst(nehs1oso5tutiromansics3ntt0iaivnmdetil"lney)(nologinpage)

SSO Session Expired

Error: “Session not active”

ERReOrRro[ro_rdge.skceryicpltoiaokn.:prSoetsosciooln.oniodtc]acRtEiFvReESH_TOKEN_ERROR

The SSO session expired because the user was inactive longer than SSO Session Idle (default 30 minutes) or the SSO Session Max (default 10 hours) was reached.

Fix: Increase SSO Session Idle or ensure your application refreshes tokens before the idle timeout:

AdmSSiSSnOOCSSoeensssssoiilooennIMdaRlxee:a:l1m300Shemotiutnriusntgess24S6he0osusmriisonnustetsab:orhigherbasedonusecase)

For SPAs: Schedule token refresh at (SSO Session Idle - buffer) intervals. If idle is 30 minutes, refresh every 25 minutes:

// Refresh before session idle timeout
const REFRESH_INTERVAL = (SSO_SESSION_IDLE_SECONDS - 300) * 1000; // 5 min buffer
setInterval(() => {
  keycloak.updateToken(60) // Refresh if token expires within 60 seconds
    .catch(() => keycloak.login()); // Session expired, force re-login
}, REFRESH_INTERVAL);

Refresh Token Expired

Error: “Token is not active”

ERReOrRro[ro_rdge.skceryicpltoiaokn.:prTootkoecnoli.soindoct]aRcEtFiRvEeSH_TOKEN_ERROR

The refresh token itself has expired or been revoked. This happens when:

  1. The session idle timeout expired between the last refresh and the current attempt
  2. An admin revoked the user’s sessions
  3. The user changed their password (invalidates all tokens)
  4. Refresh Token Max Reuse is set to 0 and the same refresh token was used twice

Verify token status via Admin REST API:

# Get admin token
ACCESS_TOKEN=$(curl -s -X POST \
  "https://keycloak.example.com/realms/master/protocol/openid-connect/token" \
  -d "client_id=admin-cli&username=admin&password=admin&grant_type=password" \
  | jq -r '.access_token')

# List user's sessions
curl -s \
  "https://keycloak.example.com/admin/realms/myrealm/users/{userId}/sessions" \
  -H "Authorization: Bearer $ACCESS_TOKEN" | jq .

If the response is empty, the session has expired or been terminated.

Client Session Timeout

Error: “Client session not active”

This error occurs when a per-client session timeout is configured and it expires before the SSO session. The user’s SSO session is still valid, but the specific client’s session has ended.

How to identify: The user can access other applications without re-login, but one specific application forces re-authentication.

Fix: Check per-client overrides at Clients → [client] → Advanced → Advanced Settings. Either increase Client Session Idle or remove the override to inherit realm defaults.

Infinispan Cache Eviction

Error: “Session doesn’t have required client”

ERReOrRro[ro_rdge.skceryicpltoiaokn.:prSoetsosciooln.odiodecs]n'RtEFhRaEvSeH_rTeOqKuEiNr_eEdRRcOlRient

This is the most confusing session error because the user session is valid but the client session is missing. The sessions cache and clientSessions cache are evicted independently.

Cause: The Infinispan cache reached its per-node limit (default 10,000 entries in Keycloak 26+), and the client session was evicted.

Keycloak 26+ (persistent sessions enabled by default): Evicted sessions are loaded from the database on demand. This error should be rare unless the database is unreachable.

Keycloak 25 and earlier (volatile sessions): Evicted sessions are permanently lost. This error is common in high-traffic environments.

Fix for Keycloak 26+:

# Increase cache size
bin/kc.sh start \
  --cache-embedded-sessions-max-count=20000 \
  --cache-embedded-client-sessions-max-count=20000

Fix for Keycloak 25 and earlier:

# Enable persistent sessions (preview feature in KC 25)
bin/kc.sh start --features=persistent-user-sessions

# Or increase cache size in conf/cache-ispn.xml

Offline Session Expired

Error: “Offline session not active”

Offline sessions (created with offline_access scope) have much longer timeouts but still expire.

Default behavior:

  • Offline Session Idle: 30 days — token must be refreshed within 30 days
  • Offline Session Max Limited: OFF — no absolute limit by default

With Offline Session Max Limited = ON:

  • Offline Session Max: 60 days — absolute limit regardless of activity

Known issue (Keycloak 22-23): When “Offline Session Max Limited” is enabled, the token’s exp claim is based on Offline Session Idle rather than Offline Session Max, causing tokens to expire sooner than expected.

Fix: Increase Offline Session Idle or ensure your background processes refresh offline tokens within the idle period.

Authentication Session Timeout

Error: “authentication_expired” in redirect URL

https://your-app.com/callback?error=temporarily_unavailable&error_description=authentication_expired

The user’s login page sat idle too long. The authentication session expired before they completed the login flow.

Settings:

  • Login Timeout (default 30 minutes): Total time to complete the login flow
  • Login Action Timeout (default 5 minutes): Time for a single login step

Fix for slow login flows (MFA, email verification): Increase Login Action Timeout to 10-15 minutes.

SPA handling: When your SPA receives authentication_expired, retry the authentication request immediately. If the user has an active SSO session, re-authentication succeeds without a login prompt.

Remember Me Sessions

When “Remember Me” is enabled (Realm Settings → Login tab), users who check the checkbox get persistent cookies that survive browser close.

Separate timeouts (optional):

SettingEffect
Remember Me SSO Session IdleOverrides SSO Session Idle for remember-me sessions (0 = use default)
Remember Me SSO Session MaxOverrides SSO Session Max for remember-me sessions (0 = use default)

Common configuration: Set SSO Session Idle to 30 minutes for regular users, but Remember Me SSO Session Idle to 7 days for users who check “Remember Me”.

Docker and Kubernetes Session Issues

Sticky Sessions Required

Keycloak uses the AUTH_SESSION_ID cookie for session affinity. Without sticky sessions configured on your load balancer, authentication requests may hit different Keycloak nodes, causing intermittent session errors.

Nginx Ingress:

annotations:
  nginx.ingress.kubernetes.io/affinity: "cookie"
  nginx.ingress.kubernetes.io/session-cookie-name: "AUTH_SESSION_ID"

Sessions Lost After Pod Restart

Keycloak 26+: Persistent sessions are enabled by default. Sessions survive pod restarts because they’re stored in the database.

Keycloak 25 and earlier: Sessions are stored only in Infinispan memory. Pod restarts lose all sessions. Fix: enable persistent-user-sessions feature or use an external Infinispan cluster.

Common Kubernetes Session Issues

IssueCauseFix
Random logouts in clusterNo sticky sessionsConfigure load balancer affinity on AUTH_SESSION_ID
All sessions lost on restartVolatile sessions (KC < 26)Upgrade to KC 26+ or enable persistent-user-sessions
“Session doesn’t have required client”Cache eviction under loadIncrease --cache-embedded-client-sessions-max-count
Slow authentication in clusterRequests hitting non-owner nodesEnable sticky sessions

Debug Logging

Enable Session-Specific Logging

# Keycloak 22+ (Quarkus)
bin/kc.sh start --log-level="INFO,org.keycloak.protocol.oidc:TRACE,org.keycloak.models.sessions:DEBUG"

# Docker
docker run \
  -e KC_LOG_LEVEL="INFO,org.keycloak.protocol.oidc:TRACE,org.keycloak.models.sessions:DEBUG" \
  quay.io/keycloak/keycloak:latest start

Check Events via Admin API

# Get recent session errors
curl -s \
  "https://keycloak.example.com/admin/realms/myrealm/events?type=REFRESH_TOKEN_ERROR&max=50" \
  -H "Authorization: Bearer $ACCESS_TOKEN" | jq .

# Force logout a specific session
curl -s -X DELETE \
  "https://keycloak.example.com/admin/realms/myrealm/sessions/{sessionId}" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Event Types for Session Debugging

EventMeaning
LOGINNew user session created
LOGOUTSession terminated by user
CODE_TO_TOKENAuthorization code exchanged successfully
CODE_TO_TOKEN_ERRORCode exchange failed (expired code, PKCE mismatch)
REFRESH_TOKENToken refreshed, session idle timer reset
REFRESH_TOKEN_ERRORRefresh failed — session expired or revoked
USER_SESSION_DELETEDSession removed by admin or timeout

Enable event logging: Admin Console → Realm Settings → Events → User events settings → Save events = ON.

Enterprise (High Security)

SSCARSSlceOOicfeerSSnseeetsssshssSTiieoTooskonnsekineIMondanLlxiMe:Ifa:dex8ls1epR5h:aeonumu1:sir5ens1:umtim0enisuntuetse

Consumer Application

SSRRASSeecOOmmceeeSSmmseebbssseessrrTiioooMMknneeenIMSSdaSSLlxOOie:f:SSe3ees70sspssaddiinaaoo:yynnss1IM5dalxme:i:n9u30t0edsdaayyss

Mobile / Offline

SOOOASfffcOfffcllleSiiisennnsseeesTiSSSooeeeknsssesssnIiiidoooLlnnnief:IMMedaas3lxxp0e:a:Lnmi9:i3m0n0i5utdtdeameadyisy:snsuOtoNensline)