use of org.keycloak.models.PasswordPolicy in project keycloak by keycloak.
the class HistoryPasswordPolicyProvider method validate.
@Override
public PolicyError validate(RealmModel realm, UserModel user, String password) {
PasswordPolicy policy = session.getContext().getRealm().getPasswordPolicy();
int passwordHistoryPolicyValue = policy.getPolicyConfig(PasswordPolicy.PASSWORD_HISTORY_ID);
if (passwordHistoryPolicyValue != -1) {
if (session.userCredentialManager().getStoredCredentialsByTypeStream(realm, user, PasswordCredentialModel.TYPE).map(PasswordCredentialModel::createFromCredentialModel).anyMatch(passwordCredential -> {
PasswordHashProvider hash = session.getProvider(PasswordHashProvider.class, passwordCredential.getPasswordCredentialData().getAlgorithm());
return hash != null && hash.verify(password, passwordCredential);
})) {
return new PolicyError(ERROR_MESSAGE, passwordHistoryPolicyValue);
}
if (passwordHistoryPolicyValue > 0) {
if (this.getRecent(session.userCredentialManager().getStoredCredentialsByTypeStream(realm, user, PasswordCredentialModel.PASSWORD_HISTORY), passwordHistoryPolicyValue - 1).map(PasswordCredentialModel::createFromCredentialModel).anyMatch(passwordCredential -> {
PasswordHashProvider hash = session.getProvider(PasswordHashProvider.class, passwordCredential.getPasswordCredentialData().getAlgorithm());
return hash.verify(password, passwordCredential);
})) {
return new PolicyError(ERROR_MESSAGE, passwordHistoryPolicyValue);
}
}
}
return null;
}
use of org.keycloak.models.PasswordPolicy in project keycloak by keycloak.
the class DefaultPasswordPolicyManagerProvider method getProviders.
private List<PasswordPolicyProvider> getProviders(RealmModel realm, KeycloakSession session) {
LinkedList<PasswordPolicyProvider> list = new LinkedList<>();
PasswordPolicy policy = realm.getPasswordPolicy();
for (String id : policy.getPolicies()) {
PasswordPolicyProvider provider = session.getProvider(PasswordPolicyProvider.class, id);
list.add(provider);
}
return list;
}
use of org.keycloak.models.PasswordPolicy in project keycloak by keycloak.
the class PasswordPolicyTest method testRegexPatterns.
@Test
public void testRegexPatterns() {
testingClient.server("passwordPolicy").run(session -> {
RealmModel realmModel = session.getContext().getRealm();
PasswordPolicyManagerProvider policyManager = session.getProvider(PasswordPolicyManagerProvider.class);
PasswordPolicy policy = null;
try {
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "regexPattern"));
fail("Expected NullPointerException: Regex Pattern cannot be null.");
} catch (ModelException e) {
assertEquals("Invalid config for regexPattern: Config required", e.getMessage());
}
try {
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "regexPattern(*)"));
fail("Expected PatternSyntaxException: Regex Pattern cannot be null.");
} catch (ModelException e) {
assertEquals("Invalid config for regexPattern: Not a valid regular expression", e.getMessage());
}
try {
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "regexPattern(*,**)"));
fail("Expected PatternSyntaxException: Regex Pattern cannot be null.");
} catch (ModelException e) {
assertEquals("Invalid config for regexPattern: Not a valid regular expression", e.getMessage());
}
// Fails to match one of the regex pattern
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "regexPattern(jdoe) and regexPattern(j*d)"));
Assert.assertEquals("invalidPasswordRegexPatternMessage", policyManager.validate("jdoe", "jdoe").getMessage());
// //Fails to match all of the regex patterns
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "regexPattern(j*p) and regexPattern(j*d) and regexPattern(adoe)"));
Assert.assertEquals("invalidPasswordRegexPatternMessage", policyManager.validate("jdoe", "jdoe").getMessage());
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "regexPattern([a-z][a-z][a-z][a-z][0-9])"));
Assert.assertEquals("invalidPasswordRegexPatternMessage", policyManager.validate("jdoe", "jdoe").getMessage());
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "regexPattern(jdoe)"));
assertNull(policyManager.validate("jdoe", "jdoe"));
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "regexPattern([a-z][a-z][a-z][a-z][0-9])"));
assertNull(policyManager.validate("jdoe", "jdoe0"));
});
}
use of org.keycloak.models.PasswordPolicy 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;
}
}
use of org.keycloak.models.PasswordPolicy 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;
}
}
Aggregations