[keycloak-user] How to dynamically trigger a custom required action in a flow ?

Sebastien Blanc sblanc at redhat.com
Tue Apr 30 04:19:09 EDT 2019


If you believe their is a inconsistency please open a JIRA, tbh I don't
know that much about the implementation details of this part.
You probably have but worth asking : have you set the priority of your
custom required action ? I can see that "Update password" has prio 30 , so
your custom action should be >30 (0 is the highest priority) if you want it
to be run after.
And regarding sort by names and priority, if I look at the implementation
of the comparator it looks like it first sort by prio and after that by
name (if they have the same prio).




On Tue, Apr 30, 2019 at 9:43 AM GESLIN Fabrice <
fabrice.geslin-prestataire at laposte.fr> wrote:

> Hi Sébastien,
>
>
>
> We’ve finally found the addRequiredAction() function with the String
> parameter and it works.
>
>
>
> But we felt into a new issue due to the fact that the required actions are
> sometime handled sorted and sometime not sorted.
>
>
>
> For instance, at the end of the authentication flow processing, when the
> required actions are processed, they are treated in an arbitrary order that
> doesn’t even correspond to the order in which they were added.  In Keycloak
> release 4.8.3.FINAL, The call stack leads to line 893 of
> org.keycloak.services.managers.AuthenticationManager that is:
>
>
>
>     public static String nextRequiredAction(final KeycloakSession session,
> final AuthenticationSessionModel authSession,
>
>                                             final ClientConnection
> clientConnection,
>
>                                             final HttpRequest request,
> final UriInfo uriInfo, final EventBuilder event) {
>
>         final RealmModel realm = authSession.getRealm();
>
>         final UserModel user = authSession.getAuthenticatedUser();
>
>         final ClientModel client = authSession.getClient();
>
>
>
>         evaluateRequiredActionTriggers(session, authSession,
> clientConnection, request, uriInfo, event, realm, user);
>
>
>
>         if (!user.getRequiredActions().isEmpty()) {
>
>             return user.getRequiredActions().iterator().next();
>
>         }
>
>         if (!authSession.getRequiredActions().isEmpty()) {
>
>             return authSession.getRequiredActions().iterator().next();
>
>         }
>
>
>
> This causes the user to be redirected to the URI of the required action
> that has been arbitrarily selected. *But* when the browser GET the
> corresponding URI, the call stack reaches line 1045 of
> org.keycloak.services.managers.AuthenticationManager where the required
> actions are sorted according to their priorities or their names (?!?):
>
>
>
>     protected static Response executionActions(KeycloakSession session, AuthenticationSessionModel authSession,
>
>                                                HttpRequest request, EventBuilder event, RealmModel realm, UserModel user,
>
>                                                Set<String> requiredActions) {
>
>
>
>         List<RequiredActionProviderModel> sortedRequiredActions = sortRequiredActionsByPriority(realm, requiredActions);
>
>
>
>         for (RequiredActionProviderModel model : sortedRequiredActions) {
>
>             RequiredActionFactory factory = (RequiredActionFactory)session.getKeycloakSessionFactory().getProviderFactory(RequiredActionProvider.class, model.getProviderId());
>
>             if (factory == null) {
>
>                 throw new RuntimeException("Unable to find factory for Required Action: " + model.getProviderId() + " did you forget to declare it in a META-INF/services file?");
>
>             }
>
>             RequiredActionContextResult context = new RequiredActionContextResult(authSession, realm, event, session, request, user, factory);
>
>             RequiredActionProvider actionProvider = null;
>
>             try {
>
>                 actionProvider = createRequiredAction(context);
>
>             } catch (AuthenticationFlowException e) {
>
>                 if (e.getResponse() != null) {
>
>                     return e.getResponse();
>
>                 }
>
>                 throw e;
>
>             }
>
>             actionProvider.requiredActionChallenge(context);
>
>
>
> The side effect of this inconsistency is that in our case, where we’ve
> added a custom required action after the UPDATE_PASSWORD required action to
> the reset credential flow, the user is first redirected to the URI of our
> custom action (which is not what we expected) AND the form that is
> challenged to the user once redirected is the one from the UPDATE_PASSWORD
> action !
>
>
>
> The question is how can we have the required actions that are added to a
> flow be processed according to the order in which they are added ?
>
>
>
> Regards,
>
>
>
> Fabrice Geslin
>
>
>
> Groupe La Poste
>
>
>
> *De :* Sebastien Blanc [mailto:sblanc at redhat.com]
> *Envoyé :* lundi 29 avril 2019 14:35
> *À :* GESLIN Fabrice <fabrice.geslin-prestataire at laposte.fr>
> *Cc :* keycloak-user at lists.jboss.org
> *Objet :* Re: [keycloak-user] How to dynamically trigger a custom
> required action in a flow ?
>
>
>
> Hi,
>
>
>
> When you says it does not accept it, you have an exception at runtime ?
> Because you have addRequiredAction(String string)
>
>
>
> On Mon, Apr 29, 2019 at 12:13 PM GESLIN Fabrice <
> fabrice.geslin-prestataire at laposte.fr> wrote:
>
> Hi,
>
> We're trying to trigger a custom required action  as part of the reset
> credential.
>
> For this we plan to mimic the implementation of the authenticate method of
> the org.keycloak.authentication.authenticators.resetcred.ResetPassword.java
> :
>
>     @Override
>     public void authenticate(AuthenticationFlowContext context) {
>         if (context.getExecution().isRequired() ||
>                 (context.getExecution().isOptional() &&
>                         configuredFor(context))) {
>
> context.getAuthenticationSession().addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
>         }
>         context.success();
>     }
>
>
> But the question is what value should we pass to the addRequiredAction() ?
>
> This method seems to only accept the predefined required actions mapped to
> the values from the  UserModel.RequiredAction enum.
>
> Any help is welcome .
>
> Fabrice Geslin
>
> Groupe La Poste
>
> Post-scriptum La Poste
>
> Ce message est confidentiel. Sous reserve de tout accord conclu par
> ecrit entre vous et La Poste, son contenu ne represente en aucun cas un
> engagement de la part de La Poste. Toute publication, utilisation ou
> diffusion, meme partielle, doit etre autorisee prealablement. Si vous
> n'etes pas destinataire de ce message, merci d'en avertir immediatement
> l'expediteur.
> _______________________________________________
> keycloak-user mailing list
> keycloak-user at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/keycloak-user
>
>
> Post-scriptum La Poste
>
> Ce message est confidentiel. Sous reserve de tout accord conclu par
> ecrit entre vous et La Poste, son contenu ne represente en aucun cas un
> engagement de la part de La Poste. Toute publication, utilisation ou
> diffusion, meme partielle, doit etre autorisee prealablement. Si vous
> n'etes pas destinataire de ce message, merci d'en avertir immediatement
> l'expediteur.
>


More information about the keycloak-user mailing list