Java Code Examples for org.keycloak.models.UserModel#isEnabled()

The following examples show how to use org.keycloak.models.UserModel#isEnabled() . 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: AbstractIdpAuthenticator.java    From keycloak with Apache License 2.0 6 votes vote down vote up
public static UserModel getExistingUser(KeycloakSession session, RealmModel realm, AuthenticationSessionModel authSession) {
    String existingUserId = authSession.getAuthNote(EXISTING_USER_INFO);
    if (existingUserId == null) {
        throw new AuthenticationFlowException("Unexpected state. There is no existing duplicated user identified in ClientSession",
                AuthenticationFlowError.INTERNAL_ERROR);
    }

    ExistingUserInfo duplication = ExistingUserInfo.deserialize(existingUserId);

    UserModel existingUser = session.users().getUserById(duplication.getExistingUserId(), realm);
    if (existingUser == null) {
        throw new AuthenticationFlowException("User with ID '" + existingUserId + "' not found.", AuthenticationFlowError.INVALID_USER);
    }

    if (!existingUser.isEnabled()) {
        throw new AuthenticationFlowException("User with ID '" + existingUserId + "', username '" + existingUser.getUsername() + "' disabled.", AuthenticationFlowError.USER_DISABLED);
    }

    return existingUser;
}
 
Example 2
Source File: MSADLDSUserAccountControlStorageMapper.java    From keycloak with Apache License 2.0 6 votes vote down vote up
@Override
public void passwordUpdated(UserModel user, LDAPObject ldapUser, UserCredentialModel password) {
    logger.debugf("Going to update pwdLastSet for ldap user '%s' after successful password update", ldapUser.getDn().toString());

    // Normally it's read-only
    ldapUser.removeReadOnlyAttributeName(LDAPConstants.PWD_LAST_SET);

    ldapUser.setSingleAttribute(LDAPConstants.PWD_LAST_SET, "-1");
    
    if (user.isEnabled()) {
        // TODO: Use removeAttribute once available
        ldapUser.setSingleAttribute(LDAPConstants.MSDS_USER_ACCOUNT_DISABLED, "FALSE");
        logger.debugf("Removing msDS-UserPasswordExpired of user '%s'", ldapUser.getDn().toString());
    }

    ldapProvider.getLdapIdentityStore().update(ldapUser);
}
 
Example 3
Source File: MSADUserAccountControlStorageMapper.java    From keycloak with Apache License 2.0 6 votes vote down vote up
protected boolean processAuthErrorCode(String errorCode, UserModel user) {
    logger.debugf("MSAD Error code is '%s' after failed LDAP login of user '%s'", errorCode, user.getUsername());

    if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE) {
        if (errorCode.equals("532") || errorCode.equals("773")) {
            // User needs to change his MSAD password. Allow him to login, but add UPDATE_PASSWORD required action
            if (!user.getRequiredActions().contains(UserModel.RequiredAction.UPDATE_PASSWORD.name())) {
                user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
            }
            return true;
        } else if (errorCode.equals("533")) {
            // User is disabled in MSAD. Set him to disabled in KC as well
            if (user.isEnabled()) {
                user.setEnabled(false);
            }
            return true;
        } else if (errorCode.equals("775")) {
            logger.warnf("Locked user '%s' attempt to login", user.getUsername());
        }
    }

    return false;
}
 
Example 4
Source File: MSADUserAccountControlStorageMapper.java    From keycloak with Apache License 2.0 6 votes vote down vote up
@Override
public void passwordUpdated(UserModel user, LDAPObject ldapUser, UserCredentialModel password) {
    logger.debugf("Going to update userAccountControl for ldap user '%s' after successful password update", ldapUser.getDn().toString());

    // Normally it's read-only
    ldapUser.removeReadOnlyAttributeName(LDAPConstants.PWD_LAST_SET);

    ldapUser.setSingleAttribute(LDAPConstants.PWD_LAST_SET, "-1");

    UserAccountControl control = getUserAccountControl(ldapUser);
    control.remove(UserAccountControl.PASSWD_NOTREQD);
    control.remove(UserAccountControl.PASSWORD_EXPIRED);

    if (user.isEnabled()) {
        control.remove(UserAccountControl.ACCOUNTDISABLE);
    }

    updateUserAccountControl(true, ldapUser, control);
}
 
Example 5
Source File: MSADLDSUserAccountControlStorageMapper.java    From keycloak with Apache License 2.0 6 votes vote down vote up
protected boolean processAuthErrorCode(String errorCode, UserModel user) {
    logger.debugf("MSAD LDS Error code is '%s' after failed LDAP login of user '%s'", errorCode, user.getUsername());

    if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE) {
        if (errorCode.equals("532") || errorCode.equals("773")) {
            // User needs to change his MSAD password. Allow him to login, but add UPDATE_PASSWORD required action
            if (!user.getRequiredActions().contains(UserModel.RequiredAction.UPDATE_PASSWORD.name())) {
                user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
            }
            return true;
        } else if (errorCode.equals("533")) {
            // User is disabled in MSAD LDS. Set him to disabled in KC as well
            if (user.isEnabled()) {
                user.setEnabled(false);
            }
            return true;
        } else if (errorCode.equals("775")) {
            logger.warnf("Locked user '%s' attempt to login", user.getUsername());
        }
    }

    return false;
}
 
Example 6
Source File: TokenManager.java    From keycloak with Apache License 2.0 6 votes vote down vote up
private boolean isUserValid(KeycloakSession session, RealmModel realm, AccessToken token, UserSessionModel userSession) {
    UserModel user = userSession.getUser();
    if (user == null) {
        return false;
    }
    if (!user.isEnabled()) {
        return false;
    }
    try {
        TokenVerifier.createWithoutSignature(token)
                .withChecks(NotBeforeCheck.forModel(session ,realm, user))
                .verify();
    } catch (VerificationException e) {
        return false;
    }

    if (token.getIssuedAt() + 1 < userSession.getStarted()) {
        return false;
    }
    return true;
}
 
Example 7
Source File: CachedUser.java    From keycloak with Apache License 2.0 6 votes vote down vote up
public CachedUser(Long revision, RealmModel realm, UserModel user, int notBefore) {
    super(revision, user.getId());
    this.realm = realm.getId();
    this.username = user.getUsername();
    this.createdTimestamp = user.getCreatedTimestamp();
    this.email = user.getEmail();
    this.emailVerified = user.isEmailVerified();
    this.enabled = user.isEnabled();
    this.federationLink = user.getFederationLink();
    this.serviceAccountClientLink = user.getServiceAccountClientLink();
    this.notBefore = notBefore;
    this.requiredActions = new DefaultLazyLoader<>(UserModel::getRequiredActions, Collections::emptySet);
    this.attributes = new DefaultLazyLoader<>(userModel -> new MultivaluedHashMap<>(userModel.getAttributes()), MultivaluedHashMap::new);
    this.roleMappings = new DefaultLazyLoader<>(userModel -> userModel.getRoleMappings().stream().map(RoleModel::getId).collect(Collectors.toSet()), Collections::emptySet);
    this.groups = new DefaultLazyLoader<>(userModel -> userModel.getGroups().stream().map(GroupModel::getId).collect(Collectors.toCollection(LinkedHashSet::new)), LinkedHashSet::new);
}
 
Example 8
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 9
Source File: AuthorizationEndpointBase.java    From keycloak with Apache License 2.0 5 votes vote down vote up
protected AuthenticationSessionModel createAuthenticationSession(ClientModel client, String requestState) {
    AuthenticationSessionManager manager = new AuthenticationSessionManager(session);
    RootAuthenticationSessionModel rootAuthSession = manager.getCurrentRootAuthenticationSession(realm);

    AuthenticationSessionModel authSession;

    if (rootAuthSession != null) {
        authSession = rootAuthSession.createAuthenticationSession(client);

        logger.debugf("Sent request to authz endpoint. Root authentication session with ID '%s' exists. Client is '%s' . Created new authentication session with tab ID: %s",
                rootAuthSession.getId(), client.getClientId(), authSession.getTabId());
    } else {
        UserSessionCrossDCManager userSessionCrossDCManager = new UserSessionCrossDCManager(session);
        UserSessionModel userSession = userSessionCrossDCManager.getUserSessionIfExistsRemotely(manager, realm);

        if (userSession != null) {
            UserModel user = userSession.getUser();
            if (user != null && !user.isEnabled()) {
                authSession = createNewAuthenticationSession(manager, client);

                AuthenticationManager.backchannelLogout(session, userSession, true);
            } else {
                String userSessionId = userSession.getId();
                rootAuthSession = session.authenticationSessions().createRootAuthenticationSession(userSessionId, realm);
                authSession = rootAuthSession.createAuthenticationSession(client);
                logger.debugf("Sent request to authz endpoint. We don't have root authentication session with ID '%s' but we have userSession." +
                        "Re-created root authentication session with same ID. Client is: %s . New authentication session tab ID: %s", userSessionId, client.getClientId(), authSession.getTabId());
            }
        } else {
            authSession = createNewAuthenticationSession(manager, client);
        }
    }

    session.getProvider(LoginFormsProvider.class).setAuthenticationSession(authSession);

    return authSession;

}
 
Example 10
Source File: LoginFormsUtil.java    From keycloak with Apache License 2.0 5 votes vote down vote up
public static List<IdentityProviderModel> filterIdentityProvidersByUser(List<IdentityProviderModel> providers, KeycloakSession session, RealmModel realm,
                                                                  Map<String, Object> attributes, MultivaluedMap<String, String> formData) {

    Boolean usernameEditDisabled = (Boolean) attributes.get(LoginFormsProvider.USERNAME_EDIT_DISABLED);
    if (usernameEditDisabled != null && usernameEditDisabled) {
        String username = formData.getFirst(UserModel.USERNAME);
        if (username == null) {
            throw new IllegalStateException("USERNAME_EDIT_DISABLED but username not known");
        }

        UserModel user = session.users().getUserByUsername(username, realm);
        if (user == null || !user.isEnabled()) {
            throw new IllegalStateException("User " + username + " not found or disabled");
        }

        Set<FederatedIdentityModel> fedLinks = session.users().getFederatedIdentities(user, realm);
        Set<String> federatedIdentities = new HashSet<>();
        for (FederatedIdentityModel fedLink : fedLinks) {
            federatedIdentities.add(fedLink.getIdentityProvider());
        }

        List<IdentityProviderModel> result = new LinkedList<>();
        for (IdentityProviderModel idp : providers) {
            if (federatedIdentities.contains(idp.getAlias())) {
                result.add(idp);
            }
        }
        return result;
    } else {
        return providers;
    }
}
 
Example 11
Source File: X509ClientCertificateAuthenticator.java    From keycloak with Apache License 2.0 5 votes vote down vote up
private boolean userEnabled(AuthenticationFlowContext context, UserModel user) {
    if (!user.isEnabled()) {
        context.getEvent().user(user);
        context.getEvent().error(Errors.USER_DISABLED);
        return false;
    }
    return true;
}
 
Example 12
Source File: AbstractUsernameFormAuthenticator.java    From keycloak with Apache License 2.0 5 votes vote down vote up
public boolean enabledUser(AuthenticationFlowContext context, UserModel user) {
    if (!user.isEnabled()) {
        context.getEvent().user(user);
        context.getEvent().error(Errors.USER_DISABLED);
        Response challengeResponse = challenge(context, Messages.ACCOUNT_DISABLED);
        context.forceChallenge(challengeResponse);
        return false;
    }
    if (isTemporarilyDisabledByBruteForce(context, user)) return false;
    return true;
}
 
Example 13
Source File: IdentityBrokerService.java    From keycloak with Apache License 2.0 5 votes vote down vote up
public Response validateUser(AuthenticationSessionModel authSession, UserModel user, RealmModel realm) {
    if (!user.isEnabled()) {
        event.error(Errors.USER_DISABLED);
        return ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, Messages.ACCOUNT_DISABLED);
    }
    if (realm.isBruteForceProtected()) {
        if (session.getProvider(BruteForceProtector.class).isTemporarilyDisabled(session, realm, user)) {
            event.error(Errors.USER_TEMPORARILY_DISABLED);
            return ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, Messages.ACCOUNT_DISABLED);
        }
    }
    return null;
}
 
Example 14
Source File: CrossRealmClientAuthMapper.java    From keycloak-extension-playground with Apache License 2.0 4 votes vote down vote up
private Object fetchCrossRealmData(KeycloakSession session) {


        RealmModel targetRealm = session.realms().getRealmByName("services-demo");
        ClientModel serviceClient = targetRealm.getClientByClientId("simple-service");
        if (!serviceClient.isServiceAccountsEnabled()) {
            return null;
        }
        String loopback = "127.0.0.1";
        EventBuilder event = new EventBuilder(targetRealm, session, new ClientConnection() {
            public String getRemoteAddr() {
                return loopback;
            }

            public String getRemoteHost() {
                return loopback;
            }

            public int getRemotePort() {
                return 8080;
            }

            public String getLocalAddr() {
                return loopback;
            }

            public int getLocalPort() {
                return 8080;
            }
        });

        UserModel serviceAccountUser = session.users().getServiceAccount(serviceClient);
        if (!serviceAccountUser.isEnabled()) {
            return null;
        }

        RootAuthenticationSessionModel rootAuthSession = new AuthenticationSessionManager(session).createAuthenticationSession(targetRealm, false);
        AuthenticationSessionModel authSession = rootAuthSession.createAuthenticationSession(serviceClient);
        authSession.setAuthenticatedUser(serviceAccountUser);
        authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
        authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(session.getContext().getUri().getBaseUri(), targetRealm.getName()));
        authSession.setClientNote(OIDCLoginProtocol.SCOPE_PARAM, "openid profile roles");
        UserSessionModel serviceAccountUserSession = session.sessions().createUserSession(authSession.getParentSession().getId(), targetRealm, serviceAccountUser, serviceAccountUser.getUsername(),
                loopback, ServiceAccountConstants.CLIENT_AUTH, false, null, null);
        AuthenticationManager.setClientScopesInSession(authSession);
        ClientSessionContext clientSessionContext = TokenManager.attachAuthenticationSession(session, serviceAccountUserSession, authSession);

        // Notes about serviceClient details
        serviceAccountUserSession.setNote(ServiceAccountConstants.CLIENT_ID, serviceClient.getClientId());
        serviceAccountUserSession.setNote(ServiceAccountConstants.CLIENT_HOST, loopback);
        serviceAccountUserSession.setNote(ServiceAccountConstants.CLIENT_ADDRESS, loopback);

        TokenManager tokenManager = new TokenManager();
        TokenManager.AccessTokenResponseBuilder responseBuilder = tokenManager.responseBuilder(targetRealm, serviceClient, event, session, serviceAccountUserSession, clientSessionContext)
                .generateAccessToken();

        AccessTokenResponse accessTokenResponse = responseBuilder.build();

        String accessToken = accessTokenResponse.getToken();

        LOGGER.infof("AccessToken: %s", accessToken);

        return null;
    }
 
Example 15
Source File: ResetCredentialChooseUser.java    From keycloak with Apache License 2.0 4 votes vote down vote up
@Override
public void action(AuthenticationFlowContext context) {
    EventBuilder event = context.getEvent();
    MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
    String username = formData.getFirst("username");
    if (username == null || username.isEmpty()) {
        event.error(Errors.USERNAME_MISSING);
        Response challenge = context.form()
                .setError(Messages.MISSING_USERNAME)
                .createPasswordReset();
        context.failureChallenge(AuthenticationFlowError.INVALID_USER, challenge);
        return;
    }

    username = username.trim();
    
    RealmModel realm = context.getRealm();
    UserModel user = context.getSession().users().getUserByUsername(username, realm);
    if (user == null && realm.isLoginWithEmailAllowed() && username.contains("@")) {
        user =  context.getSession().users().getUserByEmail(username, realm);
    }

    context.getAuthenticationSession().setAuthNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME, username);

    // we don't want people guessing usernames, so if there is a problem, just continue, but don't set the user
    // a null user will notify further executions, that this was a failure.
    if (user == null) {
        event.clone()
                .detail(Details.USERNAME, username)
                .error(Errors.USER_NOT_FOUND);
        context.clearUser();
    } else if (!user.isEnabled()) {
        event.clone()
                .detail(Details.USERNAME, username)
                .user(user).error(Errors.USER_DISABLED);
        context.clearUser();
    } else {
        context.setUser(user);
    }

    context.success();
}
 
Example 16
Source File: AuthenticationProcessor.java    From keycloak with Apache License 2.0 4 votes vote down vote up
public void validateUser(UserModel authenticatedUser) {
    if (authenticatedUser == null) return;
    if (!authenticatedUser.isEnabled()) throw new AuthenticationFlowException(AuthenticationFlowError.USER_DISABLED);
    if (authenticatedUser.getServiceAccountClientLink() != null) throw new AuthenticationFlowException(AuthenticationFlowError.UNKNOWN_USER);
}
 
Example 17
Source File: IdentityBrokerService.java    From keycloak with Apache License 2.0 4 votes vote down vote up
private Response performAccountLinking(AuthenticationSessionModel authSession, UserSessionModel userSession, BrokeredIdentityContext context, FederatedIdentityModel newModel, UserModel federatedUser) {
    logger.debugf("Will try to link identity provider [%s] to user [%s]", context.getIdpConfig().getAlias(), userSession.getUser().getUsername());

    this.event.event(EventType.FEDERATED_IDENTITY_LINK);



    UserModel authenticatedUser = userSession.getUser();
    authSession.setAuthenticatedUser(authenticatedUser);

    if (federatedUser != null && !authenticatedUser.getId().equals(federatedUser.getId())) {
        return redirectToErrorWhenLinkingFailed(authSession, Messages.IDENTITY_PROVIDER_ALREADY_LINKED, context.getIdpConfig().getAlias());
    }

    if (!authenticatedUser.hasRole(this.realmModel.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID).getRole(AccountRoles.MANAGE_ACCOUNT))) {
        return redirectToErrorPage(authSession, Response.Status.FORBIDDEN, Messages.INSUFFICIENT_PERMISSION);
    }

    if (!authenticatedUser.isEnabled()) {
        return redirectToErrorWhenLinkingFailed(authSession, Messages.ACCOUNT_DISABLED);
    }



    if (federatedUser != null) {
        if (context.getIdpConfig().isStoreToken()) {
            FederatedIdentityModel oldModel = this.session.users().getFederatedIdentity(federatedUser, context.getIdpConfig().getAlias(), this.realmModel);
            if (!ObjectUtil.isEqualOrBothNull(context.getToken(), oldModel.getToken())) {
                this.session.users().updateFederatedIdentity(this.realmModel, federatedUser, newModel);
                if (isDebugEnabled()) {
                    logger.debugf("Identity [%s] update with response from identity provider [%s].", federatedUser, context.getIdpConfig().getAlias());
                }
            }
        }
    } else {
        this.session.users().addFederatedIdentity(this.realmModel, authenticatedUser, newModel);
    }
    context.getIdp().authenticationFinished(authSession, context);

    AuthenticationManager.setClientScopesInSession(authSession);
    TokenManager.attachAuthenticationSession(session, userSession, authSession);

    if (isDebugEnabled()) {
        logger.debugf("Linking account [%s] from identity provider [%s] to user [%s].", newModel, context.getIdpConfig().getAlias(), authenticatedUser);
    }

    this.event.user(authenticatedUser)
            .detail(Details.USERNAME, authenticatedUser.getUsername())
            .detail(Details.IDENTITY_PROVIDER, newModel.getIdentityProvider())
            .detail(Details.IDENTITY_PROVIDER_USERNAME, newModel.getUserName())
            .success();

    // we do this to make sure that the parent IDP is logged out when this user session is complete.
    // But for the case when userSession was previously authenticated with broker1 and now is linked to another broker2, we shouldn't override broker1 notes with the broker2 for sure.
    // Maybe broker logout should be rather always skiped in case of broker-linking
    if (userSession.getNote(Details.IDENTITY_PROVIDER) == null) {
        userSession.setNote(Details.IDENTITY_PROVIDER, context.getIdpConfig().getAlias());
        userSession.setNote(Details.IDENTITY_PROVIDER_USERNAME, context.getUsername());
    }

    return Response.status(302).location(UriBuilder.fromUri(authSession.getRedirectUri()).build()).build();
}
 
Example 18
Source File: AccountFormService.java    From keycloak with Apache License 2.0 4 votes vote down vote up
@Path("identity")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processFederatedIdentityUpdate(final MultivaluedMap<String, String> formData) {
    if (auth == null) {
        return login("identity");
    }

    auth.require(AccountRoles.MANAGE_ACCOUNT);
    csrfCheck(formData);
    UserModel user = auth.getUser();

    String action = formData.getFirst("action");
    String providerId = formData.getFirst("providerId");

    if (Validation.isEmpty(providerId)) {
        setReferrerOnPage();
        return account.setError(Status.OK, Messages.MISSING_IDENTITY_PROVIDER).createResponse(AccountPages.FEDERATED_IDENTITY);
    }
    AccountSocialAction accountSocialAction = AccountSocialAction.getAction(action);
    if (accountSocialAction == null) {
        setReferrerOnPage();
        return account.setError(Status.OK, Messages.INVALID_FEDERATED_IDENTITY_ACTION).createResponse(AccountPages.FEDERATED_IDENTITY);
    }

    boolean hasProvider = false;

    for (IdentityProviderModel model : realm.getIdentityProviders()) {
        if (model.getAlias().equals(providerId)) {
            hasProvider = true;
        }
    }

    if (!hasProvider) {
        setReferrerOnPage();
        return account.setError(Status.OK, Messages.IDENTITY_PROVIDER_NOT_FOUND).createResponse(AccountPages.FEDERATED_IDENTITY);
    }

    if (!user.isEnabled()) {
        setReferrerOnPage();
        return account.setError(Status.OK, Messages.ACCOUNT_DISABLED).createResponse(AccountPages.FEDERATED_IDENTITY);
    }

    switch (accountSocialAction) {
        case ADD:
            String redirectUri = UriBuilder.fromUri(Urls.accountFederatedIdentityPage(session.getContext().getUri().getBaseUri(), realm.getName())).build().toString();

            try {
                String nonce = UUID.randomUUID().toString();
                MessageDigest md = MessageDigest.getInstance("SHA-256");
                String input = nonce + auth.getSession().getId() + client.getClientId() + providerId;
                byte[] check = md.digest(input.getBytes(StandardCharsets.UTF_8));
                String hash = Base64Url.encode(check);
                URI linkUrl = Urls.identityProviderLinkRequest(this.session.getContext().getUri().getBaseUri(), providerId, realm.getName());
                linkUrl = UriBuilder.fromUri(linkUrl)
                        .queryParam("nonce", nonce)
                        .queryParam("hash", hash)
                        .queryParam("client_id", client.getClientId())
                        .queryParam("redirect_uri", redirectUri)
                        .build();
                return Response.seeOther(linkUrl)
                        .build();
            } catch (Exception spe) {
                setReferrerOnPage();
                return account.setError(Response.Status.INTERNAL_SERVER_ERROR, Messages.IDENTITY_PROVIDER_REDIRECT_ERROR).createResponse(AccountPages.FEDERATED_IDENTITY);
            }
        case REMOVE:
            FederatedIdentityModel link = session.users().getFederatedIdentity(user, providerId, realm);
            if (link != null) {

                // Removing last social provider is not possible if you don't have other possibility to authenticate
                if (session.users().getFederatedIdentities(user, realm).size() > 1 || user.getFederationLink() != null || isPasswordSet(session, realm, user)) {
                    session.users().removeFederatedIdentity(realm, user, providerId);

                    logger.debugv("Social provider {0} removed successfully from user {1}", providerId, user.getUsername());

                    event.event(EventType.REMOVE_FEDERATED_IDENTITY).client(auth.getClient()).user(auth.getUser())
                            .detail(Details.USERNAME, auth.getUser().getUsername())
                            .detail(Details.IDENTITY_PROVIDER, link.getIdentityProvider())
                            .detail(Details.IDENTITY_PROVIDER_USERNAME, link.getUserName())
                            .success();

                    setReferrerOnPage();
                    return account.setSuccess(Messages.IDENTITY_PROVIDER_REMOVED).createResponse(AccountPages.FEDERATED_IDENTITY);
                } else {
                    setReferrerOnPage();
                    return account.setError(Status.OK, Messages.FEDERATED_IDENTITY_REMOVING_LAST_PROVIDER).createResponse(AccountPages.FEDERATED_IDENTITY);
                }
            } else {
                setReferrerOnPage();
                return account.setError(Status.OK, Messages.FEDERATED_IDENTITY_NOT_ACTIVE).createResponse(AccountPages.FEDERATED_IDENTITY);
            }
        default:
            throw new IllegalArgumentException();
    }
}
 
Example 19
Source File: AuthenticationManager.java    From keycloak with Apache License 2.0 4 votes vote down vote up
public static AuthResult verifyIdentityToken(KeycloakSession session, RealmModel realm, UriInfo uriInfo, ClientConnection connection, boolean checkActive, boolean checkTokenType,
                                                boolean isCookie, String tokenString, HttpHeaders headers, Predicate<? super AccessToken>... additionalChecks) {
    try {
        TokenVerifier<AccessToken> verifier = TokenVerifier.create(tokenString, AccessToken.class)
          .withDefaultChecks()
          .realmUrl(Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()))
          .checkActive(checkActive)
          .checkTokenType(checkTokenType)
          .withChecks(additionalChecks);
        String kid = verifier.getHeader().getKeyId();
        String algorithm = verifier.getHeader().getAlgorithm().name();

        SignatureVerifierContext signatureVerifier = session.getProvider(SignatureProvider.class, algorithm).verifier(kid);
        verifier.verifierContext(signatureVerifier);

        AccessToken token = verifier.verify().getToken();
        if (checkActive) {
            if (!token.isActive() || token.getIssuedAt() < realm.getNotBefore()) {
                logger.debug("Identity cookie expired");
                return null;
            }
        }

        UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState());
        UserModel user = null;
        if (userSession != null) {
            user = userSession.getUser();
            if (user == null || !user.isEnabled()) {
                logger.debug("Unknown user in identity token");
                return null;
            }

            int userNotBefore = session.users().getNotBeforeOfUser(realm, user);
            if (token.getIssuedAt() < userNotBefore) {
                logger.debug("User notBefore newer than token");
                return null;
            }
        }

        if (!isSessionValid(realm, userSession)) {
            // Check if accessToken was for the offline session.
            if (!isCookie) {
                UserSessionModel offlineUserSession = session.sessions().getOfflineUserSession(realm, token.getSessionState());
                if (isOfflineSessionValid(realm, offlineUserSession)) {
                    user = offlineUserSession.getUser();
                    return new AuthResult(user, offlineUserSession, token);
                }
            }

            if (userSession != null) backchannelLogout(session, realm, userSession, uriInfo, connection, headers, true);
            logger.debug("User session not active");
            return null;
        }

        session.setAttribute("state_checker", token.getOtherClaims().get("state_checker"));

        return new AuthResult(user, userSession, token);
    } catch (VerificationException e) {
        logger.debugf("Failed to verify identity token: %s", e.getMessage());
    }
    return null;
}
 
Example 20
Source File: TokenManager.java    From keycloak with Apache License 2.0 4 votes vote down vote up
public TokenValidation validateToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm,
                                     RefreshToken oldToken, HttpHeaders headers) throws OAuthErrorException {
    UserSessionModel userSession = null;
    boolean offline = TokenUtil.TOKEN_TYPE_OFFLINE.equals(oldToken.getType());

    if (offline) {

        UserSessionManager sessionManager = new UserSessionManager(session);
        userSession = sessionManager.findOfflineUserSession(realm, oldToken.getSessionState());
        if (userSession != null) {

            // Revoke timeouted offline userSession
            if (!AuthenticationManager.isOfflineSessionValid(realm, userSession)) {
                sessionManager.revokeOfflineUserSession(userSession);
                throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline session not active", "Offline session not active");
            }

        } else {
            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline user session not found", "Offline user session not found");
        }
    } else {
        // Find userSession regularly for online tokens
        userSession = session.sessions().getUserSession(realm, oldToken.getSessionState());
        if (!AuthenticationManager.isSessionValid(realm, userSession)) {
            AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, connection, headers, true);
            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session not active", "Session not active");
        }
    }

    UserModel user = userSession.getUser();
    if (user == null) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", "Unknown user");
    }

    if (!user.isEnabled()) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "User disabled", "User disabled");
    }

    if (oldToken.getIssuedAt() + 1 < userSession.getStarted()) {
        logger.debug("Refresh toked issued before the user session started");
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Refresh toked issued before the user session started");
    }


    ClientModel client = session.getContext().getClient();
    AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());

    // Can theoretically happen in cross-dc environment. Try to see if userSession with our client is available in remoteCache
    if (clientSession == null) {
        userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, userSession.getId(), offline, client.getId());
        if (userSession != null) {
            clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
        } else {
            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session doesn't have required client", "Session doesn't have required client");
        }
    }

    if (!client.getClientId().equals(oldToken.getIssuedFor())) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Unmatching clients", "Unmatching clients");
    }

    try {
        TokenVerifier.createWithoutSignature(oldToken)
                .withChecks(NotBeforeCheck.forModel(client), NotBeforeCheck.forModel(session, realm, user))
                .verify();
    } catch (VerificationException e) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
    }

    // Setup clientScopes from refresh token to the context
    String oldTokenScope = oldToken.getScope();

    // Case when offline token is migrated from previous version
    if (oldTokenScope == null && userSession.isOffline()) {
        logger.debugf("Migrating offline token of user '%s' for client '%s' of realm '%s'", user.getUsername(), client.getClientId(), realm.getName());
        MigrationUtils.migrateOldOfflineToken(session, realm, client, user);
        oldTokenScope = OAuth2Constants.OFFLINE_ACCESS;
    }

    ClientSessionContext clientSessionCtx = DefaultClientSessionContext.fromClientSessionAndScopeParameter(clientSession, oldTokenScope, session);

    // Check user didn't revoke granted consent
    if (!verifyConsentStillAvailable(session, user, client, clientSessionCtx.getClientScopes())) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "Client no longer has requested consent from user");
    }

    clientSessionCtx.setAttribute(OIDCLoginProtocol.NONCE_PARAM, oldToken.getNonce());

    // recreate token.
    AccessToken newToken = createClientAccessToken(session, realm, client, user, userSession, clientSessionCtx);

    return new TokenValidation(user, userSession, clientSessionCtx, newToken);
}