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();
}
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();
}
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();
}
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();
}
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);
}
Aggregations