CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-apereo-cas--cas-server-core-webflow-mfa-api

Core API for multifactor authentication webflow configuration in Apereo CAS providing interfaces and base classes for MFA provider integration

Pending
Overview
Eval results
Files

webflow-actions.mddocs/

Webflow Actions

Action classes that execute during webflow state transitions to perform MFA-specific operations like availability checks, bypassing, device management, and failure handling. Actions bridge the gap between webflow states and MFA provider implementations.

Capabilities

AbstractMultifactorAuthenticationAction

Base generic action class providing common functionality for MFA actions including provider resolution and principal resolution.

/**
 * Abstract base class for MFA actions providing provider resolution and principal resolution hooks
 * @param <T> Type of MultifactorAuthenticationProvider this action works with
 */
public abstract class AbstractMultifactorAuthenticationAction<T extends MultifactorAuthenticationProvider> 
    extends BaseCasWebflowAction {
    
    /**
     * The resolved provider for this flow (available to subclasses)
     */
    protected T provider;
    
    /**
     * Pre-execution hook that resolves the MFA provider for this flow
     * @param requestContext The webflow request context
     * @return Event result of pre-execution (typically null to continue)
     * @throws Exception If provider resolution fails
     */
    @Override
    protected Event doPreExecute(RequestContext requestContext) throws Exception;
    
    /**
     * Resolve principal using available MultifactorAuthenticationPrincipalResolver instances
     * @param principal The principal to resolve
     * @param requestContext The webflow request context
     * @return Resolved principal
     */
    protected Principal resolvePrincipal(Principal principal, RequestContext requestContext);
    
    /**
     * Get throttled request key for authentication throttling
     * @param authentication Current authentication
     * @param requestContext The webflow request context
     * @return Throttling key (typically principal ID)
     */
    protected String getThrottledRequestKeyFor(Authentication authentication, RequestContext requestContext);
}

Usage Example:

public class MyMfaVerificationAction extends AbstractMultifactorAuthenticationAction<MyMfaProvider> {
    
    @Override
    protected Event doExecuteInternal(RequestContext requestContext) throws Exception {
        // Provider is automatically resolved and available as this.provider
        val authentication = WebUtils.getAuthentication(requestContext);
        val principal = resolvePrincipal(authentication.getPrincipal(), requestContext);
        
        // Get MFA token from request
        val token = requestContext.getRequestParameters().get("token");
        
        // Verify token using the resolved provider
        if (provider.verify(principal, token)) {
            return success();
        } else {
            return error();
        }
    }
}

MultifactorAuthenticationAvailableAction

Determines if an MFA provider is available to provide authentication.

/**
 * Action that determines if MFA provider is available for authentication
 */
public class MultifactorAuthenticationAvailableAction 
    extends AbstractMultifactorAuthenticationAction<MultifactorAuthenticationProvider> {
    
    /**
     * Default constructor - uses inherited constructor from AbstractMultifactorAuthenticationAction
     */
    public MultifactorAuthenticationAvailableAction();
    
    /**
     * Execute availability check for the MFA provider
     * @param requestContext The webflow request context
     * @return Event indicating availability (yes/no)
     * @throws Exception If availability check fails
     */
    @Override
    protected Event doExecuteInternal(RequestContext requestContext) throws Exception;
}

MultifactorAuthenticationBypassAction

Determines if MFA provider can be bypassed for the current user and service.

/**
 * Action that determines if MFA provider can be bypassed
 */
public class MultifactorAuthenticationBypassAction 
    extends AbstractMultifactorAuthenticationAction<MultifactorAuthenticationProvider> {
    
    /**
     * Default constructor - uses inherited constructor from AbstractMultifactorAuthenticationAction
     */
    public MultifactorAuthenticationBypassAction();
    
    /**
     * Execute bypass check for the MFA provider
     * @param requestContext The webflow request context
     * @return Event indicating bypass decision (yes/no)
     * @throws Exception If bypass check fails
     */
    @Override
    protected Event doExecuteInternal(RequestContext requestContext) throws Exception;
    
    /**
     * Check if multifactor authentication should be bypassed
     * @param requestContext The webflow request context
     * @param registeredService The service being accessed
     * @param provider The MFA provider
     * @return true if MFA should be bypassed
     */
    protected boolean isMultifactorAuthenticationBypass(
        RequestContext requestContext,
        RegisteredService registeredService,
        MultifactorAuthenticationProvider provider);
}

MultifactorAuthenticationFailureAction

Handles MFA provider failure scenarios and determines appropriate failure mode.

/**
 * Action that handles MFA provider failure scenarios
 */
public class MultifactorAuthenticationFailureAction 
    extends AbstractMultifactorAuthenticationAction<MultifactorAuthenticationProvider> {
    
    /**
     * Default constructor - uses inherited constructor from AbstractMultifactorAuthenticationAction
     */
    public MultifactorAuthenticationFailureAction();
    
    /**
     * Execute failure handling for the MFA provider
     * @param requestContext The webflow request context
     * @return Event indicating failure mode (unavailable/bypass)
     * @throws Exception If failure handling fails
     */
    @Override
    protected Event doExecuteInternal(RequestContext requestContext) throws Exception;
}

MultifactorAuthenticationDeviceProviderAction

Functional interface for actions that provide MFA device information.

/**
 * Functional interface for actions that provide MFA device information
 */
@FunctionalInterface
public interface MultifactorAuthenticationDeviceProviderAction extends Action, Ordered, NamedObject {
    
    /**
     * Get execution order for this action
     * @return Order value (default LOWEST_PRECEDENCE)
     */
    @Override
    default int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}

MultifactorAuthenticationTrustedDeviceProviderAction

Functional interface for actions that handle trusted device information in MFA flows.

/**
 * Functional interface for actions that handle trusted device information in MFA flows
 */
@FunctionalInterface  
public interface MultifactorAuthenticationTrustedDeviceProviderAction extends Action, Ordered, NamedObject {
    
    /**
     * Get execution order for this action
     * @return Order value (default LOWEST_PRECEDENCE)
     */
    @Override
    default int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}

DefaultMultifactorAuthenticationDeviceProviderAction

Default implementation for loading registered MFA devices for a user.

/**
 * Default implementation for loading registered MFA devices for a user
 */
public class DefaultMultifactorAuthenticationDeviceProviderAction 
    implements MultifactorAuthenticationDeviceProviderAction {
    
    /**
     * Constructor
     * @param deviceManager MFA device manager for loading devices
     */
    public DefaultMultifactorAuthenticationDeviceProviderAction(
        MultifactorAuthenticationDeviceManager deviceManager);
    
    /**
     * Execute device loading action
     * @param context The action execution context
     * @return Event result of device loading
     * @throws Exception If device loading fails
     */
    @Override
    public Event execute(RequestContext context) throws Exception;
    
    /**
     * Internal execution logic for device loading
     * @param requestContext The webflow request context
     * @return Event result
     * @throws Exception If execution fails
     */
    protected Event doExecuteInternal(RequestContext requestContext) throws Exception;
}

Complete Action Implementation Example:

@Component
public class CustomMfaActions {
    
    @Bean
    public Action customMfaAvailabilityAction(ApplicationEventPublisher eventPublisher) {
        return new CustomMfaAvailabilityAction(eventPublisher);
    }
    
    @Bean
    public MultifactorAuthenticationDeviceProviderAction customDeviceAction(
        MultifactorAuthenticationDeviceManager deviceManager) {
        return new CustomDeviceProviderAction(deviceManager);
    }
    
    private static class CustomMfaAvailabilityAction extends MultifactorAuthenticationAvailableAction {
        
        public CustomMfaAvailabilityAction(ApplicationEventPublisher eventPublisher) {
            super(eventPublisher);
        }
        
        @Override
        protected Event doExecuteInternal(RequestContext requestContext) throws Exception {
            // this.provider is automatically resolved
            val principal = WebUtils.getAuthentication(requestContext).getPrincipal();
            
            // Custom availability logic
            if (isProviderAvailableForUser(principal)) {
                return new EventFactorySupport().event(this, CasWebflowConstants.TRANSITION_ID_YES);
            }
            return new EventFactorySupport().event(this, CasWebflowConstants.TRANSITION_ID_NO);
        }
        
        private boolean isProviderAvailableForUser(Principal principal) {
            // Custom logic to check if provider is available for this user
            return true;
        }
    }
    
    private static class CustomDeviceProviderAction implements MultifactorAuthenticationDeviceProviderAction {
        
        private final MultifactorAuthenticationDeviceManager deviceManager;
        
        public CustomDeviceProviderAction(MultifactorAuthenticationDeviceManager deviceManager) {
            this.deviceManager = deviceManager;
        }
        
        @Override
        public Event execute(RequestContext context) throws Exception {
            val authentication = WebUtils.getAuthentication(context);
            val devices = deviceManager.findRegisteredDevices(authentication.getPrincipal());
            
            MultifactorAuthenticationWebflowUtils.putMultifactorAuthenticationRegisteredDevices(context, devices);
            return new EventFactorySupport().event(this, CasWebflowConstants.TRANSITION_ID_SUCCESS);
        }
        
        @Override
        public String getName() {
            return "customDeviceProviderAction";
        }
    }
}

Action Integration

Actions are typically integrated into webflows through configuration:

@Configuration
public class MyMfaWebflowActionsConfiguration {
    
    @Bean
    public Action myMfaCheckAvailableAction(ApplicationEventPublisher eventPublisher) {
        return new MultifactorAuthenticationAvailableAction(eventPublisher);
    }
    
    @Bean
    public Action myMfaCheckBypassAction(ApplicationEventPublisher eventPublisher) {
        return new MultifactorAuthenticationBypassAction(eventPublisher);
    }
    
    @Bean
    public Action myMfaFailureAction(ApplicationEventPublisher eventPublisher) {
        return new MultifactorAuthenticationFailureAction(eventPublisher);
    }
}

These actions are then referenced in webflow definitions by their bean names and executed during state transitions.

Install with Tessl CLI

npx tessl i tessl/maven-org-apereo-cas--cas-server-core-webflow-mfa-api

docs

authentication-components.md

event-resolution.md

index.md

provider-selection.md

webflow-actions.md

webflow-configuration.md

webflow-utilities.md

tile.json