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

The following examples show how to use org.keycloak.authentication.AuthenticationFlowContext#getUser() . 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: DynamicIdpRedirectAuthenticator.java    From keycloak-extension-playground with Apache License 2.0 6 votes vote down vote up
@Override
public void authenticate(AuthenticationFlowContext context) {

    UserModel user = context.getUser();
    if (user == null) {
        context.attempted();
        return;
    }

    String targetIdp = determineTargetIdp(user, context);
    if (targetIdp != null) {
        redirect(context, targetIdp);
        return;
    }

    boolean fallbackToAuthFlow = getConfigValueOrDefault(context.getAuthenticatorConfig(), FALLBACK_TO_AUTHFLOW_CONFIG_PROPERTY, "true", Boolean::parseBoolean);
    if (fallbackToAuthFlow) {
        context.attempted();
        return;
    }

    context.getEvent().error(Errors.UNKNOWN_IDENTITY_PROVIDER);
    context.failure(AuthenticationFlowError.IDENTITY_PROVIDER_NOT_FOUND);
    context.cancelLogin();
    context.resetFlow();
}
 
Example 2
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 3
Source File: ConditionalUserAttributeValue.java    From keycloak with Apache License 2.0 6 votes vote down vote up
@Override
public boolean matchCondition(AuthenticationFlowContext context) {
    boolean result = false;

    // Retrieve configuration
    Map<String, String> config = context.getAuthenticatorConfig().getConfig();
    String attributeName = config.get(ConditionalUserAttributeValueFactory.CONF_ATTRIBUTE_NAME);
    String attributeValue = config.get(ConditionalUserAttributeValueFactory.CONF_ATTRIBUTE_EXPECTED_VALUE);
    boolean negateOutput = Boolean.parseBoolean(config.get(ConditionalUserAttributeValueFactory.CONF_NOT));

    UserModel user = context.getUser();
    if (user == null) {
        throw new AuthenticationFlowException("authenticator: " + ConditionalUserAttributeValueFactory.PROVIDER_ID, AuthenticationFlowError.UNKNOWN_USER);
    }

    List<String> lstValues = user.getAttribute(attributeName);
    if (lstValues != null) {
        result = lstValues.contains(attributeValue);
    }

    if (negateOutput) {
        result = !result;
    }

    return result;
}
 
Example 4
Source File: SetUserAttributeAuthenticator.java    From keycloak with Apache License 2.0 6 votes vote down vote up
@Override
public void authenticate(AuthenticationFlowContext context) {
    // Retrieve configuration
    Map<String, String> config = context.getAuthenticatorConfig().getConfig();
    String attrName = config.get(SetUserAttributeAuthenticatorFactory.CONF_ATTR_NAME);
    String attrValue = config.get(SetUserAttributeAuthenticatorFactory.CONF_ATTR_VALUE);

    UserModel user = context.getUser();
    if (user.getAttribute(attrName) == null) {
        user.setSingleAttribute(attrName, attrValue);
    }
    else {
        List<String> attrValues = new ArrayList<>(user.getAttribute(attrName));
        if (!attrValues.contains(attrValue)) {
            attrValues.add(attrValue);
        }
        user.setAttribute(attrName, attrValues);
    }

    context.success();
}
 
Example 5
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 6
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 7
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 8
Source File: WebAuthn4jAuthenticator.java    From keycloak-webauthn-authenticator with Apache License 2.0 6 votes vote down vote up
public void authenticate(AuthenticationFlowContext context) {
    LoginFormsProvider form = context.form();
    Map<String, String> params = generateParameters(context.getRealm(), context.getUriInfo().getBaseUri());
    context.getAuthenticationSession().setAuthNote(WebAuthnConstants.AUTH_CHALLENGE_NOTE, params.get(WebAuthnConstants.CHALLENGE));
    UserModel user = context.getUser();
    boolean isUserIdentified = false;
    if (user != null) {
        // in 2 Factor Scenario where the user has already identified
        isUserIdentified = true;
        form.setAttribute("authenticators", new WebAuthnAuthenticatorsBean(user));
    } else {
        // in ID-less & Password-less Scenario
        // NOP
    }
    params.put("isUserIdentified", Boolean.toString(isUserIdentified));
    params.forEach(form::setAttribute);
    context.challenge(form.createForm("webauthn.ftl"));
}
 
Example 9
Source File: X509ClientCertificateAuthenticator.java    From keycloak with Apache License 2.0 5 votes vote down vote up
@Override
public void action(AuthenticationFlowContext context) {
    MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
    if (formData.containsKey("cancel")) {
        context.clearUser();
        context.attempted();
        return;
    }
    if (context.getUser() != null) {
        recordX509CertificateAuditDataViaContextEvent(context);
        context.success();
        return;
    }
    context.attempted();
}
 
Example 10
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 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: SimpleAuthenticator.java    From keycloak-extension-playground with Apache License 2.0 5 votes vote down vote up
@Override
public void authenticate(AuthenticationFlowContext context) {

    UserModel user = context.getUser();

    if (user != null) {
        LOG.infof("Pass through: %s%n", user.getUsername());
    } else {
        LOG.infof("Pass through: %s%n", "anonymous");
    }

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

    UserModel user = context.getUser();

    long currentLoginTime = System.currentTimeMillis();
    long lastLoginTime = detectLastLoginTimeForUser(user, currentLoginTime);

    try {
        if (user.getEmail() != null) {
            String timeSinceLastEmail = getConfigSettingOrDefault(context, TIME_SINCE_LAST_LOGIN, null);
            if (timeSinceLastEmail != null) {
                Duration duration = Duration.parse(timeSinceLastEmail);
                Instant lastLogin = Instant.ofEpochMilli(lastLoginTime);
                Instant currentLogin = Instant.ofEpochMilli(currentLoginTime);
                if (lastLogin.plus(duration).isBefore(currentLogin)) {
                    log.infof("Sending login notification email after longer absence. userId=%s", user.getUsername());
                    sendLoginNotificationEmail(context, user);
                }
            }
        }
    } catch (Exception ex) {
        log.warnf("Could not send login notification email after longer absence. userId=%s", user.getId(), ex);
    } finally {
        updateLastLoginTimeForUser(user, currentLoginTime);
        context.success();
    }
}
 
Example 14
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 15
Source File: AdHocAuthenticator.java    From keycloak-extension-playground with Apache License 2.0 5 votes vote down vote up
@Override
public void authenticate(AuthenticationFlowContext context) {

    UserModel user = context.getUser();

    if (user != null) {
        LOG.infof("Pass through: %s%n", user.getUsername());
    } else {
        LOG.infof("Pass through: %s%n", "anonymous");
    }

   context.success();
}
 
Example 16
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 17
Source File: WebAuthnAuthenticator.java    From keycloak with Apache License 2.0 4 votes vote down vote up
public void action(AuthenticationFlowContext context) {
    MultivaluedMap<String, String> params = context.getHttpRequest().getDecodedFormParameters();

    context.getEvent().detail(Details.CREDENTIAL_TYPE, getCredentialType());

    // receive error from navigator.credentials.get()
    String errorMsgFromWebAuthnApi = params.getFirst(WebAuthnConstants.ERROR);
    if (errorMsgFromWebAuthnApi != null && !errorMsgFromWebAuthnApi.isEmpty()) {
        setErrorResponse(context, WEBAUTHN_ERROR_API_GET, errorMsgFromWebAuthnApi);
        return;
    }

    String baseUrl = UriUtils.getOrigin(context.getUriInfo().getBaseUri());
    String rpId = getRpID(context);

    Origin origin = new Origin(baseUrl);
    Challenge challenge = new DefaultChallenge(context.getAuthenticationSession().getAuthNote(WebAuthnConstants.AUTH_CHALLENGE_NOTE));
    ServerProperty server = new ServerProperty(origin, rpId, challenge, null);

    byte[] credentialId = Base64Url.decode(params.getFirst(WebAuthnConstants.CREDENTIAL_ID));
    byte[] clientDataJSON = Base64Url.decode(params.getFirst(WebAuthnConstants.CLIENT_DATA_JSON));
    byte[] authenticatorData = Base64Url.decode(params.getFirst(WebAuthnConstants.AUTHENTICATOR_DATA));
    byte[] signature = Base64Url.decode(params.getFirst(WebAuthnConstants.SIGNATURE));

    final String userHandle = params.getFirst(WebAuthnConstants.USER_HANDLE);
    final String userId;
    // existing User Handle means that the authenticator used Resident Key supported public key credential
    if (userHandle == null || userHandle.isEmpty()) {
        // Resident Key not supported public key credential was used
        // so rely on the user that has already been authenticated
        userId = context.getUser().getId();
    } else {
        // decode using the same charset as it has been encoded (see: WebAuthnRegister.java)
        userId = new String(Base64Url.decode(userHandle), StandardCharsets.UTF_8);
        if (context.getUser() != null) {
            // Resident Key supported public key credential was used,
            // so need to confirm whether the already authenticated user is equals to one authenticated by the webauthn authenticator
            String firstAuthenticatedUserId = context.getUser().getId();
            if (firstAuthenticatedUserId != null && !firstAuthenticatedUserId.equals(userId)) {
                context.getEvent()
                        .detail("first_authenticated_user_id", firstAuthenticatedUserId)
                        .detail("web_authn_authenticator_authenticated_user_id", userId);
                setErrorResponse(context, WEBAUTHN_ERROR_DIFFERENT_USER, null);
                return;
            }
        } else {
            // Resident Key supported public key credential was used,
            // and the user has not yet been identified
            // so rely on the user authenticated by the webauthn authenticator
            // NOP
        }
    }

    boolean isUVFlagChecked = false;
    String userVerificationRequirement = getWebAuthnPolicy(context).getUserVerificationRequirement();
    if (WebAuthnConstants.OPTION_REQUIRED.equals(userVerificationRequirement)) isUVFlagChecked = true;

    UserModel user = session.users().getUserById(userId, context.getRealm());

    AuthenticationRequest authenticationRequest = new AuthenticationRequest(
            credentialId,
            authenticatorData,
            clientDataJSON,
            signature
            );

    AuthenticationParameters authenticationParameters = new AuthenticationParameters(
            server,
            null, // here authenticator cannot be fetched, set it afterwards in WebAuthnCredentialProvider.isValid()
            isUVFlagChecked
            );

    WebAuthnCredentialModelInput cred = new WebAuthnCredentialModelInput(getCredentialType());

    cred.setAuthenticationRequest(authenticationRequest);
    cred.setAuthenticationParameters(authenticationParameters);

    boolean result = false;
    try {
        result = session.userCredentialManager().isValid(context.getRealm(), user, cred);
    } catch (WebAuthnException wae) {
        setErrorResponse(context, WEBAUTHN_ERROR_AUTH_VERIFICATION, wae.getMessage());
        return;
    }
    String encodedCredentialID = Base64Url.encode(credentialId);
    if (result) {
        String isUVChecked = Boolean.toString(isUVFlagChecked);
        logger.debugv("WebAuthn Authentication successed. isUserVerificationChecked = {0}, PublicKeyCredentialID = {1}", isUVChecked, encodedCredentialID);
        context.setUser(user);
        context.getEvent()
            .detail("web_authn_authenticator_user_verification_checked", isUVChecked)
            .detail("public_key_credential_id", encodedCredentialID);
        context.success();
    } else {
        context.getEvent()
            .detail("web_authn_authenticated_user_id", userId)
            .detail("public_key_credential_id", encodedCredentialID);
        setErrorResponse(context, WEBAUTHN_ERROR_USER_NOT_FOUND, null);
        context.cancelLogin();
    }
}
 
Example 18
Source File: WebAuthn4jAuthenticator.java    From keycloak-webauthn-authenticator with Apache License 2.0 4 votes vote down vote up
public void action(AuthenticationFlowContext context) {
    MultivaluedMap<String, String> params = context.getHttpRequest().getDecodedFormParameters();

    // receive error from navigator.credentials.get()
    String error = params.getFirst(WebAuthnConstants.ERROR);
    if (error != null && !error.isEmpty()) {
        throw new AuthenticationFlowException("exception raised from navigator.credentials.get() : " + error, AuthenticationFlowError.INVALID_USER);
    }

    String baseUrl = UriUtils.getOrigin(context.getUriInfo().getBaseUri());
    String rpId = context.getUriInfo().getBaseUri().getHost();

    Origin origin = new Origin(baseUrl);
    Challenge challenge = new DefaultChallenge(context.getAuthenticationSession().getAuthNote(WebAuthnConstants.AUTH_CHALLENGE_NOTE));
    ServerProperty server = new ServerProperty(origin, rpId, challenge, null);

    byte[] credentialId = Base64Url.decode(params.getFirst(WebAuthnConstants.CREDENTIAL_ID));
    byte[] clientDataJSON = Base64Url.decode(params.getFirst(WebAuthnConstants.CLIENT_DATA_JSON));
    byte[] authenticatorData = Base64Url.decode(params.getFirst(WebAuthnConstants.AUTHENTICATOR_DATA));
    byte[] signature = Base64Url.decode(params.getFirst(WebAuthnConstants.SIGNATURE));

    String userId = params.getFirst(WebAuthnConstants.USER_HANDLE);
    boolean isUVFlagChecked = true;
    logger.debugv("userId = {0}", userId);

    if (userId == null || userId.isEmpty()) {
        // in 2 Factor with Resident Key not supported Authenticator Scenario
        userId = context.getUser().getId();
        isUVFlagChecked = false;
    } else {
        if (context.getUser() != null) {
            // in 2 Factor with Resident Key supported Authenticator Scenario
            String firstAuthenticatedUserId = context.getUser().getId();
            logger.debugv("firstAuthenticatedUserId = {0}", firstAuthenticatedUserId);
            if (firstAuthenticatedUserId != null && !firstAuthenticatedUserId.equals(userId)) {
                throw new AuthenticationFlowException("First authenticated user is not the one authenticated by 2nd factor authenticator", AuthenticationFlowError.USER_CONFLICT);
            }
        } else {
            // in Passwordless with Resident Key supported Authenticator Scenario
            // NOP
        }
    }
    UserModel user = session.users().getUserById(userId, context.getRealm());
    WebAuthnAuthenticationContext authenticationContext = new WebAuthnAuthenticationContext(
            credentialId,
            clientDataJSON,
            authenticatorData,
            signature,
            server,
            isUVFlagChecked
    );

    WebAuthnCredentialModel cred = new WebAuthnCredentialModel();
    cred.setAuthenticationContext(authenticationContext);

    boolean result = false;
    try {
        result = session.userCredentialManager().isValid(context.getRealm(), user, cred);
    } catch (Exception e) {
        e.printStackTrace();
        throw new AuthenticationFlowException("unknown user authenticated by the authenticator", AuthenticationFlowError.UNKNOWN_USER);
    }
    if (result) {
        context.setUser(user);
        context.success();
    } else {
        context.cancelLogin();
    }
}
 
Example 19
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 20
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);
}