[keycloak-user] Identity provider, keycloak js adapter and session management

Peter Nalyvayko petervn1 at yahoo.com
Thu Jul 6 12:10:47 EDT 2017


Hi,

We've hit a bit of a snag while setting up our one page js client. Changing the value of the "sub" claim to anything other than the unique identifier of the keycloak user causes the keycloak adapter to detect the changes to the session and clear out the tokens, forcing the users to re-log in after every 5 seconds. 
 
We are using the version 2.3.0 of keycloak. Our app is set up to use keycloak.js adapter for all things related to OIDC. The adapter is configured to use the "code authorization" (standard) flow. The instance of keycloak is configured to use an external OIDC identity provider and the users are uniquely identified by their e-mails. Naturally, we wanted that the "sub" claim in the claim set returned by calling the keycloak's OIDC /token endpoint would return the unique identity of the external user rather than the internal identifier of the keycloak user, so we re-configured the keycloak client by adding a property mapper to map the user's email to the "sub" claim, here the example of the access token: 
{
   "sub": "user at company.com",
   "iat": 223235098325,
   "email": "user at company.com",
   ...
} 

Once we had implemented these changes on the keycloak side, our users were able to initially sign into the application, but when they tried to access any functionality within the app, they would be prompted to sign in again. The problem seems to related to the OIDC session management and the assumption and the "sub" claim always matches the keycloak user's unique identifier. 

We narrowed the problem down to four components:

- keycloak.js
- login-status-iframe.html
- services\srv\main\java\org\keycloak\protocol\oidc\endpoints\LoginStatusIframeEndpoint.java
- services\src\main\java\org\keycloak\services\managers\AuthenticationManager.java
 
In keycloak.js, line 637, the implementation creates a session id to be used to check the session state. Notice that the code uses the value from the "sub" claim: 
   var sessionId = kc.realm + "/" + kc.tokenParsed.sub;
  
In AuthenticationManager.createLoginCookie, line 306, the value of the "SESSION_COOKIE" is set to:

  String sessionCookieValue = realm.getName() + "/" + user.getId();

Sadly, in our configuration, the value returned of by user.getId() is not the same as the value stored in the "sub" claim, thus causing the session management code in login-status-iframe.html, line 53 to clear out any tokens and force the users to re-login the next time it checks the session state (default is 5 second intervals):

  var cookie = getCookie();
  if (sessionState == cookie) { ... } else { callback("changed"); }  

 
Looking at the LoginStatusIframeEndpoint.preCheck (LoginSatusIframeEndpoint.java, lines 71-93), we've noticed that the implementation does not even make use of the user identity, only the session id.

The workaround, at least temporary, for us was to add the "id" claim containing the user identity internal to keycloak, and modify the keycloak JS adapter code to look for the "id" claim and use its value instead of the value in the "sub" claim when creating the session id, i.e.:

  
   var sessionId;
   if (kc.tokenParsed.id) {
      sessionId = kc.realm + "/" + kc.tokenParsed.id;
   } else {
      sessionId = kc.realm + "/" + kc.tokenParsed.sub;
   }

Is this a bug, or does it work as intended, i.e. the users should never set the "sub" claim to anything other than the keycloak's user identity? If this is a bug, I can submit a JIRA request and a fix as long as the workaround above seems like an acceptable solution

Any comments are welcome
Regards,
Peter


More information about the keycloak-user mailing list