[keycloak-user] Automatic one-time login

Manuel Bleichenbacher manuel.bleichenbacher at acrea.com
Mon Jun 24 04:43:23 EDT 2019


Our implementation for the automatic one-time login is making good progress. We've now got a REST service that can create an action token and an action token handler that logs the user in (see main code below). It uses an authentication flow with no steps/executions.

If we use to action token key and build a URL like http://localhost:8180/auth/realms/myrealm/login-actions/action-token?key=eyJhbGciOiJI... then the user is login in but ends up in the account console.

Now we would like to integrate it into our Spring Boot application and would be grateful for some hints:

- How can we initiate an OIDC flow from Spring Boot with the action token URL?
- How can we ensure that the flow ends on a specific page in our application?

Regards
Manuel



public class DirectLoginActionTokenHandler extends AbstractActionTokenHander<DirectLoginToken> {

    public DirectLoginActionTokenHandler() {
        super(DirectLoginToken.TOKEN_TYPE, DirectLoginToken.class, "not_allowed", EventType.LOGIN, "invalidCodeMessage");
    }

    @Override
    public Response handleToken(DirectLoginToken token, ActionTokenContext<DirectLoginToken> tokenContext) {
        return tokenContext.processFlow(false, LoginActionsService.AUTHENTICATE_PATH,
                tokenContext.getRealm().getFlowByAlias("direct login"), null, new AuthenticationProcessor());
    }

    @Override
    public String getAuthenticationSessionIdFromToken(DirectLoginToken token, ActionTokenContext<DirectLoginToken> tokenContext, AuthenticationSessionModel authenticationSessionModel) {
        return null;
    }

    @Override
    public AuthenticationSessionModel startFreshAuthenticationSession(DirectLoginToken token, ActionTokenContext<DirectLoginToken> tokenContext) {
        return tokenContext.createAuthenticationSessionForClient(token.getIssuedFor());
    }

    @Override
    public boolean canUseTokenRepeatedly(DirectLoginToken token, ActionTokenContext tokenContext) {
        return false;
    }
}

-----Ursprüngliche Nachricht-----
Von: Dmitry Telegin <demetrio at carretti.pro> 
Gesendet: Dienstag, 18. Juni 2019 19:12
An: Manuel Bleichenbacher <manuel.bleichenbacher at acrea.com>; keycloak-user at lists.jboss.org
Betreff: Re: AW: [keycloak-user] Automatic one-time login

Hi Manuel, you're welcome,

On Tue, 2019-06-18 at 14:02 +0000, Manuel Bleichenbacher wrote:
> Hi Dmitry
> 
> Thanks so much for your valuable input. It contains so much useful information.
> 
> I had studied the action-token-authenticator quickstart example before but I can't see how we could fit it into our solution. I haven't mentioned so far that an unregistered user never goes to a login or registration page. Instead the flow is similar to what you find in some web shops: a customer purchases some items and - as part of the checkout process - enters email address and mobile phone number. After the checkout is complete, the customer is asked if an account should be created for him. Up to this moment, Keycloak has not been involved and no authentication or registration flow has been initiated. And since no further entry is needed (in the future the user will log in with email address and a one-time password sent to the mobile number), the Keycloak user can be immediately created and the customer can immediately be logged in.
> 
> So given this flow: the quickstart example with a switch from the Keycloak flow to an external application and back is probably not applicable, right?

Correct. This is exactly what I meant by "Had you been using Keycloak's registration flow, this quickstart could have been applicable entirely". Third conditional :)

In other words, you should use this quickstart just as a source of inspiration if you decide to go with action token handler + authenticator + app-specific token instead of REST + one-time code.

Cheers,
Dmitry

> 
> Regards
> Manuel
> 
> -----Ursprüngliche Nachricht-----
> Von: Dmitry Telegin <demetrio at carretti.pro>
> Gesendet: Dienstag, 18. Juni 2019 15:14
> An: Manuel Bleichenbacher <manuel.bleichenbacher at acrea.com>; 
> keycloak-user at lists.jboss.org
> Betreff: Re: [keycloak-user] Automatic one-time login
> 
> Hi Manuel,
> 
> You might even avoid implementing one-time code logic (incl. REST endpoint, custom credential etc.) by using the approach demonstrated in the quickstart [1].
> 
> Had you been using Keycloak's registration flow, this quickstart could have been applicable entirely (modulo authentication vs. registration flow), but still you can borrow the main idea from it: using app-specific signed token (instead of one-time code) to assert that registration succeeded.
> 
> Keycloak already supports one-time action tokens (see org.keycloak.authentication.actiontoken.ActionTokenHandler::canUseTokenRepeatedly). To ensure that your app-specific token is one-time too, you could associate it with the "parent" action token using the latter's "nonce" claim. One thing you need to know about one-time action tokens in Keycloak - this is done via org.keycloak.models.ActionTokenStoreProvider, and the default implementation (o.k.models.sessions.infinispan.InfinispanActionTokenStoreProvider) is non-persistent, so if by some reason the whole cluster gets restarted before action token expires, it could be potentially reused.
> 
> Otherwise, both options that you described should be viable. Please find the answers below.
> 
> On Tue, 2019-06-18 at 08:03 +0000, Manuel Bleichenbacher wrote:
> > Hi everybody,
> > 
> > Our new application will have a length user registration procedure that we would like to keep separate from Keycloak (it will mainly require application data, reuse part of the application's UI etc.). At the end of the registration procedure, we would still like to automatically login the user so he/she doesn't need to reenter the username and password. What are our options to achieve it?
> > 
> > The backend will certainly use a privileged Keycloak user (e.g. to create the new user via the REST Admin API). And the result of the login should be that the user's access token (JWT) is available in the user's session in the backend. So far we have come up with the following options:
> > 
> > Option A: REST endpoint / custom authenticator
> > 
> > - Add a custom REST endpoint so the backend can create a one-time 
> > code and save it as a credential on the new user
> > - Add a custom authenticator to the browser flow that checks for the 
> > one-time code
> > - The user would then be directed to the regular authentication flow. If the one-time code is present and correct, the username/password step and possibly all other authentication steps will be skipped and the authentication immediately succeeds.
> > 
> > Option B: REST endpoint / action token
> > 
> > - Add a custom REST endpoint so the backend can create a one-time 
> > code and save it as a credential on the new user
> > - Implement an additional action token handler that checks the 
> > one-time token to authenticate the user
> > - The user would then be directed to the action token URL. If the one-time code is correct, the user is authenticated.
> > 
> > What is your recommendation:
> > - Are these feasible options?
> > - Are we missing a good option?
> > 
> > For option A: How can we pass the one-time code to the authentication flow? Can we use a URL parameter, HTTP header attribute?
> 
> This is possible, but not much reliable because of HTTP redirects. After a redirect, the initial parameters will be lost (as well as headers), and you'll need to parse the parameter out of Referer header. Check out this thread [2] for details.
> 
> However, there exists a hack so that you can use "scope" parameter to pass data reliably, see this thread for details [3].
> 
> > For option B: Can the action token flow initiate the OAUTH2 flow and return an authorization code? Can this flow be easily integrated with the Spring Boot  adapter?
> 
> Yes, see this [4]. AFAIK for the adapter it should look like an ordinary flow, it won't even know it had been initiated via action token handler.
> 
> [1] 
> https://github.com/keycloak/keycloak-quickstarts/tree/latest/action-to
> ken-authenticator [2] 
> https://lists.jboss.org/pipermail/keycloak-user/2018-November/016230.h
> tml [3] 
> https://lists.jboss.org/pipermail/keycloak-user/2019-May/018393.html
> [4] 
> https://github.com/keycloak/keycloak-quickstarts/blob/latest/action-to
> ken-authenticator/src/main/java/org/keycloak/quickstart/actiontoken/to
> ken/ExternalApplicationNotificationActionTokenHandler.java#L89
> 
> Good luck,
> Dmitry Telegin
> 
> Carretti Consulting OÜ | Keycloak Consulting and Training Sepapaja 6, 
> Tallinn 15551, Estonia | info at carretti.pro
> 
> > Any input is appreciated.
> > 
> > Thanks
> > Manuel
> > 
> > --
> > manuel bleichenbacher | senior consultant m +41 79 617 90 01 | 
> > manuel.bleichenbacher at acrea.com
> >  
> > acrea ag | konradstrasse 32 | 8005 zürich www.acrea.com | 
> > blog.acrea.com
> >  
> > www.nezasa.com - incubated by Acrea
> > 
> > 
> > _______________________________________________
> > keycloak-user mailing list
> > keycloak-user at lists.jboss.org
> > https://lists.jboss.org/mailman/listinfo/keycloak-user




More information about the keycloak-user mailing list