Search in sources :

Example 1 with SubflowState

use of org.springframework.webflow.engine.SubflowState in project cas by apereo.

the class AbstractCasWebflowConfigurer method registerMultifactorProviderAuthenticationWebflow.

/**
     * Register multifactor provider authentication webflow.
     *
     * @param flow      the flow
     * @param subflowId the subflow id
     * @param registry  the registry
     */
protected void registerMultifactorProviderAuthenticationWebflow(final Flow flow, final String subflowId, final FlowDefinitionRegistry registry) {
    final SubflowState subflowState = createSubflowState(flow, subflowId, subflowId);
    final ActionState actionState = (ActionState) flow.getState(CasWebflowConstants.TRANSITION_ID_REAL_SUBMIT);
    final String targetStateId = actionState.getTransition(CasWebflowConstants.TRANSITION_ID_SUCCESS).getTargetStateId();
    final List<DefaultMapping> mappings = new ArrayList<>();
    final Mapper inputMapper = createMapperToSubflowState(mappings);
    final SubflowAttributeMapper subflowMapper = createSubflowAttributeMapper(inputMapper, null);
    subflowState.setAttributeMapper(subflowMapper);
    subflowState.getTransitionSet().add(createTransition(CasWebflowConstants.TRANSITION_ID_SUCCESS, targetStateId));
    LOGGER.debug("Retrieved action state [{}]", actionState.getId());
    createTransitionForState(actionState, subflowId, subflowId);
    registerFlowDefinitionIntoLoginFlowRegistry(registry);
    final TransitionableState state = flow.getTransitionableState(CasWebflowConstants.TRANSITION_ID_INITIAL_AUTHN_REQUEST_VALIDATION_CHECK);
    createTransitionForState(state, subflowId, subflowId);
}
Also used : DefaultMapper(org.springframework.binding.mapping.impl.DefaultMapper) SubflowAttributeMapper(org.springframework.webflow.engine.SubflowAttributeMapper) GenericSubflowAttributeMapper(org.springframework.webflow.engine.support.GenericSubflowAttributeMapper) Mapper(org.springframework.binding.mapping.Mapper) SubflowAttributeMapper(org.springframework.webflow.engine.SubflowAttributeMapper) GenericSubflowAttributeMapper(org.springframework.webflow.engine.support.GenericSubflowAttributeMapper) ArrayList(java.util.ArrayList) SubflowState(org.springframework.webflow.engine.SubflowState) DefaultMapping(org.springframework.binding.mapping.impl.DefaultMapping) TransitionableState(org.springframework.webflow.engine.TransitionableState) ActionState(org.springframework.webflow.engine.ActionState)

Example 2 with SubflowState

use of org.springframework.webflow.engine.SubflowState in project cas by apereo.

the class AbstractCasMultifactorWebflowConfigurer method registerMultifactorProviderAuthenticationWebflow.

/**
 * Register multifactor provider authentication webflow.
 *
 * @param flow                    the flow
 * @param subflowId               the subflow id
 * @param mfaProviderFlowRegistry the registry
 */
protected void registerMultifactorProviderAuthenticationWebflow(final Flow flow, final String subflowId, final FlowDefinitionRegistry mfaProviderFlowRegistry) {
    final SubflowState subflowState = createSubflowState(flow, subflowId, subflowId);
    final Collection<String> states = getCandidateStatesForMultifactorAuthentication();
    LOGGER.debug("Candidate states for multifactor authentication are [{}]", states);
    states.forEach(s -> {
        LOGGER.debug("Locating state [{}] to process for multifactor authentication", s);
        final TransitionableState actionState = getState(flow, s);
        LOGGER.debug("Locating transition id [{}] to process multifactor authentication for state [{}", CasWebflowConstants.TRANSITION_ID_SUCCESS, s);
        final String targetSuccessId = actionState.getTransition(CasWebflowConstants.TRANSITION_ID_SUCCESS).getTargetStateId();
        LOGGER.debug("Locating transition id [{}] to process multifactor authentication for state [{}", CasWebflowConstants.TRANSITION_ID_SUCCESS_WITH_WARNINGS, s);
        final String targetWarningsId = actionState.getTransition(CasWebflowConstants.TRANSITION_ID_SUCCESS_WITH_WARNINGS).getTargetStateId();
        final List<DefaultMapping> mappings = new ArrayList<>();
        final Mapper inputMapper = createMapperToSubflowState(mappings);
        final SubflowAttributeMapper subflowMapper = createSubflowAttributeMapper(inputMapper, null);
        subflowState.setAttributeMapper(subflowMapper);
        LOGGER.debug("Creating transitions to subflow state [{}]", subflowState.getId());
        final TransitionSet transitionSet = subflowState.getTransitionSet();
        transitionSet.add(createTransition(CasWebflowConstants.TRANSITION_ID_SUCCESS, targetSuccessId));
        transitionSet.add(createTransition(CasWebflowConstants.TRANSITION_ID_SUCCESS_WITH_WARNINGS, targetWarningsId));
        LOGGER.debug("Creating transition [{}] fpr state [{}]", subflowId, actionState.getId());
        createTransitionForState(actionState, subflowId, subflowId);
        registerMultifactorFlowDefinitionIntoLoginFlowRegistry(mfaProviderFlowRegistry);
        augmentMultifactorProviderFlowRegistry(mfaProviderFlowRegistry);
        final TransitionableState state = getTransitionableState(flow, CasWebflowConstants.STATE_ID_INITIAL_AUTHN_REQUEST_VALIDATION_CHECK);
        createTransitionForState(state, subflowId, subflowId);
    });
}
Also used : Mapper(org.springframework.binding.mapping.Mapper) SubflowAttributeMapper(org.springframework.webflow.engine.SubflowAttributeMapper) SubflowAttributeMapper(org.springframework.webflow.engine.SubflowAttributeMapper) TransitionSet(org.springframework.webflow.engine.TransitionSet) ArrayList(java.util.ArrayList) SubflowState(org.springframework.webflow.engine.SubflowState) DefaultMapping(org.springframework.binding.mapping.impl.DefaultMapping) TransitionableState(org.springframework.webflow.engine.TransitionableState)

Example 3 with SubflowState

use of org.springframework.webflow.engine.SubflowState in project cas by apereo.

the class BaseMultifactorWebflowConfigurerTests method verifyOperation.

@Test
public void verifyOperation() {
    val registry = getMultifactorFlowDefinitionRegistry();
    assertTrue(registry.containsFlowDefinition(getMultifactorEventId()));
    val flow = (Flow) registry.getFlowDefinition(getMultifactorEventId());
    assertTrue(flow.containsState(CasWebflowConstants.STATE_ID_MFA_CHECK_BYPASS));
    assertTrue(flow.containsState(CasWebflowConstants.STATE_ID_MFA_CHECK_AVAILABLE));
    assertTrue(flow.containsState(CasWebflowConstants.STATE_ID_MFA_FAILURE));
    val loginFlow = (Flow) loginFlowDefinitionRegistry.getFlowDefinition(CasWebflowConfigurer.FLOW_ID_LOGIN);
    assertTrue(loginFlow.getState(getMultifactorEventId()) instanceof SubflowState);
}
Also used : lombok.val(lombok.val) SubflowState(org.springframework.webflow.engine.SubflowState) Flow(org.springframework.webflow.engine.Flow) Test(org.junit.jupiter.api.Test)

Example 4 with SubflowState

use of org.springframework.webflow.engine.SubflowState in project cas by apereo.

the class AccountManagementWebflowConfigurerTests method verifyOperation.

@Test
public void verifyOperation() {
    assertFalse(casWebflowExecutionPlan.getWebflowConfigurers().isEmpty());
    val flow = (Flow) this.loginFlowDefinitionRegistry.getFlowDefinition(CasWebflowConfigurer.FLOW_ID_LOGIN);
    assertNotNull(flow);
    assertTrue(flow.containsState(CasWebflowConstants.STATE_ID_VIEW_ACCOUNT_SIGNUP));
    assertTrue(flow.containsState(CasWebflowConstants.STATE_ID_SUBMIT_ACCOUNT_REGISTRATION));
    assertTrue(flow.containsState(CasWebflowConstants.STATE_ID_SENT_ACCOUNT_SIGNUP_INFO));
    assertTrue(flow.containsState(CasWebflowConstants.STATE_ID_ACCOUNT_REGISTRATION_SUBFLOW));
    val subflow = (SubflowState) flow.getState(CasWebflowConstants.STATE_ID_ACCOUNT_REGISTRATION_SUBFLOW);
    assertNotNull(subflow);
    val regFlow = (Flow) loginFlowDefinitionRegistry.getFlowDefinition(AccountManagementWebflowConfigurer.FLOW_ID_ACCOUNT_REGISTRATION);
    val context = new MockRequestControlContext(regFlow);
    val request = new MockHttpServletRequest();
    val response = new MockHttpServletResponse();
    context.setExternalContext(new ServletExternalContext(new MockServletContext(), request, response));
    RequestContextHolder.setRequestContext(context);
    ExternalContextHolder.setExternalContext(context.getExternalContext());
    val completeState = (ViewState) regFlow.getState(CasWebflowConstants.STATE_ID_COMPLETE_ACCOUNT_REGISTRATION);
    completeState.enter(context);
    assertNotNull(WebUtils.getPasswordPolicyPattern(context));
    assertEquals(2, AccountRegistrationUtils.getAccountRegistrationSecurityQuestionsCount(context));
}
Also used : lombok.val(lombok.val) MockHttpServletRequest(org.springframework.mock.web.MockHttpServletRequest) ServletExternalContext(org.springframework.webflow.context.servlet.ServletExternalContext) SubflowState(org.springframework.webflow.engine.SubflowState) ViewState(org.springframework.webflow.engine.ViewState) MockRequestControlContext(org.springframework.webflow.test.MockRequestControlContext) MockHttpServletResponse(org.springframework.mock.web.MockHttpServletResponse) MockServletContext(org.springframework.mock.web.MockServletContext) Flow(org.springframework.webflow.engine.Flow) Test(org.junit.jupiter.api.Test)

Example 5 with SubflowState

use of org.springframework.webflow.engine.SubflowState in project cas by apereo.

the class AbstractCasMultifactorWebflowConfigurer method registerMultifactorProviderAuthenticationWebflow.

@Override
public void registerMultifactorProviderAuthenticationWebflow(final Flow flow, final String subflowId, final String providerId) {
    multifactorAuthenticationFlowDefinitionRegistries.forEach(registry -> {
        if (!registry.containsFlowDefinition(subflowId)) {
            LOGGER.error("Could not locate flow id [{}]", subflowId);
            return;
        }
        if (flow == null) {
            LOGGER.error("Unable to locate parent flow definition to register provider [{}]", providerId);
            return;
        }
        val mfaFlow = (Flow) registry.getFlowDefinition(subflowId);
        mfaFlow.getStartActionList().add(requestContext -> {
            WebUtils.createCredential(requestContext);
            return null;
        });
        mfaFlow.getStartActionList().add(createSetAction("flowScope.".concat(CasWebflowConstants.VAR_ID_MFA_PROVIDER_ID), StringUtils.quote(providerId)));
        val initStartState = (TransitionableState) mfaFlow.getStartState();
        val transition = (Transition) initStartState.getTransition(CasWebflowConstants.TRANSITION_ID_SUCCESS);
        val targetStateId = transition.getTargetStateId();
        transition.setTargetStateResolver(new DefaultTargetStateResolver(CasWebflowConstants.STATE_ID_MFA_CHECK_BYPASS));
        registerMultifactorProviderBypassAction(mfaFlow);
        registerMultifactorProviderAvailableAction(mfaFlow, targetStateId);
        registerMultifactorProviderFailureAction(flow, mfaFlow);
        val subflowState = createSubflowState(flow, subflowId, subflowId);
        val subflowMappings = Stream.of(CasWebflowConstants.ATTRIBUTE_SERVICE, CasWebflowConstants.ATTRIBUTE_REGISTERED_SERVICE).map(attr -> new DefaultMapping(createExpression("flowScope." + attr), createExpression(attr))).collect(Collectors.toList());
        subflowMappings.add(new DefaultMapping(createExpression("flowScope." + CasWebflowConstants.VAR_ID_CREDENTIAL), createExpression("parent" + StringUtils.capitalize(CasWebflowConstants.VAR_ID_CREDENTIAL))));
        multifactorAuthenticationFlowCustomizers.forEach(c -> c.getMultifactorWebflowAttributeMappings().forEach(key -> subflowMappings.add(new DefaultMapping(createExpression("flowScope." + key), createExpression(key)))));
        val inputMapper = createMapperToSubflowState(subflowMappings);
        val subflowMapper = createSubflowAttributeMapper(inputMapper, null);
        subflowState.setAttributeMapper(subflowMapper);
        val flowMappings = Stream.of(CasWebflowConstants.ATTRIBUTE_SERVICE, CasWebflowConstants.ATTRIBUTE_REGISTERED_SERVICE).map(attr -> new DefaultMapping(createExpression(attr), createExpression("flowScope." + attr))).collect(Collectors.toList());
        flowMappings.add(new DefaultMapping(createExpression("parent" + StringUtils.capitalize(CasWebflowConstants.VAR_ID_CREDENTIAL)), createExpression("flowScope.parent" + StringUtils.capitalize(CasWebflowConstants.VAR_ID_CREDENTIAL))));
        multifactorAuthenticationFlowCustomizers.forEach(c -> c.getMultifactorWebflowAttributeMappings().forEach(key -> flowMappings.add(new DefaultMapping(createExpression(key), createExpression("flowScope." + key)))));
        val flowInputMapper = createMapperToSubflowState(flowMappings);
        mfaFlow.setInputMapper(flowInputMapper);
        val states = getCandidateStatesForMultifactorAuthentication();
        registerMultifactorAuthenticationSubflowWithStates(flow, subflowState, states);
        registerMultifactorFlowDefinitionIntoLoginFlowRegistry();
        augmentMultifactorProviderFlowRegistry();
        LOGGER.trace("Registering the [{}] flow into the flow [{}]", subflowId, flow.getId());
        val startState = flow.getTransitionableState(flow.getStartState().getId());
        createTransitionForState(startState, subflowId, subflowId, true);
        val initState = getState(flow, CasWebflowConstants.STATE_ID_INITIAL_AUTHN_REQUEST_VALIDATION_CHECK);
        createTransitionForState(initState, subflowId, subflowId, true);
    });
}
Also used : lombok.val(lombok.val) CasConfigurationProperties(org.apereo.cas.configuration.CasConfigurationProperties) SubflowState(org.springframework.webflow.engine.SubflowState) Ordered(org.springframework.core.Ordered) Arrays(java.util.Arrays) Getter(lombok.Getter) DefaultMapping(org.springframework.binding.mapping.impl.DefaultMapping) FlowBuilderServices(org.springframework.webflow.engine.builder.support.FlowBuilderServices) TransitionableState(org.springframework.webflow.engine.TransitionableState) ArrayList(java.util.ArrayList) CasWebflowConstants(org.apereo.cas.web.flow.CasWebflowConstants) ConfigurableApplicationContext(org.springframework.context.ConfigurableApplicationContext) LinkedHashSet(java.util.LinkedHashSet) FlowDefinitionRegistry(org.springframework.webflow.definition.registry.FlowDefinitionRegistry) Collection(java.util.Collection) lombok.val(lombok.val) Flow(org.springframework.webflow.engine.Flow) Transition(org.springframework.webflow.engine.Transition) Collectors(java.util.stream.Collectors) Slf4j(lombok.extern.slf4j.Slf4j) List(java.util.List) Stream(java.util.stream.Stream) Optional(java.util.Optional) WebUtils(org.apereo.cas.web.support.WebUtils) DefaultTargetStateResolver(org.springframework.webflow.engine.support.DefaultTargetStateResolver) StringUtils(org.springframework.util.StringUtils) Transition(org.springframework.webflow.engine.Transition) DefaultTargetStateResolver(org.springframework.webflow.engine.support.DefaultTargetStateResolver) DefaultMapping(org.springframework.binding.mapping.impl.DefaultMapping) TransitionableState(org.springframework.webflow.engine.TransitionableState) Flow(org.springframework.webflow.engine.Flow)

Aggregations

SubflowState (org.springframework.webflow.engine.SubflowState)5 ArrayList (java.util.ArrayList)3 lombok.val (lombok.val)3 DefaultMapping (org.springframework.binding.mapping.impl.DefaultMapping)3 Flow (org.springframework.webflow.engine.Flow)3 TransitionableState (org.springframework.webflow.engine.TransitionableState)3 Test (org.junit.jupiter.api.Test)2 Mapper (org.springframework.binding.mapping.Mapper)2 SubflowAttributeMapper (org.springframework.webflow.engine.SubflowAttributeMapper)2 Arrays (java.util.Arrays)1 Collection (java.util.Collection)1 LinkedHashSet (java.util.LinkedHashSet)1 List (java.util.List)1 Optional (java.util.Optional)1 Collectors (java.util.stream.Collectors)1 Stream (java.util.stream.Stream)1 Getter (lombok.Getter)1 Slf4j (lombok.extern.slf4j.Slf4j)1 CasConfigurationProperties (org.apereo.cas.configuration.CasConfigurationProperties)1 CasWebflowConstants (org.apereo.cas.web.flow.CasWebflowConstants)1