[keycloak-user] session timeout behavior when using the Spring Security adapter
Sud Ramasamy
to_sud at yahoo.com
Wed Nov 22 08:24:43 EST 2017
It looks like when using Keycloak and Spring Security with the OIDC Client protocol there is a way to hose the application session unintentionally when the Keycloak SSO session timeout setting is lower than the application (ie. Client) session timeout value.
If the user accesses any parts of the application which are protected by the Keycloak adapter after the access token has expired (configured for 5 minutes) without first ending the application session, Spring Security still has the authentication object. But as part of the authentication flow in the application, the Keycloak adapter checks to see if the Access token is active which it won't be at this point. So the Keycloak adapter (RefreshableKeycloakSecurityContext.java) attempts to get a new Access token using the refresh token it has. Since the refresh token has been invalidated in Keycloak the adapter receives a "Stale refresh token" error response from Keycloak. The "no access token" is propagated to the Keycloak adapter's OAuthRequestAuthenticator.java which proceeds to trigger a login redirect to Keycloak. Once the user is successfully authenticated in Keycloak and control is returned to the KeycloakAuthenticationProcessingFilter.java as a final step it attempts to store the KeycloakAuthenticationToken in the Spring SecurityContextHolder (see SpringSecurityTokenStore.saveAccountInfo). Here the code throws an exception because there is already an existing KeycloakAuthenticationToken in the SecurityContextHolder from the earlier login that wasn't cleared.
At this point SSO login into the application is hosed. A potential fix is to trigger a call to the application’s logout endpoint which will clear the Spring SecurityContextHolder object prior to fetching a new access token.
I was wondering if anyone has run into this behavior. It seems like when using the OIDC Client protocol by it’s very nature of using short lived Access tokens and Refresh tokens that are tied to the Keycloak session we will have to set the Keycloak Session timeout to be the same or higher than the Client session timeout. But we do not necessarily have control over the clients. So we will have to set the Keycloak session timeout to the highest session timeout across all Clients since this is realm level setting and not a per Client setting. But this breaks another use case since we are using Identity Brokering. We want the user to be bounced to the external Identity Provider when their application session timeouts. If the Keycloak session timeout is higher than their application session timeout then they wouldn’t be bounced to the external Identity Provider for authentication. Looks like we might need to force Keycloak to initiate the authentication when we detect an application timeout.
-sud
More information about the keycloak-user
mailing list