Create "online session" from offline session

Hello,

This question is a follow up on this question :
https://lists.jboss.org/pipermail/keycloak-dev/2018-October/011296.html

Stian Thorgersen was mentioning that a custom authenticator would be included soon . Is it the case ?

The reason why I am asking is because I am trying to open a webpage within a mobile application. The mobile application uses offline sessions to be constantly logged in. When you open the webpage within the mobile application, how do you get automatically logged in ?

Thank you

Any news on that subject ? Thank you!

I don’t think this authenticator ever got off the ground. We had to implement a custom resource that would act like an authenticator by stripping out an auth token from the request, load associated offline session and then create a new session from that. There appear to be a few variations to the state the “on and offline sessions” but in essence the creation of a new session from an offline session does look something like below. Our use case was specific to a mobile app that had been swapping refresh tokens with the identity provider for an extended amount of time and the user did not hold any “keycloak cookies” in the browser that would support the SSO hop to another client. We simply used the same browser widget to call a rest endpoint on the keycloak server which would then activate a session and return the right cookies for the browser to recognise the user as being logged in. Lots of caveats as this approach only works for a very limited used case. Unit testing this was a nightmare as the keycloak server does all sort of magic when the calls descend into things like the AuthenticationManager. An OOTB solution for better offline session management would be good, the current user experience is pretty poor in native mobile apps land.

// capture inputs like redirect url and parse/validate access token

final UserSessionModel offlineSession = session.sessions().getOfflineUserSession(realm, token.getSessionState());

RootAuthenticationSessionModel rootAuthSession = session.authenticationSessions().getRootAuthenticationSession(realm, offlineSession.getId());
if (rootAuthSession == null) {
  rootAuthSession = session.authenticationSessions().createRootAuthenticationSession(offlineSession.getId(), realm);
}

AuthenticationSessionModel authSession = rootAuthSession.createAuthenticationSession(client);
authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
authSession.setClientNote(OIDCLoginProtocol.ISSUER, token.getIssuer());
authSession.setClientNote(OIDCLoginProtocol.SCOPE_PARAM, "openid");
authSession.setAuthenticatedUser(offlineSession.getUser());

// create an online session from the offline session
UserSessionModel userSession = session.sessions().createUserSession(
  authSession.getParentSession().getId(),
  realm,
  authSession.getAuthenticatedUser(),
  authSession.getAuthenticatedUser().getUsername(),
  context.getConnection().getRemoteAddr(),
  OIDCLoginProtocol.LOGIN_PROTOCOL,
  false,
  offlineSession.getBrokerSessionId(),
  offlineSession.getBrokerUserId());

// attach auth to user session
clientSessionContext = TokenManager.attachAuthenticationSession(session, userSession, authSession);

offlineSession.setLastSessionRefresh(Time.currentTime());

userSession.setLastSessionRefresh(Time.currentTime());

AuthenticationManager.setClientScopesInSession(authSession);

AuthenticationManager.createLoginCookie(session, realm, userSession.getUser(), userSession, context.getUri(), context.getConnection());

return Response.temporaryRedirect(uri).build();

Thank you very much @nielsbne . I got it working with your explanations. It would be good if that could be working out of the box ; like you said the mobile experience can be quick poor.