[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