Keycloak server issuing already expired tokens

Hi there,

We recently began using Keycloak to issue access tokens using the OIDC Authorization Code flow, and have a custom app written in Golang which handles the flow/callbacks and saves the resulting access token as a cookie in the user’s browser. This app also has built in logic to request a new access token when the existing token in the cookie expires (after 12 hours).

This seems to work well most of the time, however occasionally we notice that an already logged in user (aka they have a login session with keycloak) receives an access token that is already expired from keycloak (that is, it’s exp time is in the past). This token obviously fails to validate and we return an error to users.

The only workaround we have currently is clearing all cookies for our Keycloak instance, so I suspect it is somehow tied to longer-running Keycloak sessions. Obviously this is not a great user experience, having to ask users to repeatedly clear cookies, so any help would be appreciated!

1 Like

That’s maybe not that, but have you checked that the Keycloak server time is fine (like ntpd synchronised) ?

Note that a client (browser) with a bad time synchronisation could also receive expired tokens.

Yep I confirmed that the Keycloak server time is correct, and it is happening to multiple clients, all of whom have correct time

So upon further testing, this seems related to the client’s “Client Session Idle Timeout”.

If I set the Client Session Idle Timeout to something low, like 1 minute, I can see it overrides the “Access Token Lifespan” value as well, and tokens I am issued only are valid for 1 minute. Additionally, if after 1 minute I try to issue a fresh access token, I am instead given an already expired token.

Does anyone know why this is the case? I am concerned that Keycloak’s internal session management is preventing valid tokens from being issued in certain cases.

1 Like

@nulltrope did u find any solutions to this?
I am facing same issue in a nextjs app

This comment put me on track of something interesting.

I have Keycloak 21.0.2 / next-auth 4.22.1 with a next 13.1.6 app

When I in Client settings (overriding Realm settings) set

  • Accesstoken lifespan to 1 minute
  • Client Session Idle to 2 minutes
  • Client session Max to 3 minutes (overriding Realm: SSO Session Max=10 hours)

After a minute and some seconds I navigate around, and a new access token is issued (refresh token exchange). The page starts LOOPING with { error: ‘invalid_grant’, error_description: ‘Token is not active’ } in the terminal as response to the token exchange.

Interestingly, the refresh token here is shorter lived than the access token:

expires_in: 60,
refresh_expires_in: 46,  // NOTE refresh_token is shorter lived.

HOWEVER, when I set Realm to SSO Session Max = 3 minutes and override:

  • Accesstoken lifespan to 1 minute
  • Client Session Idle to 2 minutes

then the refreshtoken is [correctly, I think] set to the access token expiry after a couple refreshes, and the page does NOT loop. It navigates to the SSO signon page (Keycloak page).

expires_in: 33,
refresh_expires_in: 33,

In summary, If I override SSO Session Max with Client Session Max of 3 minutes, after the Session maxes out after 3 minutes I get

  • refresh token exchange fails with { error: ‘invalid_grant’, error_description: ‘Token is not active’ } which is expected, but then
  • signIn() seemingly tries to do a token exchange with the old refreshtoken, because I see that error, and never get to the SSO page
  • even if I signOut(); and then signIn(), it STILL tries to do token exchange → eternal loop and never see the SSO page.

If I don’t override SSO Session Max, it behaves as expected.

(I would expect the two situations above to produce the same result, since SSO Session Max = 3 minutes or Client Session Max = 3 minutes should effectively be the same setting).

Will keep digging :slight_smile:

After quite some testing I filed Client Session Max isn't an exact override for SSO Session Max · Issue #21038 · keycloak/keycloak · GitHub on this; I think it must be a bug.

Thanks for logging this down. I’ve experienced the exact same issue and this helped me to quickly resolve it.