Search in sources :

Example 31 with AuthenticationExecutionModel

use of org.keycloak.models.AuthenticationExecutionModel in project keycloak by keycloak.

the class AuthenticationManagementResource method updateExecutions.

/**
 * Update authentication executions of a Flow
 * @param flowAlias Flow alias
 * @param rep AuthenticationExecutionInfoRepresentation
 */
@Path("/flows/{flowAlias}/executions")
@PUT
@NoCache
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response updateExecutions(@PathParam("flowAlias") String flowAlias, AuthenticationExecutionInfoRepresentation rep) {
    auth.realm().requireManageRealm();
    AuthenticationFlowModel flow = realm.getFlowByAlias(flowAlias);
    if (flow == null) {
        logger.debug("flow not found: " + flowAlias);
        throw new NotFoundException("flow not found");
    }
    AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(rep.getId());
    if (model == null) {
        session.getTransactionManager().setRollbackOnly();
        throw new NotFoundException("Illegal execution");
    }
    if (!model.getRequirement().name().equals(rep.getRequirement())) {
        model.setRequirement(AuthenticationExecutionModel.Requirement.valueOf(rep.getRequirement()));
        realm.updateAuthenticatorExecution(model);
        adminEvent.operation(OperationType.UPDATE).resource(ResourceType.AUTH_EXECUTION).resourcePath(session.getContext().getUri()).representation(rep).success();
        return Response.accepted(flow).build();
    }
    // executions can't have name and description updated
    if (rep.getAuthenticationFlow() == null) {
        return Response.accepted(flow).build();
    }
    // check if updating a correct flow
    AuthenticationFlowModel checkFlow = realm.getAuthenticationFlowById(rep.getFlowId());
    if (checkFlow == null) {
        session.getTransactionManager().setRollbackOnly();
        throw new NotFoundException("Illegal execution");
    }
    // if a different flow with the same name does already exist, throw an exception
    if (realm.getFlowByAlias(rep.getDisplayName()) != null && !checkFlow.getAlias().equals(rep.getDisplayName())) {
        return ErrorResponse.exists("Flow alias name already exists");
    }
    // if the name changed
    if (!checkFlow.getAlias().equals(rep.getDisplayName())) {
        checkFlow.setAlias(rep.getDisplayName());
    }
    // check if the description changed
    if (!checkFlow.getDescription().equals(rep.getDescription())) {
        checkFlow.setDescription(rep.getDescription());
    }
    // update the flow
    realm.updateAuthenticationFlow(checkFlow);
    adminEvent.operation(OperationType.UPDATE).resource(ResourceType.AUTH_EXECUTION).resourcePath(session.getContext().getUri()).representation(rep).success();
    return Response.accepted(flow).build();
}
Also used : AuthenticationExecutionModel(org.keycloak.models.AuthenticationExecutionModel) AuthenticationFlowModel(org.keycloak.models.AuthenticationFlowModel) NotFoundException(javax.ws.rs.NotFoundException) Path(javax.ws.rs.Path) Produces(javax.ws.rs.Produces) Consumes(javax.ws.rs.Consumes) NoCache(org.jboss.resteasy.annotations.cache.NoCache) PUT(javax.ws.rs.PUT)

Example 32 with AuthenticationExecutionModel

use of org.keycloak.models.AuthenticationExecutionModel in project keycloak by keycloak.

the class AuthenticationManagementResource method deleteFlow.

private void deleteFlow(String id, boolean isTopMostLevel) {
    AuthenticationFlowModel flow = realm.getAuthenticationFlowById(id);
    if (flow == null) {
        throw new NotFoundException("Could not find flow with id");
    }
    if (flow.isBuiltIn()) {
        throw new BadRequestException("Can't delete built in flow");
    }
    realm.getAuthenticationExecutionsStream(id).map(AuthenticationExecutionModel::getFlowId).filter(Objects::nonNull).forEachOrdered(flowId -> deleteFlow(flowId, false));
    realm.removeAuthenticationFlow(flow);
    // Use just one event for top-level flow. Using separate events won't work properly for flows of depth 2 or bigger
    if (isTopMostLevel)
        adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri()).success();
}
Also used : AuthenticationExecutionModel(org.keycloak.models.AuthenticationExecutionModel) AuthenticationFlowModel(org.keycloak.models.AuthenticationFlowModel) NotFoundException(javax.ws.rs.NotFoundException) BadRequestException(javax.ws.rs.BadRequestException)

Example 33 with AuthenticationExecutionModel

use of org.keycloak.models.AuthenticationExecutionModel in project keycloak by keycloak.

the class AuthenticationManagementResource method addExecutionToFlow.

/**
 * Add new authentication execution to a flow
 *
 * @param flowAlias Alias of parent flow
 * @param data New execution JSON data containing 'provider' attribute
 */
@Path("/flows/{flowAlias}/executions/execution")
@POST
@NoCache
@Consumes(MediaType.APPLICATION_JSON)
public Response addExecutionToFlow(@PathParam("flowAlias") String flowAlias, Map<String, String> data) {
    auth.realm().requireManageRealm();
    AuthenticationFlowModel parentFlow = realm.getFlowByAlias(flowAlias);
    if (parentFlow == null) {
        throw new BadRequestException("Parent flow doesn't exist");
    }
    if (parentFlow.isBuiltIn()) {
        throw new BadRequestException("It is illegal to add execution to a built in flow");
    }
    String provider = data.get("provider");
    // make sure provider is one of the registered providers
    ProviderFactory f;
    if (parentFlow.getProviderId().equals(AuthenticationFlow.CLIENT_FLOW)) {
        f = session.getKeycloakSessionFactory().getProviderFactory(ClientAuthenticator.class, provider);
    } else if (parentFlow.getProviderId().equals(AuthenticationFlow.FORM_FLOW)) {
        f = session.getKeycloakSessionFactory().getProviderFactory(FormAction.class, provider);
    } else {
        f = session.getKeycloakSessionFactory().getProviderFactory(Authenticator.class, provider);
    }
    if (f == null) {
        throw new BadRequestException("No authentication provider found for id: " + provider);
    }
    AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
    execution.setParentFlow(parentFlow.getId());
    ConfigurableAuthenticatorFactory conf = (ConfigurableAuthenticatorFactory) f;
    if (conf.getRequirementChoices().length == 1)
        execution.setRequirement(conf.getRequirementChoices()[0]);
    else
        execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
    execution.setAuthenticatorFlow(false);
    execution.setAuthenticator(provider);
    execution.setPriority(getNextPriority(parentFlow));
    execution = realm.addAuthenticatorExecution(execution);
    data.put("id", execution.getId());
    adminEvent.operation(OperationType.CREATE).resource(ResourceType.AUTH_EXECUTION).resourcePath(session.getContext().getUri()).representation(data).success();
    String addExecutionPathSegment = UriBuilder.fromMethod(AuthenticationManagementResource.class, "addExecutionToFlow").build(parentFlow.getAlias()).getPath();
    return Response.created(session.getContext().getUri().getBaseUriBuilder().path(session.getContext().getUri().getPath().replace(addExecutionPathSegment, "")).path("executions").path(execution.getId()).build()).build();
}
Also used : AuthenticationExecutionModel(org.keycloak.models.AuthenticationExecutionModel) ProviderFactory(org.keycloak.provider.ProviderFactory) ClientAuthenticator(org.keycloak.authentication.ClientAuthenticator) ConfigurableAuthenticatorFactory(org.keycloak.authentication.ConfigurableAuthenticatorFactory) AuthenticationFlowModel(org.keycloak.models.AuthenticationFlowModel) BadRequestException(javax.ws.rs.BadRequestException) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes) NoCache(org.jboss.resteasy.annotations.cache.NoCache)

Example 34 with AuthenticationExecutionModel

use of org.keycloak.models.AuthenticationExecutionModel in project keycloak by keycloak.

the class AuthenticationProcessor method authenticationAction.

public Response authenticationAction(String execution) {
    logger.debug("authenticationAction");
    checkClientSession(true);
    String current = authenticationSession.getAuthNote(CURRENT_AUTHENTICATION_EXECUTION);
    if (execution == null || !execution.equals(current)) {
        logger.debug("Current execution does not equal executed execution.  Might be a page refresh");
        return new AuthenticationFlowURLHelper(session, realm, uriInfo).showPageExpired(authenticationSession);
    }
    UserModel authUser = authenticationSession.getAuthenticatedUser();
    validateUser(authUser);
    AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
    if (model == null) {
        logger.debug("Cannot find execution, reseting flow");
        logFailure();
        resetFlow();
        return authenticate();
    }
    event.client(authenticationSession.getClient().getClientId()).detail(Details.REDIRECT_URI, authenticationSession.getRedirectUri()).detail(Details.AUTH_METHOD, authenticationSession.getProtocol());
    String authType = authenticationSession.getAuthNote(Details.AUTH_TYPE);
    if (authType != null) {
        event.detail(Details.AUTH_TYPE, authType);
    }
    AuthenticationFlow authenticationFlow = createFlowExecution(this.flowId, model);
    Response challenge = authenticationFlow.processAction(execution);
    if (challenge != null)
        return challenge;
    if (authenticationSession.getAuthenticatedUser() == null) {
        throw new AuthenticationFlowException(AuthenticationFlowError.UNKNOWN_USER);
    }
    if (!authenticationFlow.isSuccessful()) {
        throw new AuthenticationFlowException(authenticationFlow.getFlowExceptions());
    }
    return authenticationComplete();
}
Also used : UserModel(org.keycloak.models.UserModel) Response(javax.ws.rs.core.Response) AuthenticationExecutionModel(org.keycloak.models.AuthenticationExecutionModel) AuthenticationFlowURLHelper(org.keycloak.services.util.AuthenticationFlowURLHelper)

Example 35 with AuthenticationExecutionModel

use of org.keycloak.models.AuthenticationExecutionModel in project keycloak by keycloak.

the class DefaultAuthenticationFlow method processSingleFlowExecutionModel.

private Response processSingleFlowExecutionModel(AuthenticationExecutionModel model, boolean calledFromFlow) {
    logger.debugf("check execution: '%s', requirement: '%s'", logExecutionAlias(model), model.getRequirement());
    if (isProcessed(model)) {
        logger.debugf("execution '%s' is processed", logExecutionAlias(model));
        return null;
    }
    // handle case where execution is a flow
    if (model.isAuthenticatorFlow()) {
        AuthenticationFlow authenticationFlow = processor.createFlowExecution(model.getFlowId(), model);
        Response flowChallenge = authenticationFlow.processFlow();
        if (flowChallenge == null) {
            if (authenticationFlow.isSuccessful()) {
                logger.debugf("Flow '%s' successfully finished", logExecutionAlias(model));
                setExecutionStatus(model, AuthenticationSessionModel.ExecutionStatus.SUCCESS);
            } else {
                logger.debugf("Flow '%s' failed", logExecutionAlias(model));
                setExecutionStatus(model, AuthenticationSessionModel.ExecutionStatus.FAILED);
            }
            return null;
        } else {
            setExecutionStatus(model, AuthenticationSessionModel.ExecutionStatus.CHALLENGED);
            return flowChallenge;
        }
    }
    // handle normal execution case
    AuthenticatorFactory factory = getAuthenticatorFactory(model);
    Authenticator authenticator = createAuthenticator(factory);
    logger.debugv("authenticator: {0}", factory.getId());
    UserModel authUser = processor.getAuthenticationSession().getAuthenticatedUser();
    // If executions are alternative, get the actual execution to show based on user preference
    List<AuthenticationSelectionOption> selectionOptions = createAuthenticationSelectionList(model);
    if (!selectionOptions.isEmpty() && calledFromFlow) {
        List<AuthenticationSelectionOption> finalSelectionOptions = selectionOptions.stream().filter(aso -> !aso.getAuthenticationExecution().isAuthenticatorFlow() && !isProcessed(aso.getAuthenticationExecution())).collect(Collectors.toList());
        if (finalSelectionOptions.isEmpty()) {
            // move to next
            return null;
        }
        model = finalSelectionOptions.get(0).getAuthenticationExecution();
        factory = (AuthenticatorFactory) processor.getSession().getKeycloakSessionFactory().getProviderFactory(Authenticator.class, model.getAuthenticator());
        if (factory == null) {
            throw new RuntimeException("Unable to find factory for AuthenticatorFactory: " + model.getAuthenticator() + " did you forget to declare it in a META-INF/services file?");
        }
        authenticator = createAuthenticator(factory);
    }
    AuthenticationProcessor.Result context = processor.createAuthenticatorContext(model, authenticator, executions);
    context.setAuthenticationSelections(selectionOptions);
    if (authenticator.requiresUser()) {
        if (authUser == null) {
            throw new AuthenticationFlowException("authenticator: " + factory.getId(), AuthenticationFlowError.UNKNOWN_USER);
        }
        if (!authenticator.configuredFor(processor.getSession(), processor.getRealm(), authUser)) {
            if (factory.isUserSetupAllowed() && model.isRequired() && authenticator.areRequiredActionsEnabled(processor.getSession(), processor.getRealm())) {
                // This means that having even though the user didn't validate the
                logger.debugv("authenticator SETUP_REQUIRED: {0}", factory.getId());
                setExecutionStatus(model, AuthenticationSessionModel.ExecutionStatus.SETUP_REQUIRED);
                authenticator.setRequiredActions(processor.getSession(), processor.getRealm(), processor.getAuthenticationSession().getAuthenticatedUser());
                return null;
            } else {
                throw new AuthenticationFlowException("authenticator: " + factory.getId(), AuthenticationFlowError.CREDENTIAL_SETUP_REQUIRED);
            }
        }
    }
    logger.debugv("invoke authenticator.authenticate: {0}", factory.getId());
    authenticator.authenticate(context);
    return processResult(context, false);
}
Also used : Response(javax.ws.rs.core.Response) UserModel(org.keycloak.models.UserModel) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) Iterator(java.util.Iterator) StringUtil(org.keycloak.utils.StringUtil) Predicate(java.util.function.Predicate) Logger(org.jboss.logging.Logger) ConditionalAuthenticator(org.keycloak.authentication.authenticators.conditional.ConditionalAuthenticator) Constants(org.keycloak.models.Constants) Set(java.util.Set) ServicesLogger(org.keycloak.services.ServicesLogger) Collectors(java.util.stream.Collectors) HttpMethod(javax.ws.rs.HttpMethod) ArrayList(java.util.ArrayList) MultivaluedMap(javax.ws.rs.core.MultivaluedMap) Objects(java.util.Objects) List(java.util.List) UserModel(org.keycloak.models.UserModel) Stream(java.util.stream.Stream) Response(javax.ws.rs.core.Response) AuthenticationExecutionModel(org.keycloak.models.AuthenticationExecutionModel) AuthenticationFlowModel(org.keycloak.models.AuthenticationFlowModel) CommonClientSessionModel(org.keycloak.sessions.CommonClientSessionModel) LinkedList(java.util.LinkedList) OAuth2Constants(org.keycloak.OAuth2Constants) ConditionalAuthenticator(org.keycloak.authentication.authenticators.conditional.ConditionalAuthenticator)

Aggregations

AuthenticationExecutionModel (org.keycloak.models.AuthenticationExecutionModel)51 AuthenticationFlowModel (org.keycloak.models.AuthenticationFlowModel)32 AuthenticatorConfigModel (org.keycloak.models.AuthenticatorConfigModel)11 Path (javax.ws.rs.Path)8 NoCache (org.jboss.resteasy.annotations.cache.NoCache)8 HashMap (java.util.HashMap)7 Response (javax.ws.rs.core.Response)7 RealmModel (org.keycloak.models.RealmModel)7 BadRequestException (javax.ws.rs.BadRequestException)6 NotFoundException (javax.ws.rs.NotFoundException)6 POST (javax.ws.rs.POST)6 ArrayList (java.util.ArrayList)5 LinkedList (java.util.LinkedList)5 Consumes (javax.ws.rs.Consumes)5 Before (org.junit.Before)5 ClientModel (org.keycloak.models.ClientModel)4 List (java.util.List)3 UserModel (org.keycloak.models.UserModel)3 MultivaluedMap (javax.ws.rs.core.MultivaluedMap)2 Logger (org.jboss.logging.Logger)2