[keycloak-dev] Create "online session" from offline session

Stian Thorgersen sthorger at redhat.com
Wed Oct 3 15:33:14 EDT 2018


I would say this is a common use-case and is something we should support
properly. Can you open an RFE for it? We can't include it for 7.3 I'm
afraid, but it's something we could aim to include in the release after
that. Without having thought too deeply on how it could be solved I would
imagine something that lets you decide what type of session you want based
on some sort of condition. Perhaps we could have a per-client option to
control the SSO session type and if the initial authentication is trigger
with login to such a client it would trigger a long lived session.

I guess the best option for you then is a custom authenticator, which
hopefully in the not to distant future you can drop and no longer have to
maintain. Hopefully Marek can help you with this one ;)

On Wed, 3 Oct 2018 at 16:54, Niels Bertram <nielsbne at gmail.com> wrote:

> We mainly need a function to create a "long lived" session in a mobile app
> where we have more options to secure the refresh/id token (e.g. place
> refresh/id tokens into iOS keychain and after some interval let the
> device/user unlock the tokens for the app using face id, fingerprint or
> pin). Inside the app we want to display a website that also participates in
> SSO and be seamlessly recognised as logged in. The current remember me
> function does not work for this as we do not want to increase the Max
> Session Idle time for *all* SSO enabled systems to anything beyond an
> hour. The only way we found to get a longer token for a mobile app is to
> use offline access scope - not ideal but we exhausted all avenues on
> remember me including 2 RH support tickets without a resolution.
>
> The challenge we face now is that having an offline session is managed
> outside the browser and after the initial 30 minute Max Session Idle time,
> we can no longer SSO someone in a browser window due to no valid user
> session in KC backend.
>
> I dug around a bit and found that one can setup a "sub session" from the
> id token from an offline session. This session and related cookies can be
> used like any other normal "user session" within a website. The trick was
> to load the "offline session" belonging to the offline access token and
> then create a user session like this:
>
>         userSession = session.sessions().createUserSession(
>           offlineSession.getId(),
>           realm,
>           offlineSession.getUser(),
>           offlineSession.getLoginUsername(),
>           ctx.getConnection().getRemoteAddr(),
>           "openid-connect",
>           false,
>           offlineSession.getBrokerSessionId(),
>           offlineSession.getBrokerUserId());
>
> We tested this with the approach outlined in my initial email and it does
> appear to work as intended (bar the client id not populated on the created
> session - the method call is missing a client param). The advantage of this
> approach is that we merely create a valid user session for the client_id of
> the current mobile app in KC server, set the session and id cookie in the
> webview and then refer out to another website via regular link. I do not
> need to know where this link leads to or if the client(_id) of the other
> site requires different scope, consent or whatever. I simply created a
> "short lived" user session for the mobile app that can be consulted by the
> SSO server in an auth check on another SSO enabled system.
>
> So taking all of this, we could build an authenticator that sets up a
> child session for the offline session under the same client that owns the
> ID token and send the cookies for that child session to the client browser.
> The big question is, where do you redirect the response to? If you redirect
> to another system that uses their own client, I am not sure what would
> happen if that client tried to swap the code grant for tokens - my
> assumption would be, it would get whatever the client swapping the code
> grant could get - but that is flawed if consent is required before hand for
> instance. I think the use case for which to use such adapter will be vital
> for the design - the use case I have does appear to be more like a rework
> of session and remember me is required than an authz adapter.
>
> Hope all that makes any sense.
>
>
> On Wed, Oct 3, 2018 at 9:46 PM Stian Thorgersen <sthorger at redhat.com>
> wrote:
>
>> I think we really need to consider if and how we add it properly. You
>> shouldn't be able to use any odd id token to authenticate, but rather a
>> special token. Further, it probably does require proper handling of
>> authentication levels. Or even perhaps you can authenticate for a specific
>> client with an id token, but when you try to use a different client you
>> need to provider username/password. End of the day we just need to be very
>> careful about adding something like this.
>>
>> By the way a long time ago I actually had this in mind as a way of doing
>> SSO for CLIs. You simply get a special id token that serves as the sso
>> cookie. Never got around to think it through in depth though. Bill had some
>> concerns with that idea, can't remember exactly what, so he ended up doing
>> token exchange for kcinit (I have quite a lot of concerns around that and
>> token exchange though).
>>
>> On Wed, 3 Oct 2018 at 14:00, Marek Posolda <mposolda at redhat.com> wrote:
>>
>>> Yes, I see some possible issues with it. IMO if we add it, it should
>>> probably not even be added in default "browser" flow, so it's more "hard"
>>> to have it working and just someone, who knows what he is doing, will be
>>> able to setup it.
>>>
>>> On the other hand, may be useful for some deployments where the
>>> applications are "trusted". IMO it could be fine if the security
>>> implications are described in the documentation.
>>>
>>> Marek
>>>
>>> On 03/10/18 09:39, Stian Thorgersen wrote:
>>>
>>> I'm not quite convinced about this approach.
>>>
>>> Firstly it seems like a workaround. Offline sessions are designed for
>>> applications that want to have access when the user is not around. Not for
>>> a "permanent" log-in. I would rather consider options that allows different
>>> SSO session expiration depending on device type (or initiating client) for
>>> instance. Once you have an SSO session in the system browser on the phone
>>> you can use an inapp browser tab to enable SSO to all apps, or you can do
>>> it for individual apps by not using the system browser.
>>>
>>> Secondly authenticating with id_token_hint is scary. For example a less
>>> trusted application could then use the ID token to authenticate as the user
>>> behind the covers and have access to everything the user has access to
>>> rather than the limited scope that it should have.
>>>
>>> On Wed, 3 Oct 2018 at 09:11, Marek Posolda <mposolda at redhat.com> wrote:
>>>
>>>> On 02/10/18 17:15, Niels Bertram wrote:
>>>> > Thanks for the response Marek. I implemented a custom authenticator
>>>> > before so that makes all total sense. The parts I am a bit worried
>>>> > about is:
>>>> >
>>>> > a) the GET implementation would require use to send the IDToken
>>>> > unprotected in the URL (POST is fine)
>>>> I see. This makes sense and we support sending POST request to the
>>>> initial Authentication endpoint. Maybe you can add a flag to the
>>>> authenticator like "Allow POST method only" to specify if it accepts
>>>> just POST or allow both POST and GET? Flag can be set to ON by default
>>>> (hence accept only POST).
>>>> >
>>>> > b) a mobile app from which we want to initiate the "sign me in and
>>>> > then redirect me to another website" would effectively need to
>>>> > whitelist every possible URL that it can redirect to.
>>>> >
>>>> > If I send a PR to latest Keycloak, any chance that can be patched
>>>> into
>>>> > current or next version of RH-SSO?
>>>> Yes, once the PR is accepted, it always go to the latest Keycloak
>>>> upstream and latest Keycloak always "turns" after some time to RH-SSO.
>>>> Some details about this https://www.keycloak.org/support.html .
>>>>
>>>> Just a note that we're close to feature freeze for Keycloak 4.x (RHSSO
>>>> 7.3), so if you want it in RHSSO 7.3, you need to be a bit quick though
>>>> :) And even then no guarantee as we will need some time for PR review
>>>> etc.
>>>>
>>>> Marek
>>>> >
>>>> > Cheers,
>>>> > Niels
>>>> >
>>>> > On Wed, Oct 3, 2018 at 12:33 AM Marek Posolda <mposolda at redhat.com
>>>> > <mailto:mposolda at redhat.com>> wrote:
>>>> >
>>>> >     I suggest to use the flow like this:
>>>> >     1) Exchange the offline token for the 3 tokens, which will include
>>>> >     the
>>>> >     triplet of (access token, id token, offline token).
>>>> >
>>>> >     2) Then you can pass the just retrieved IDToken in the
>>>> authentication
>>>> >     request in the "id_token_hint" parameter.
>>>> >
>>>> >     3) Then you will need to create Authenticator (see our
>>>> >     docs/quickstarts
>>>> >     for more details), which will be able to see if "id_token_hint"
>>>> >     was sent
>>>> >     and then verify this token and authenticate user if it was ok. You
>>>> >     can
>>>> >     probably use some existing code from IDToken introspection
>>>> >     endpoint. If
>>>> >     parameter is not used, authenticator can be just ignored during
>>>> the
>>>> >     authentication flow.
>>>> >
>>>> >     4) As last step, you will need to add this authenticator to the
>>>> >     browser
>>>> >     authentication flow.
>>>> >
>>>> >     This will cause that if IDToken is sent, it will be able to use
>>>> it to
>>>> >     authenticate the user and hence new UserSessionModel (+cookies and
>>>> >     all
>>>> >     of this) will be properly created by Keycloak itself.
>>>> >
>>>> >     If you manage to make this working, we will be happy if you
>>>> >     contribute
>>>> >     it in the PR :) As this is described in the OIDC specification
>>>> (see
>>>> >     https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
>>>> >     ), but
>>>> >     we don't yet implement it.
>>>> >
>>>> >     If you don't want to send PR, you may implement it a bit easier
>>>> and
>>>> >     differently in a non-OIDC standard way (EG. pass the offline_token
>>>> >     directly instead of IDToken in step 2).
>>>> >
>>>> >     Marek
>>>> >
>>>> >     On 02/10/18 08:24, Niels Bertram wrote:
>>>> >     > Hi devs,
>>>> >     >
>>>> >     > we are trying to turn an offline session back into an "online
>>>> >     session" for
>>>> >     > which we can generate cookies and send them to the clients
>>>> browser.
>>>> >     >
>>>> >     > I tried to create a user session with AuthenticationManager but
>>>> >     for some
>>>> >     > reason the created session is not showing up as a proper in the
>>>> user
>>>> >     > account management section. Is there anything that needs to
>>>> >     happen after
>>>> >     > this session is created to make it a normal user session?
>>>> >     >
>>>> >     > AuthenticatedClientSessionModel clientSession =
>>>> >     > session.sessions().createClientSession(realm, client,
>>>> >     offlineSession);
>>>> >     >
>>>> >     > We have a mobile app that uses offline_access to create an
>>>> >     "always logged"
>>>> >     > in experience for the app user. However when we open a
>>>> >     SSO-enabled website
>>>> >     > in the app (WebView), there is no KEYCLOAK_SESSION cookie to
>>>> >     allow the web
>>>> >     > page to initiate a successful pre-auth check.
>>>> >     >
>>>> >     > We wrote a custom resource which we call in our webview to
>>>> >     "redirect" the
>>>> >     > user to an SSO enabled site:
>>>> >     >
>>>> >     > 1. authenticate the user
>>>> >     >
>>>> >     > AuthResult auth = new
>>>> >     AppAuthManager().authenticateBearerToken(session)
>>>> >     >
>>>> >     > 2. load a valid userSession
>>>> >     >
>>>> >     > UserSessionModel userSession =
>>>> >     session.sessions().getUserSession(realm,
>>>> >     > token.getSessionState());
>>>> >     >
>>>> >     > 3. create the session cookies
>>>> >     >
>>>> >     > AuthenticationManager.createLoginCookie(session, realm, user,
>>>> >     userSession,
>>>> >     > ctx.getUri(), ctx.getConnection());
>>>> >     >
>>>> >     > 4. forward the user to the SSO enabled website
>>>> >     >
>>>> >     > 5. SSO enabled website would do a normal pre-auth check with
>>>> >     prompt=none
>>>> >     >
>>>> >     > There was a similar conversation about the "lost" session in
>>>> >     KEYCLOAK-4201
>>>> >     > <https://issues.jboss.org/browse/KEYCLOAK-420>, but that one
>>>> did
>>>> >     not go as
>>>> >     > far as creating a new session.
>>>> >     >
>>>> >     > Anyone of you got any clever idea on how do "preload" a valid
>>>> >     SSO session
>>>> >     > into a WebView?
>>>> >     >
>>>> >     > Cheers,
>>>> >     > Niels
>>>> >     >
>>>> >     > PS. we are on RH-SSO 7.2.4 so roughly Keycloak 3.4.3
>>>> >     > _______________________________________________
>>>> >     > keycloak-dev mailing list
>>>> >     > keycloak-dev at lists.jboss.org <mailto:
>>>> keycloak-dev at lists.jboss.org>
>>>> >     > https://lists.jboss.org/mailman/listinfo/keycloak-dev
>>>> >
>>>> >
>>>>
>>>> _______________________________________________
>>>> keycloak-dev mailing list
>>>> keycloak-dev at lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/keycloak-dev
>>>>
>>>
>>>


More information about the keycloak-dev mailing list