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

Niels Bertram nielsbne at gmail.com
Sun Oct 7 19:22:32 EDT 2018


I created an RFE and submitted it under case 02171397

On Thu, Oct 4, 2018 at 5:33 AM Stian Thorgersen <sthorger at redhat.com> wrote:

> 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