Search in sources :

Example 6 with UserCredentialModel

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

the class BackwardsCompatibilityUserStorage method updateCredential.

@Override
public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
    if (!(input instanceof UserCredentialModel))
        return false;
    if (input.getType().equals(UserCredentialModel.PASSWORD)) {
        // Compatibility with 4.8.3 - Using "legacy" type PasswordUserCredentialModel
        if (!(input instanceof PasswordUserCredentialModel)) {
            log.warn("Input is not PasswordUserCredentialModel");
            return false;
        }
        PasswordUserCredentialModel userCredentialModel = (PasswordUserCredentialModel) input;
        // Those are not supposed to be set when calling this method in Keycloak 4.8.3 for password credential
        assertNull(userCredentialModel.getDevice());
        assertNull(userCredentialModel.getAlgorithm());
        PasswordPolicy policy = session.getContext().getRealm().getPasswordPolicy();
        PasswordHashProvider hashProvider = getHashProvider(policy);
        CredentialModel newPassword = new CredentialModel();
        newPassword.setType(CredentialModel.PASSWORD);
        long createdDate = Time.currentTimeMillis();
        newPassword.setCreatedDate(createdDate);
        // Compatibility with 4.8.3 - Using "legacy" signature of the method on hashProvider
        hashProvider.encode(userCredentialModel.getValue(), policy.getHashIterations(), newPassword);
        // Test expected values of credentialModel
        assertEquals(newPassword.getAlgorithm(), policy.getHashAlgorithm());
        assertNotNull(newPassword.getValue());
        assertNotNull(newPassword.getSalt());
        users.get(translateUserName(user.getUsername())).hashedPassword = newPassword;
        UserCache userCache = session.userCache();
        if (userCache != null) {
            userCache.evict(realm, user);
        }
        return true;
    } else if (isOTPType(input.getType())) {
        UserCredentialModel otpCredential = (UserCredentialModel) input;
        // Those are not supposed to be set when calling this method in Keycloak 4.8.3 for password credential
        assertNull(otpCredential.getDevice());
        assertNull(otpCredential.getAlgorithm());
        OTPPolicy otpPolicy = session.getContext().getRealm().getOTPPolicy();
        CredentialModel newOTP = new CredentialModel();
        newOTP.setType(input.getType());
        long createdDate = Time.currentTimeMillis();
        newOTP.setCreatedDate(createdDate);
        newOTP.setValue(otpCredential.getValue());
        newOTP.setCounter(otpPolicy.getInitialCounter());
        newOTP.setDigits(otpPolicy.getDigits());
        newOTP.setAlgorithm(otpPolicy.getAlgorithm());
        newOTP.setPeriod(otpPolicy.getPeriod());
        users.get(translateUserName(user.getUsername())).otp = newOTP;
        return true;
    } else {
        log.infof("Attempt to update unsupported credential of type: %s", input.getType());
        return false;
    }
}
Also used : PasswordUserCredentialModel(org.keycloak.models.credential.PasswordUserCredentialModel) PasswordUserCredentialModel(org.keycloak.models.credential.PasswordUserCredentialModel) UserCredentialModel(org.keycloak.models.UserCredentialModel) CredentialModel(org.keycloak.credential.CredentialModel) PasswordPolicy(org.keycloak.models.PasswordPolicy) OTPPolicy(org.keycloak.models.OTPPolicy) UserCache(org.keycloak.models.cache.UserCache) PasswordUserCredentialModel(org.keycloak.models.credential.PasswordUserCredentialModel) UserCredentialModel(org.keycloak.models.UserCredentialModel) PasswordHashProvider(org.keycloak.credential.hash.PasswordHashProvider)

Example 7 with UserCredentialModel

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

the class BackwardsCompatibilityUserStorage method isValid.

@Override
public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) {
    MyUser myUser = users.get(translateUserName(user.getUsername()));
    if (myUser == null)
        return false;
    if (input.getType().equals(UserCredentialModel.PASSWORD)) {
        if (!(input instanceof PasswordUserCredentialModel))
            return false;
        CredentialModel hashedPassword = myUser.hashedPassword;
        if (hashedPassword == null) {
            log.warnf("Password not set for user %s", user.getUsername());
            return false;
        }
        PasswordUserCredentialModel userCredentialModel = (PasswordUserCredentialModel) input;
        // Those are not supposed to be set when calling this method in Keycloak 4.8.3 for password credential
        assertNull(userCredentialModel.getDevice());
        assertNull(userCredentialModel.getAlgorithm());
        PasswordPolicy policy = session.getContext().getRealm().getPasswordPolicy();
        PasswordHashProvider hashProvider = getHashProvider(policy);
        String rawPassword = userCredentialModel.getValue();
        // Compatibility with 4.8.3 - using "legacy" signature of this method
        return hashProvider.verify(rawPassword, hashedPassword);
    } else if (isOTPType(input.getType())) {
        UserCredentialModel otpCredential = (UserCredentialModel) input;
        // Special hardcoded OTP, which is always considered valid
        if ("123456".equals(otpCredential.getValue())) {
            return true;
        }
        CredentialModel storedOTPCredential = myUser.otp;
        if (storedOTPCredential == null) {
            log.warnf("Not found credential for the user %s", user.getUsername());
            return false;
        }
        TimeBasedOTP validator = new TimeBasedOTP(storedOTPCredential.getAlgorithm(), storedOTPCredential.getDigits(), storedOTPCredential.getPeriod(), realm.getOTPPolicy().getLookAheadWindow());
        return validator.validateTOTP(otpCredential.getValue(), storedOTPCredential.getValue().getBytes());
    } else {
        log.infof("Not supported to validate credential of type '%s' for user '%s'", input.getType(), user.getUsername());
        return false;
    }
}
Also used : PasswordUserCredentialModel(org.keycloak.models.credential.PasswordUserCredentialModel) PasswordUserCredentialModel(org.keycloak.models.credential.PasswordUserCredentialModel) UserCredentialModel(org.keycloak.models.UserCredentialModel) CredentialModel(org.keycloak.credential.CredentialModel) TimeBasedOTP(org.keycloak.models.utils.TimeBasedOTP) PasswordPolicy(org.keycloak.models.PasswordPolicy) PasswordUserCredentialModel(org.keycloak.models.credential.PasswordUserCredentialModel) UserCredentialModel(org.keycloak.models.UserCredentialModel) PasswordHashProvider(org.keycloak.credential.hash.PasswordHashProvider)

Example 8 with UserCredentialModel

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

the class LDAPStorageProvider method authenticate.

@Override
public CredentialValidationOutput authenticate(RealmModel realm, CredentialInput cred) {
    if (!(cred instanceof UserCredentialModel))
        CredentialValidationOutput.failed();
    UserCredentialModel credential = (UserCredentialModel) cred;
    if (credential.getType().equals(UserCredentialModel.KERBEROS)) {
        if (kerberosConfig.isAllowKerberosAuthentication()) {
            String spnegoToken = credential.getChallengeResponse();
            SPNEGOAuthenticator spnegoAuthenticator = factory.createSPNEGOAuthenticator(spnegoToken, kerberosConfig);
            spnegoAuthenticator.authenticate();
            Map<String, String> state = new HashMap<String, String>();
            if (spnegoAuthenticator.isAuthenticated()) {
                // TODO: This assumes that LDAP "uid" is equal to kerberos principal name. Like uid "hnelson" and kerberos principal "hnelson@KEYCLOAK.ORG".
                // Check if it's correct or if LDAP attribute for mapping kerberos principal should be available (For ApacheDS it seems to be attribute "krb5PrincipalName" but on MSAD it's likely different)
                String username = spnegoAuthenticator.getAuthenticatedUsername();
                UserModel user = findOrCreateAuthenticatedUser(realm, username);
                if (user == null) {
                    logger.warnf("Kerberos/SPNEGO authentication succeeded with username [%s], but couldn't find or create user with federation provider [%s]", username, model.getName());
                    return CredentialValidationOutput.failed();
                } else {
                    String delegationCredential = spnegoAuthenticator.getSerializedDelegationCredential();
                    if (delegationCredential != null) {
                        state.put(KerberosConstants.GSS_DELEGATION_CREDENTIAL, delegationCredential);
                    }
                    return new CredentialValidationOutput(user, CredentialValidationOutput.Status.AUTHENTICATED, state);
                }
            } else if (spnegoAuthenticator.getResponseToken() != null) {
                // Case when SPNEGO handshake requires multiple steps
                logger.tracef("SPNEGO Handshake will continue");
                state.put(KerberosConstants.RESPONSE_TOKEN, spnegoAuthenticator.getResponseToken());
                return new CredentialValidationOutput(null, CredentialValidationOutput.Status.CONTINUE, state);
            } else {
                logger.tracef("SPNEGO Handshake not successful");
                return CredentialValidationOutput.failed();
            }
        }
    }
    return CredentialValidationOutput.failed();
}
Also used : CachedUserModel(org.keycloak.models.cache.CachedUserModel) UserModel(org.keycloak.models.UserModel) CredentialValidationOutput(org.keycloak.models.CredentialValidationOutput) HashMap(java.util.HashMap) SPNEGOAuthenticator(org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator) UserCredentialModel(org.keycloak.models.UserCredentialModel)

Example 9 with UserCredentialModel

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

the class AccountFormService method processPasswordUpdate.

/**
 * Update account password
 * <p>
 * Form params:
 * <p>
 * password - old password
 * password-new
 * pasword-confirm
 *
 * @return
 */
@Path("password")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processPasswordUpdate() {
    MultivaluedMap<String, String> formData = request.getDecodedFormParameters();
    if (auth == null) {
        return login("password");
    }
    auth.require(AccountRoles.MANAGE_ACCOUNT);
    csrfCheck(formData);
    UserModel user = auth.getUser();
    boolean requireCurrent = isPasswordSet(session, realm, user);
    account.setPasswordSet(requireCurrent);
    String password = formData.getFirst("password");
    String passwordNew = formData.getFirst("password-new");
    String passwordConfirm = formData.getFirst("password-confirm");
    EventBuilder errorEvent = event.clone().event(EventType.UPDATE_PASSWORD_ERROR).client(auth.getClient()).user(auth.getSession().getUser());
    if (requireCurrent) {
        if (Validation.isBlank(password)) {
            setReferrerOnPage();
            errorEvent.error(Errors.PASSWORD_MISSING);
            return account.setError(Status.OK, Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD);
        }
        UserCredentialModel cred = UserCredentialModel.password(password);
        if (!session.userCredentialManager().isValid(realm, user, cred)) {
            setReferrerOnPage();
            errorEvent.error(Errors.INVALID_USER_CREDENTIALS);
            return account.setError(Status.OK, Messages.INVALID_PASSWORD_EXISTING).createResponse(AccountPages.PASSWORD);
        }
    }
    if (Validation.isBlank(passwordNew)) {
        setReferrerOnPage();
        errorEvent.error(Errors.PASSWORD_MISSING);
        return account.setError(Status.OK, Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD);
    }
    if (!passwordNew.equals(passwordConfirm)) {
        setReferrerOnPage();
        errorEvent.error(Errors.PASSWORD_CONFIRM_ERROR);
        return account.setError(Status.OK, Messages.INVALID_PASSWORD_CONFIRM).createResponse(AccountPages.PASSWORD);
    }
    try {
        session.userCredentialManager().updateCredential(realm, user, UserCredentialModel.password(passwordNew, false));
    } catch (ReadOnlyException mre) {
        setReferrerOnPage();
        errorEvent.error(Errors.NOT_ALLOWED);
        return account.setError(Response.Status.BAD_REQUEST, Messages.READ_ONLY_PASSWORD).createResponse(AccountPages.PASSWORD);
    } catch (ModelException me) {
        ServicesLogger.LOGGER.failedToUpdatePassword(me);
        setReferrerOnPage();
        errorEvent.detail(Details.REASON, me.getMessage()).error(Errors.PASSWORD_REJECTED);
        return account.setError(Response.Status.NOT_ACCEPTABLE, me.getMessage(), me.getParameters()).createResponse(AccountPages.PASSWORD);
    } catch (Exception ape) {
        ServicesLogger.LOGGER.failedToUpdatePassword(ape);
        setReferrerOnPage();
        errorEvent.detail(Details.REASON, ape.getMessage()).error(Errors.PASSWORD_REJECTED);
        return account.setError(Response.Status.INTERNAL_SERVER_ERROR, ape.getMessage()).createResponse(AccountPages.PASSWORD);
    }
    session.sessions().getUserSessionsStream(realm, user).filter(s -> !Objects.equals(s.getId(), auth.getSession().getId())).collect(// collect to avoid concurrent modification as backchannelLogout removes the user sessions.
    Collectors.toList()).forEach(s -> AuthenticationManager.backchannelLogout(session, realm, s, session.getContext().getUri(), clientConnection, headers, true));
    event.event(EventType.UPDATE_PASSWORD).client(auth.getClient()).user(auth.getUser()).success();
    setReferrerOnPage();
    return account.setPasswordSet(true).setSuccess(Messages.ACCOUNT_PASSWORD_UPDATED).createResponse(AccountPages.PASSWORD);
}
Also used : UserModel(org.keycloak.models.UserModel) EventBuilder(org.keycloak.events.EventBuilder) ModelException(org.keycloak.models.ModelException) UserCredentialModel(org.keycloak.models.UserCredentialModel) ReadOnlyException(org.keycloak.storage.ReadOnlyException) ReadOnlyException(org.keycloak.storage.ReadOnlyException) NotFoundException(javax.ws.rs.NotFoundException) ForbiddenException(org.keycloak.services.ForbiddenException) IOException(java.io.IOException) ModelException(org.keycloak.models.ModelException) ValidationException(org.keycloak.userprofile.ValidationException) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes)

Example 10 with UserCredentialModel

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

the class ClientResource method getClientSecret.

/**
 * Get the client secret
 *
 * @return
 */
@Path("client-secret")
@GET
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public CredentialRepresentation getClientSecret() {
    auth.clients().requireView(client);
    logger.debug("getClientSecret");
    UserCredentialModel model = UserCredentialModel.secret(client.getSecret());
    if (model == null)
        throw new NotFoundException("Client does not have a secret");
    return ModelToRepresentation.toRepresentation(model);
}
Also used : NotFoundException(javax.ws.rs.NotFoundException) UserCredentialModel(org.keycloak.models.UserCredentialModel) Path(javax.ws.rs.Path) Produces(javax.ws.rs.Produces) GET(javax.ws.rs.GET) NoCache(org.jboss.resteasy.annotations.cache.NoCache)

Aggregations

UserCredentialModel (org.keycloak.models.UserCredentialModel)20 UserModel (org.keycloak.models.UserModel)8 CredentialModel (org.keycloak.credential.CredentialModel)5 Response (javax.ws.rs.core.Response)4 OTPCredentialModel (org.keycloak.models.credential.OTPCredentialModel)4 PasswordHashProvider (org.keycloak.credential.hash.PasswordHashProvider)3 CredentialValidationOutput (org.keycloak.models.CredentialValidationOutput)3 PasswordPolicy (org.keycloak.models.PasswordPolicy)3 RealmModel (org.keycloak.models.RealmModel)3 CachedUserModel (org.keycloak.models.cache.CachedUserModel)3 HashMap (java.util.HashMap)2 NotFoundException (javax.ws.rs.NotFoundException)2 Path (javax.ws.rs.Path)2 Test (org.junit.Test)2 SPNEGOAuthenticator (org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator)2 OTPPolicy (org.keycloak.models.OTPPolicy)2 UserCache (org.keycloak.models.cache.UserCache)2 PasswordCredentialModel (org.keycloak.models.credential.PasswordCredentialModel)2 PasswordUserCredentialModel (org.keycloak.models.credential.PasswordUserCredentialModel)2 TimeBasedOTP (org.keycloak.models.utils.TimeBasedOTP)2