keycloak invalid_token - token expired before skew allowance
Fixes Keycloak 'invalid_token - token expired' rejections with skew-aware validation. Use when valid tokens get rejected at expiry boundaries. Key trigger: the exact expired-before-skew message.
keycloak invalid_token - token expired before skew allowance
TL;DR
The token expired just before the allowed clock-skew window, so Keycloak rejected it. The real fixes are longer-lived tokens where appropriate, refreshing before expiry, and keeping clocks in sync. Chasing the skew allowance itself is treating the symptom.
keycloak: invalid_token - token expired before skew allowanceSteps
Check the token's exp claim vs the rejection time: how far past expiry was it. Expected: The gap is measured.
Sync clocks between the client, Keycloak, and the resource server. Expected: Skew is minimized.
Refresh tokens before expiry: request the new token at 80% of lifetime, not after 401s. Expected: Tokens never arrive expired.
Review the token lifetime for the client: if it is too short for the use case, extend it deliberately. Expected: The lifetime fits the flow.
Keep the skew allowance at its default; widening it weakens replay protection. Expected: The security property holds.
When to use
- Keycloak rejects tokens at expiry boundaries
- clocks may differ between systems
- short-lived tokens in slow flows
When not to use
- tokens are long-expired (that is not a skew problem)
- the token was never valid (check the signature and issuer)
- the client clock is wildly off (fix the clock, not the allowance)
Tool compatibility
- Keycloak
- OAuth2/OIDC
Variant phrasings
- "keycloak invalid_token token expired"
- "keycloak skew allowance expired"
- "keycloak token expired before skew"
Why it happens
Token validation allows a small clock-skew grace, but a token that expired beyond the grace is simply expired. Systems with slow flows or drifting clocks hit the boundary constantly. The durable fix is timely refresh and synced clocks; the skew allowance is a tolerance, not a lifetime extension.
Edge cases
- do not widen the skew allowance as a fix; it weakens security for every client
- the 80%-lifetime refresh rule needs the client to know the lifetime; read it from the token
- service-to-service flows need their own refresh discipline; they cannot prompt a user
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_qt6yAzqJvodYinNdqdO4Cg