Keycloak Custom Required Action being deployed but not working

1.2k Views Asked by At

I am currently working on integrating a custom Required Action into Keycloak for role assignment purposes. The intent is that a user can choose their role during registration, and that this chosen role will be saved as a user attribute and should then be connected with the realm role of the same name as the user has chosen in registration form.

In my register.ftl i have:

           <div class="${properties.kcFormGroupClass!}">
                <div class="${properties.kcLabelWrapperClass!}">
                    <label for="user.attributes.role" class="${properties.kcLabelClass!}">${msg("role")}</label>
                </div>
                <div class="${properties.kcInputWrapperClass!}">
                    <select id="user.attributes.role" class="${properties.kcInputClass!}" name="user.attributes.role"
                            aria-invalid="<#if messagesPerField.existsError('user.attributes.role')>true</#if>"
                    >
                        <option value="">${msg("selectRole")}</option>
                        <option value="Buyer">Buyer</option>
                        <option value="Carrier">Carrier</option>
                        <option value="Shipper">Shipper</option>
                    </select>

                    <#if messagesPerField.existsError('user.attributes.role')>
                        <span id="input-error-role" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
                ${kcSanitize(messagesPerField.get('user.attributes.role'))?no_esc}
            </span>
                    </#if>
                </div>
            </div>

And in realm roles i have added "Carrier", "Shipper", and "Buyer" as roles.

Here is the Java code that I have used to create a custom RequiredActionProvider:

package com.company.keycloak;

import org.keycloak.authentication.RequiredActionContext;
import org.keycloak.authentication.RequiredActionFactory;
import org.keycloak.authentication.RequiredActionProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RoleModel;
import org.jboss.logging.Logger;

import java.util.List;

public class RoleAssignmentAction implements RequiredActionProvider, RequiredActionFactory {


private static final Logger logger = Logger.getLogger(RoleAssignmentAction.class);
@Override
public void evaluateTriggers(RequiredActionContext context) {
}

@Override
public void requiredActionChallenge(RequiredActionContext context) {
}

@Override
public void processAction(RequiredActionContext context) {
    List<String> selectedRoleList = context.getUser().getAttributes().get("role");

    if (selectedRoleList == null || selectedRoleList.isEmpty()) {
        logger.warn("No role selected by the user");
        return;
    }

    String selectedRole = selectedRoleList.get(0);
    logger.infof("Selected role: %s", selectedRole);

    RoleModel role = context.getRealm().getRole(selectedRole);

    if (role != null) {
        context.getUser().grantRole(role);
        logger.infof("Role [%s] granted to user [%s]", role.getName(), context.getUser().getUsername());
    } else {
        logger.warnf("Role [%s] not found", selectedRole);
    }

    context.success();
}

//rest of the needed methods
}

I have followed the standard steps for deploying the custom provider:

  1. Packaged this class in a JAR file.
  2. Included a METAINF/services/org.keycloak.authentication.RequiredActionProvider file.
  3. Deployed it by copying the JAR file to the standalone/deployments/ directory.

The required action shows up in "Required actions" tab in keycloak admin conole and i set it to enabled and default actions to on. However, when the RequiredActionProvider should be executed, none of the logs from the custom provider are being printed to the console nor are the roles being assigned.

Here are the things I have verified:

The JAR file is successfully deployed according to Keycloak logs. The provider ID is correctly configured in the Keycloak admin console. The Docker logs don't seem to show any errors and everything seems to be running fine. I'm currently using Keycloak version 16.1.1.

Any insights or advice on how to troubleshoot this issue or fix it would be greatly appreciated. And if any information should be added to this question, please let me know. Thank you!

1

There are 1 best solutions below

0
On BEST ANSWER

You are mixing up two phases/flows.

If you want it to happen in the registration flow, you'll have to implement the FormAction and FormActionFactory interfaces and add your custom authenticator step (the action) to the used Registration Flow.

If you want it to happen in the RequiredAction, you'll have to implement the action properly. The requiredActionChallenge() method sends the form/page (challenge) to the users browser, the processAction() method processes the submitted form request. For an example of a required action implementation, see here: https://github.com/dasniko/keycloak-extensions-demo/tree/main/requiredaction

Required Actions will always be executed, if assigned manually or programmatically, at the end of an authentication flow. Thus, also after the registration flow, which is actually an authentication flow. If you register your Required Action as an default action, all new users have to fulfill the action.