Java Code Examples for org.keycloak.authentication.AuthenticationFlowContext#getRealm()

The following examples show how to use org.keycloak.authentication.AuthenticationFlowContext#getRealm() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: RequireGroupAuthenticator.java    From keycloak-extension-playground with Apache License 2.0 6 votes vote down vote up
@Override
public void authenticate(AuthenticationFlowContext context) {

    AuthenticatorConfigModel configModel = context.getAuthenticatorConfig();

    String groupPath = configModel.getConfig().get(RequireGroupAuthenticatorFactory.GROUP);
    RealmModel realm = context.getRealm();
    UserModel user = context.getUser();

    if (!isMemberOfGroup(realm, user, groupPath)) {

        LOG.debugf("Access denied because of missing group membership. realm=%s username=%s groupPath=%s", realm.getName(), user.getUsername(), groupPath);
        context.cancelLogin();
        return;
    }

    context.success();
}
 
Example 2
Source File: IdpReviewProfileAuthenticator.java    From keycloak with Apache License 2.0 6 votes vote down vote up
protected boolean requiresUpdateProfilePage(AuthenticationFlowContext context, SerializedBrokeredIdentityContext userCtx, BrokeredIdentityContext brokerContext) {
    String enforceUpdateProfile = context.getAuthenticationSession().getAuthNote(ENFORCE_UPDATE_PROFILE);
    if (Boolean.parseBoolean(enforceUpdateProfile)) {
        return true;
    }

    String updateProfileFirstLogin;
    AuthenticatorConfigModel authenticatorConfig = context.getAuthenticatorConfig();
    if (authenticatorConfig == null || !authenticatorConfig.getConfig().containsKey(IdpReviewProfileAuthenticatorFactory.UPDATE_PROFILE_ON_FIRST_LOGIN)) {
        updateProfileFirstLogin = IdentityProviderRepresentation.UPFLM_MISSING;
    } else {
        updateProfileFirstLogin = authenticatorConfig.getConfig().get(IdpReviewProfileAuthenticatorFactory.UPDATE_PROFILE_ON_FIRST_LOGIN);
    }

    RealmModel realm = context.getRealm();
    return IdentityProviderRepresentation.UPFLM_ON.equals(updateProfileFirstLogin)
            || (IdentityProviderRepresentation.UPFLM_MISSING.equals(updateProfileFirstLogin) && !Validation.validateUserMandatoryFields(realm, userCtx));
}
 
Example 3
Source File: ScriptBasedAuthenticator.java    From keycloak with Apache License 2.0 6 votes vote down vote up
private InvocableScriptAdapter getInvocableScriptAdapter(AuthenticationFlowContext context) {

        Map<String, String> config = getAuthenticatorConfig(context).getConfig();

        String scriptName = config.get(SCRIPT_NAME);
        String scriptCode = config.get(SCRIPT_CODE);
        String scriptDescription = config.get(SCRIPT_DESCRIPTION);

        RealmModel realm = context.getRealm();

        ScriptingProvider scripting = context.getSession().getProvider(ScriptingProvider.class);

        //TODO lookup script by scriptId instead of creating it every time
        ScriptModel script = scripting.createScript(realm.getId(), ScriptModel.TEXT_JAVASCRIPT, scriptName, scriptCode, scriptDescription);

        //how to deal with long running scripts -> timeout?
        return scripting.prepareInvocableScript(script, bindings -> {
            bindings.put("script", script);
            bindings.put("realm", context.getRealm());
            bindings.put("user", context.getUser());
            bindings.put("session", context.getSession());
            bindings.put("httpRequest", context.getHttpRequest());
            bindings.put("authenticationSession", context.getAuthenticationSession());
            bindings.put("LOG", LOGGER);
        });
    }
 
Example 4
Source File: RequireRoleAuthenticator.java    From keycloak-extension-playground with Apache License 2.0 6 votes vote down vote up
@Override
public void authenticate(AuthenticationFlowContext context) {

    AuthenticatorConfigModel configModel = context.getAuthenticatorConfig();

    String roleName = configModel.getConfig().get(RequireRoleAuthenticatorFactory.ROLE);
    RealmModel realm = context.getRealm();
    UserModel user = context.getUser();

    if (userHasRole(realm, user, roleName)) {
        context.success();
        return;
    }

    LOG.debugf("Access denied because of missing role. realm=%s username=%s role=%s", realm.getName(), user.getUsername(), roleName);
    context.getEvent().user(user);
    context.getEvent().error(Errors.NOT_ALLOWED);
    context.forkWithErrorMessage(new FormMessage(Messages.NO_ACCESS));
}
 
Example 5
Source File: WebAuthnAuthenticator.java    From keycloak with Apache License 2.0 6 votes vote down vote up
public void authenticate(AuthenticationFlowContext context) {
    LoginFormsProvider form = context.form();
 
    Challenge challenge = new DefaultChallenge();
    String challengeValue = Base64Url.encode(challenge.getValue());
    context.getAuthenticationSession().setAuthNote(WebAuthnConstants.AUTH_CHALLENGE_NOTE, challengeValue);
    form.setAttribute(WebAuthnConstants.CHALLENGE, challengeValue);

    WebAuthnPolicy policy = getWebAuthnPolicy(context);
    String rpId = getRpID(context);
    form.setAttribute(WebAuthnConstants.RP_ID, rpId);

    UserModel user = context.getUser();
    boolean isUserIdentified = false;
    if (user != null) {
        // in 2 Factor Scenario where the user has already been identified
        WebAuthnAuthenticatorsBean authenticators = new WebAuthnAuthenticatorsBean(context.getSession(), context.getRealm(), user, getCredentialType());
        if (authenticators.getAuthenticators().isEmpty()) {
            // require the user to register webauthn authenticator
            return;
        }
        isUserIdentified = true;
        form.setAttribute(WebAuthnConstants.ALLOWED_AUTHENTICATORS, authenticators);
    } else {
        // in ID-less & Password-less Scenario
        // NOP
    }
    form.setAttribute(WebAuthnConstants.IS_USER_IDENTIFIED, Boolean.toString(isUserIdentified));

    // read options from policy
    String userVerificationRequirement = policy.getUserVerificationRequirement();
    form.setAttribute(WebAuthnConstants.USER_VERIFICATION, userVerificationRequirement);

    context.challenge(form.createLoginWebAuthn());
}
 
Example 6
Source File: ConditionalRoleAuthenticator.java    From keycloak with Apache License 2.0 6 votes vote down vote up
@Override
public boolean matchCondition(AuthenticationFlowContext context) {
    UserModel user = context.getUser();
    RealmModel realm = context.getRealm();
    AuthenticatorConfigModel authConfig = context.getAuthenticatorConfig();
    if (user != null && authConfig!=null && authConfig.getConfig()!=null) {
        String requiredRole = authConfig.getConfig().get(ConditionalRoleAuthenticatorFactory.CONDITIONAL_USER_ROLE);
        RoleModel role = KeycloakModelUtils.getRoleFromString(realm, requiredRole);
        if (role == null) {
            logger.errorv("Invalid role name submitted: {0}", requiredRole);
            return false;
        }
        return user.hasRole(role);
    }
    return false;
}
 
Example 7
Source File: HttpBasicAuthenticator.java    From keycloak with Apache License 2.0 5 votes vote down vote up
@Override
public void authenticate(final AuthenticationFlowContext context) {
    final HttpRequest httpRequest = context.getHttpRequest();
    final HttpHeaders httpHeaders = httpRequest.getHttpHeaders();
    final String[] usernameAndPassword = getUsernameAndPassword(httpHeaders);

    context.attempted();

    if (usernameAndPassword != null) {
        final RealmModel realm = context.getRealm();
        final String username = usernameAndPassword[0];
        final UserModel user = context.getSession().users().getUserByUsername(username, realm);

        // to allow success/failure logging for brute force
        context.getEvent().detail(Details.USERNAME, username);
        context.getAuthenticationSession().setAuthNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME, username);

        if (user != null) {
            final String password = usernameAndPassword[1];
            final boolean valid = context.getSession().userCredentialManager().isValid(realm, user, UserCredentialModel.password(password));

            if (valid) {
                if (isTemporarilyDisabledByBruteForce(context, user)) {
                    userDisabledAction(context, realm, user, Errors.USER_TEMPORARILY_DISABLED);
                } else if (user.isEnabled()) {
                    userSuccessAction(context, user);
                } else {
                    userDisabledAction(context, realm, user, Errors.USER_DISABLED);
                }
            } else {
                notValidCredentialsAction(context, realm, user);
            }
        } else {
            nullUserAction(context, realm, username);
        }
    }
}
 
Example 8
Source File: IdpAutoLinkAuthenticator.java    From keycloak with Apache License 2.0 5 votes vote down vote up
@Override
protected void authenticateImpl(AuthenticationFlowContext context, SerializedBrokeredIdentityContext serializedCtx, BrokeredIdentityContext brokerContext) {
    KeycloakSession session = context.getSession();
    RealmModel realm = context.getRealm();
    AuthenticationSessionModel authSession = context.getAuthenticationSession();

    UserModel existingUser = getExistingUser(session, realm, authSession);

    logger.debugf("User '%s' is set to authentication context when link with identity provider '%s' . Identity provider username is '%s' ", existingUser.getUsername(),
            brokerContext.getIdpConfig().getAlias(), brokerContext.getUsername());

    context.setUser(existingUser);
    context.success();
}
 
Example 9
Source File: WebAuthnAuthenticator.java    From keycloak with Apache License 2.0 5 votes vote down vote up
private Response createErrorResponse(AuthenticationFlowContext context, final String errorCase) {
    LoginFormsProvider provider = context.form().setError(errorCase);
    UserModel user = context.getUser();
    if (user != null) {
        WebAuthnAuthenticatorsBean authenticators = new WebAuthnAuthenticatorsBean(context.getSession(), context.getRealm(), user, getCredentialType());
        if (authenticators.getAuthenticators() != null) {
            provider.setAttribute(WebAuthnConstants.ALLOWED_AUTHENTICATORS, authenticators);
        }
    }
    return provider.createWebAuthnErrorPage();
}
 
Example 10
Source File: ThirdPartyMfaAuthenticator.java    From keycloak-extension-playground with Apache License 2.0 5 votes vote down vote up
@Override
public void authenticate(AuthenticationFlowContext context) {

    RealmModel realm = context.getRealm();
    UserModel user = context.getUser();
    String username = user.getUsername();

    log.infof("Request MFA for User. username=%s", username);

    String existingMfaSessionMarker = session.sessions().getUserSessions(realm, user).stream()
            // TODO ensure user comes from the same device
            .filter(us -> us.getNote(MFA_SESSION_MARKER_KEY) != null)
            .map(us -> us.getNote(MFA_SESSION_MARKER_KEY))
            .findFirst()
            .orElse(null);

    if (existingMfaSessionMarker != null) {
        // There is already an existing user session that was authenticated via MFA

        // TODO check max time since last mfa validation
        String[] items = existingMfaSessionMarker.split(";");
        long mfaAuthTime = Long.parseLong(items[0]);
        MfaMethod mfaMethod = MfaMethod.valueOf(items[1]);

        log.infof("MFA already valid for this session, skipping mfa check. realm=%s username=%s mfa_method=%s mfa_challenge_timestamp=%s",
                realm.getName(), username, mfaMethod, mfaAuthTime);
        context.success();
        return;
    }

    requestMfaChallenge(context, username, context.getAuthenticationSession());
}
 
Example 11
Source File: AccessPolicyAuthenticator.java    From keycloak-extension-playground with Apache License 2.0 5 votes vote down vote up
@Override
public void authenticate(AuthenticationFlowContext context) {

    AuthenticatorConfigModel configModel = context.getAuthenticatorConfig();

    if (configModel == null) {
        context.attempted();
        return;
    }

    String accessPolicyJson = configModel.getConfig().get(AccessPolicyAuthenticatorFactory.ACCESS_POLICY);
    if (accessPolicyJson == null) {
        context.attempted();
        return;
    }

    AccessPolicy accessPolicy = accessPolicyParser.parse(accessPolicyJson);

    RealmModel realm = context.getRealm();
    ClientModel client = context.getAuthenticationSession().getClient();
    UserModel user = context.getUser();

    if (!accessPolicy.hasAccess(realm, user, client)) {

        log.debugf("Access denied because of access policy. realm=%s client=%s username=%s", realm.getName(), client.getClientId(), user.getUsername());
        context.getEvent().user(user);
        context.getEvent().error(Errors.NOT_ALLOWED);
        context.forkWithErrorMessage(new FormMessage(Messages.NO_ACCESS));
        return;
    }


    context.success();
}
 
Example 12
Source File: LoginNotifyEmailAuthenticator.java    From keycloak-extension-playground with Apache License 2.0 5 votes vote down vote up
private Map<String, String> createMailAttributes(AuthenticationFlowContext context) {

        RealmModel realm = context.getRealm();

        Map<String, String> attributes = new HashMap<>();
        attributes.put("username", context.getUser().getUsername());
        attributes.put("ipAddress", context.getConnection().getRemoteAddr());
        URI accountUrl = context.getUriInfo().getRequestUriBuilder().replaceQuery("").replacePath("/auth/realms/{realm}/account").build(realm.getName());
        attributes.put("accountUrl", accountUrl.toString());
        String realmDisplayName = realm.getDisplayName() != null ? realm.getDisplayName() : realm.getName();
        attributes.put("realmDisplayName", realmDisplayName);

        return attributes;
    }
 
Example 13
Source File: MinPasswordAgeAuthenticator.java    From keycloak-extension-playground with Apache License 2.0 5 votes vote down vote up
@Override
public void authenticate(AuthenticationFlowContext context) {

    RealmModel realm = context.getRealm();
    UserModel user = context.getUser();
    Map<String, String> config = (context.getAuthenticatorConfig() == null ? Collections.emptyMap() : context.getAuthenticatorConfig().getConfig());

    List<CredentialModel> passwords = context.getSession().userCredentialManager().getStoredCredentialsByType(realm, user, PasswordCredentialModel.TYPE);
    if (!passwords.isEmpty()) {
        CredentialModel passwordCredential = passwords.get(0);

        Instant creationTime = Instant.ofEpochMilli(passwordCredential.getCreatedDate());

        Duration minPasswordAge = Duration.parse(config.getOrDefault(MIN_PASSWORD_AGE_DURATION, "PT15M"));

        if (creationTime.isAfter(Instant.now().minus(minPasswordAge))) {

            log.warnf("Access denied because of min password age. realm=%s username=%s", realm.getName(), user.getUsername());
            context.getEvent().user(user);
            context.getEvent().error(Errors.NOT_ALLOWED);
            context.forkWithErrorMessage(new FormMessage(Messages.NO_ACCESS));

            return;
        }
    }

    context.success();
}
 
Example 14
Source File: SessionPropagationAuthenticator.java    From keycloak-extension-playground with Apache License 2.0 4 votes vote down vote up
@Override
public void authenticate(AuthenticationFlowContext context) {

    MultivaluedMap<String, String> queryParameters = context.getHttpRequest().getUri().getQueryParameters();
    String encryptedSessionReferenceData = queryParameters.getFirst("ksr");

    if (encryptedSessionReferenceData == null) {
        log.infof("Reject session propagation. Reason: Missing sessionReferenceData.");
        context.attempted();
        return;
    }

    String encryptedSessionReferenceSalt = queryParameters.getFirst("ksrs");
    if (encryptedSessionReferenceSalt == null) {
        log.infof("Reject session propagation. Reason: Missing encryptedSessionReferenceSalt.");
        context.attempted();
        return;
    }

    log.infof("Attempting user session propagation...");

    // TODO use encryption key from env variable to avoid exposing this via the admin-console
    String sharedEncryptionKey = getConfigProperty(context, ENCRYPTION_KEY, "changeme");
    String sessionReferenceData;
    try {
        sessionReferenceData = CryptoUtil.decrypt(encryptedSessionReferenceData, encryptionKeyFrom(sharedEncryptionKey, encryptedSessionReferenceSalt));
    } catch (Exception ex) {
        context.failure(AuthenticationFlowError.INVALID_CREDENTIALS);
        log.infof("Reject session propagation. Reason: bad encryptedSessionReferenceData.");
        return;
    }

    String[] items = sessionReferenceData != null ? sessionReferenceData.split(";") : new String[0];
    if (items.length != 2) {
        context.failure(AuthenticationFlowError.INVALID_CREDENTIALS);
        log.infof("Reject session propagation. Reason: bad sessionReferenceData.");
        return;
    }

    long timestamp = Long.parseLong(items[0]);

    int sessionReferenceMaxAgeSeconds = Integer.parseInt(getConfigProperty(context, SESSION_REFERENCE_MAX_AGE_SECONDS, "30"));
    boolean sessionReferenceToOld = Instant.now().isAfter(Instant.ofEpochMilli(timestamp).plus(sessionReferenceMaxAgeSeconds, ChronoUnit.SECONDS));
    if (sessionReferenceToOld) {
        context.failure(AuthenticationFlowError.INVALID_CLIENT_SESSION);
        log.infof("Reject session propagation. Reason: session reference to old.");
        return;
    }

    String sessionHandle = items[1];

    KeycloakSessionInfo keycloakSessionInfo = resolveKeycloakSessionId(sessionHandle, sharedEncryptionKey, encryptedSessionReferenceSalt, getConfigProperty(context, SESSION_VALIDATION_SERVICE_URL, null));
    if (keycloakSessionInfo == null) {
        context.failure(AuthenticationFlowError.INVALID_CLIENT_SESSION);
        log.infof("Reject session propagation. Reason: Remote session not found.");
        return;
    }

    String keycloakSessionId = keycloakSessionInfo.getKeycloakSessionId();

    RealmModel realm = context.getRealm();
    UserSessionModel userSession = session.sessions().getUserSession(realm, keycloakSessionId);

    if (userSession == null) {
        context.failure(AuthenticationFlowError.INVALID_CLIENT_SESSION);
        log.infof("Reject session propagation. Reason: keycloak session not found.");
        return;
    }

    if (!keycloakSessionInfo.getUsername().equals(userSession.getUser().getUsername())) {
        context.failure(AuthenticationFlowError.INVALID_CLIENT_SESSION);
        log.infof("Reject session propagation. Reason: username mismatch.");
        return;
    }

    // TODO check if session propagation is allowed for client...

    log.infof("Successful user session propagation.");
    context.getAuthenticationSession().setAuthenticatedUser(userSession.getUser());

    context.success();
}
 
Example 15
Source File: AuthzPolicyAuthenticator.java    From keycloak-extension-playground with Apache License 2.0 4 votes vote down vote up
@Override
public void authenticate(AuthenticationFlowContext context) {

    RealmModel realm = context.getRealm();
    ClientModel client = context.getAuthenticationSession().getClient();

    AuthorizationProvider authzProvider = session.getProvider(AuthorizationProvider.class);
    PolicyStore policyStore = authzProvider.getStoreFactory().getPolicyStore();

    AuthenticatorConfigModel configModel = context.getAuthenticatorConfig();
    Map<String, String> config = configModel.getConfig();

    String clientPolicyName = config.get(CLIENTS_POLICY);
    String rolePolicyName = config.get(ROLES_POLICY);

    String realmManagementClientId = realm.getClientByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID).getId();
    Policy clientPolicy = policyStore.findByName(clientPolicyName, realmManagementClientId);

    List<String> clients = parseJson(clientPolicy.getConfig().get("clients"), List.class);
    if (!clients.contains(client.getId())) {
        // The current client is not contained in the client policy -> skip the authenticator
        context.success();
        return;
    }

    Policy rolePolicy = policyStore.findByName(rolePolicyName, realmManagementClientId);
    List<Map<String, Object>> roles = parseJson(rolePolicy.getConfig().get("roles"), List.class);
    List<RoleModel> requiredRoles = roles.stream()
            .map(r -> (String) r.get("id"))
            .map(realm::getRoleById)
            .collect(Collectors.toList());

    UserModel user = context.getUser();
    boolean accessAllowed = requiredRoles.stream().anyMatch(user::hasRole);

    if (accessAllowed) {
        // the user has the required roles -> let the authentication succeed
        context.success();
        return;
    }

    // the user does not have the required roles -> deny the authentication

    context.getEvent().user(user);
    context.getEvent().error(Errors.NOT_ALLOWED);
    context.forkWithErrorMessage(new FormMessage(Messages.NO_ACCESS));
}
 
Example 16
Source File: IdpCreateUserIfUniqueAuthenticator.java    From keycloak with Apache License 2.0 4 votes vote down vote up
@Override
protected void authenticateImpl(AuthenticationFlowContext context, SerializedBrokeredIdentityContext serializedCtx, BrokeredIdentityContext brokerContext) {

    KeycloakSession session = context.getSession();
    RealmModel realm = context.getRealm();

    if (context.getAuthenticationSession().getAuthNote(EXISTING_USER_INFO) != null) {
        context.attempted();
        return;
    }

    String username = getUsername(context, serializedCtx, brokerContext);
    if (username == null) {
        ServicesLogger.LOGGER.resetFlow(realm.isRegistrationEmailAsUsername() ? "Email" : "Username");
        context.getAuthenticationSession().setAuthNote(ENFORCE_UPDATE_PROFILE, "true");
        context.resetFlow();
        return;
    }

    ExistingUserInfo duplication = checkExistingUser(context, username, serializedCtx, brokerContext);

    if (duplication == null) {
        logger.debugf("No duplication detected. Creating account for user '%s' and linking with identity provider '%s' .",
                username, brokerContext.getIdpConfig().getAlias());

        UserModel federatedUser = session.users().addUser(realm, username);
        federatedUser.setEnabled(true);
        federatedUser.setEmail(brokerContext.getEmail());
        federatedUser.setFirstName(brokerContext.getFirstName());
        federatedUser.setLastName(brokerContext.getLastName());

        for (Map.Entry<String, List<String>> attr : serializedCtx.getAttributes().entrySet()) {
            federatedUser.setAttribute(attr.getKey(), attr.getValue());
        }

        AuthenticatorConfigModel config = context.getAuthenticatorConfig();
        if (config != null && Boolean.parseBoolean(config.getConfig().get(IdpCreateUserIfUniqueAuthenticatorFactory.REQUIRE_PASSWORD_UPDATE_AFTER_REGISTRATION))) {
            logger.debugf("User '%s' required to update password", federatedUser.getUsername());
            federatedUser.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
        }

        userRegisteredSuccess(context, federatedUser, serializedCtx, brokerContext);

        context.setUser(federatedUser);
        context.getAuthenticationSession().setAuthNote(BROKER_REGISTERED_NEW_USER, "true");
        context.success();
    } else {
        logger.debugf("Duplication detected. There is already existing user with %s '%s' .",
                duplication.getDuplicateAttributeName(), duplication.getDuplicateAttributeValue());

        // Set duplicated user, so next authenticators can deal with it
        context.getAuthenticationSession().setAuthNote(EXISTING_USER_INFO, duplication.serialize());
        //Only show error message if the authenticator was required
        if (context.getExecution().isRequired()) {
            Response challengeResponse = context.form()
                    .setError(Messages.FEDERATED_IDENTITY_EXISTS, duplication.getDuplicateAttributeName(), duplication.getDuplicateAttributeValue())
                    .createErrorPage(Response.Status.CONFLICT);
            context.challenge(challengeResponse);
            context.getEvent()
                    .user(duplication.getExistingUserId())
                    .detail("existing_" + duplication.getDuplicateAttributeName(), duplication.getDuplicateAttributeValue())
                    .removeDetail(Details.AUTH_METHOD)
                    .removeDetail(Details.AUTH_TYPE)
                    .error(Errors.FEDERATED_IDENTITY_EXISTS);
        } else {
            context.attempted();
        }
    }
}
 
Example 17
Source File: IdpCreateUserIfUniqueAuthenticator.java    From keycloak with Apache License 2.0 4 votes vote down vote up
protected String getUsername(AuthenticationFlowContext context, SerializedBrokeredIdentityContext serializedCtx, BrokeredIdentityContext brokerContext) {
    RealmModel realm = context.getRealm();
    return realm.isRegistrationEmailAsUsername() ? brokerContext.getEmail() : brokerContext.getModelUsername();
}
 
Example 18
Source File: IdpReviewProfileAuthenticator.java    From keycloak with Apache License 2.0 4 votes vote down vote up
@Override
protected void actionImpl(AuthenticationFlowContext context, SerializedBrokeredIdentityContext userCtx, BrokeredIdentityContext brokerContext) {
    EventBuilder event = context.getEvent();
    event.event(EventType.UPDATE_PROFILE);
    MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();

    RealmModel realm = context.getRealm();

    List<FormMessage> errors = Validation.validateUpdateProfileForm(realm, formData, userCtx.isEditUsernameAllowed());
    if (errors != null && !errors.isEmpty()) {
        Response challenge = context.form()
                .setErrors(errors)
                .setAttribute(LoginFormsProvider.UPDATE_PROFILE_CONTEXT_ATTR, userCtx)
                .setFormData(formData)
                .createUpdateProfilePage();
        context.challenge(challenge);
        return;
    }

    String username = realm.isRegistrationEmailAsUsername() ? formData.getFirst(UserModel.EMAIL) : formData.getFirst(UserModel.USERNAME);
    userCtx.setUsername(username);
    userCtx.setFirstName(formData.getFirst(UserModel.FIRST_NAME));
    userCtx.setLastName(formData.getFirst(UserModel.LAST_NAME));

    String email = formData.getFirst(UserModel.EMAIL);
    if (!ObjectUtil.isEqualOrBothNull(email, userCtx.getEmail())) {
        if (logger.isTraceEnabled()) {
            logger.tracef("Email updated on updateProfile page to '%s' ", email);
        }

        userCtx.setEmail(email);
        context.getAuthenticationSession().setAuthNote(UPDATE_PROFILE_EMAIL_CHANGED, "true");
    }

    AttributeFormDataProcessor.process(formData, realm, userCtx);

    userCtx.saveToAuthenticationSession(context.getAuthenticationSession(), BROKERED_CONTEXT_NOTE);

    logger.debugf("Profile updated successfully after first authentication with identity provider '%s' for broker user '%s'.", brokerContext.getIdpConfig().getAlias(), userCtx.getUsername());

    event.detail(Details.UPDATED_EMAIL, email);

    // Ensure page is always shown when user later returns to it - for example with form "back" button
    context.getAuthenticationSession().setAuthNote(ENFORCE_UPDATE_PROFILE, "true");

    context.success();
}
 
Example 19
Source File: ThirdPartyMfaAuthenticator.java    From keycloak-extension-playground with Apache License 2.0 4 votes vote down vote up
@Override
public void action(AuthenticationFlowContext context) {

    MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();

    if (formData.containsKey("cancel")) {
        context.resetFlow();
        context.fork();
        return;
    }

    RealmModel realm = context.getRealm();
    UserModel user = context.getUser();
    String username = user.getUsername();
    log.infof("Request MFA for User. username=%s", username);

    AuthenticationSessionModel authSession = context.getAuthenticationSession();

    MfaMethod mfaMethod = MfaMethod.resolve(authSession.getAuthNote(MFA_METHOD));

    if (formData.containsKey(USE_OTP)) {
        authSession.setAuthNote(MFA_METHOD, MfaMethod.OTP.name());
        requestMfaChallenge(context, username, authSession);
        return;
    }

    String mfaChallengeId = authSession.getAuthNote(MFA_CHALLENGE);
    log.infof("Found challengeId=%s", mfaChallengeId);

    MfaVerifyRequest mfaRequest = new MfaVerifyRequest();
    mfaRequest.setChallengeId(UUID.fromString(mfaChallengeId));
    mfaRequest.setChallengeInput(Sanitizers.BLOCKS.sanitize(formData.getFirst("challenge_input")));

    MfaVerifyResponse mfaVerifyResponse = mfaClient.verifyAuthChallenge(mfaRequest);

    if (mfaVerifyResponse.isSuccessful()) {

        log.infof("MFA authentication successful. realm=%s username=%s mfa_method=%s mfa_challenge_duration=%s", realm.getName(), username, mfaMethod, computeChallengeDuration(authSession));

        signalSuccessfulMfaAuthentication(context, authSession, mfaMethod);
        return;
    }

    if (mfaVerifyResponse.isCompleted()) {
        log.infof("MFA authentication failed. realm=%s username=%s error_code=%s mfa_method=%s mfa_challenge_duration=%s", realm.getName(), user.getUsername(), mfaVerifyResponse.getErrorCode(), mfaMethod, computeChallengeDuration(authSession));
        context.getEvent().user(user);

        String errorMessage = Messages.LOGIN_TIMEOUT;
        if (MfaVerifyResponse.ERR_TIMEOUT.equals(mfaVerifyResponse.getErrorCode())) {
            context.getEvent().error(Errors.SESSION_EXPIRED);
        } else {
            errorMessage = Messages.INVALID_TOTP;
            context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
        }
        context.resetFlow();
        context.forkWithErrorMessage(new FormMessage(errorMessage));
        return;
    }

    log.infof("MFA authentication attempt failed. Retrying realm=%s username=%s error_code=%s mfa_method=%s", realm.getName(), user.getUsername(), mfaVerifyResponse.getErrorCode(), mfaMethod);

    Response response = createChallengeFormResponse(context, false, mfaMethod, mfaVerifyResponse);

    context.failureChallenge(AuthenticationFlowError.INVALID_CREDENTIALS, response);
}