commit
3c5e7872a7
2 changed files with 54 additions and 57 deletions
|
@ -8,7 +8,10 @@ import org.keycloak.models.*;
|
||||||
public class PasswordHashManager {
|
public class PasswordHashManager {
|
||||||
|
|
||||||
public static UserCredentialValueModel encode(KeycloakSession session, RealmModel realm, String rawPassword) {
|
public static UserCredentialValueModel encode(KeycloakSession session, RealmModel realm, String rawPassword) {
|
||||||
PasswordPolicy passwordPolicy = realm.getPasswordPolicy();
|
return encode(session, realm.getPasswordPolicy(), rawPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UserCredentialValueModel encode(KeycloakSession session, PasswordPolicy passwordPolicy, String rawPassword) {
|
||||||
String algorithm = passwordPolicy.getHashAlgorithm();
|
String algorithm = passwordPolicy.getHashAlgorithm();
|
||||||
int iterations = passwordPolicy.getHashIterations();
|
int iterations = passwordPolicy.getHashIterations();
|
||||||
if (iterations < 1) {
|
if (iterations < 1) {
|
||||||
|
@ -22,7 +25,11 @@ public class PasswordHashManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean verify(KeycloakSession session, RealmModel realm, String password, UserCredentialValueModel credential) {
|
public static boolean verify(KeycloakSession session, RealmModel realm, String password, UserCredentialValueModel credential) {
|
||||||
String algorithm = credential.getAlgorithm() != null ? credential.getAlgorithm() : realm.getPasswordPolicy().getHashAlgorithm();
|
return verify(session, realm.getPasswordPolicy(), password, credential);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean verify(KeycloakSession session, PasswordPolicy passwordPolicy, String password, UserCredentialValueModel credential) {
|
||||||
|
String algorithm = credential.getAlgorithm() != null ? credential.getAlgorithm() : passwordPolicy.getHashAlgorithm();
|
||||||
PasswordHashProvider provider = session.getProvider(PasswordHashProvider.class, algorithm);
|
PasswordHashProvider provider = session.getProvider(PasswordHashProvider.class, algorithm);
|
||||||
return provider.verify(password, credential);
|
return provider.verify(password, credential);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,19 +30,11 @@ public class PasswordPolicy implements Serializable {
|
||||||
private String policyString;
|
private String policyString;
|
||||||
|
|
||||||
public PasswordPolicy(String policyString) {
|
public PasswordPolicy(String policyString) {
|
||||||
if (policyString == null || policyString.length() == 0) {
|
|
||||||
this.policyString = null;
|
|
||||||
policies = Collections.emptyList();
|
|
||||||
} else {
|
|
||||||
this.policyString = policyString;
|
this.policyString = policyString;
|
||||||
policies = parse(policyString);
|
this.policies = new LinkedList<>();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<Policy> parse(String policyString) {
|
if (policyString != null && !policyString.isEmpty()) {
|
||||||
List<Policy> list = new LinkedList<Policy>();
|
for (String policy : policyString.split(" and ")) {
|
||||||
String[] policies = policyString.split(" and ");
|
|
||||||
for (String policy : policies) {
|
|
||||||
policy = policy.trim();
|
policy = policy.trim();
|
||||||
|
|
||||||
String name;
|
String name;
|
||||||
|
@ -57,33 +49,33 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name.equals(Length.NAME)) {
|
if (name.equals(Length.NAME)) {
|
||||||
list.add(new Length(arg));
|
policies.add(new Length(arg));
|
||||||
} else if (name.equals(Digits.NAME)) {
|
} else if (name.equals(Digits.NAME)) {
|
||||||
list.add(new Digits(arg));
|
policies.add(new Digits(arg));
|
||||||
} else if (name.equals(LowerCase.NAME)) {
|
} else if (name.equals(LowerCase.NAME)) {
|
||||||
list.add(new LowerCase(arg));
|
policies.add(new LowerCase(arg));
|
||||||
} else if (name.equals(UpperCase.NAME)) {
|
} else if (name.equals(UpperCase.NAME)) {
|
||||||
list.add(new UpperCase(arg));
|
policies.add(new UpperCase(arg));
|
||||||
} else if (name.equals(SpecialChars.NAME)) {
|
} else if (name.equals(SpecialChars.NAME)) {
|
||||||
list.add(new SpecialChars(arg));
|
policies.add(new SpecialChars(arg));
|
||||||
} else if (name.equals(NotUsername.NAME)) {
|
} else if (name.equals(NotUsername.NAME)) {
|
||||||
list.add(new NotUsername(arg));
|
policies.add(new NotUsername(arg));
|
||||||
} else if (name.equals(HashAlgorithm.NAME)) {
|
} else if (name.equals(HashAlgorithm.NAME)) {
|
||||||
list.add(new HashAlgorithm(arg));
|
policies.add(new HashAlgorithm(arg));
|
||||||
} else if (name.equals(HashIterations.NAME)) {
|
} else if (name.equals(HashIterations.NAME)) {
|
||||||
list.add(new HashIterations(arg));
|
policies.add(new HashIterations(arg));
|
||||||
} else if (name.equals(RegexPatterns.NAME)) {
|
} else if (name.equals(RegexPatterns.NAME)) {
|
||||||
Pattern.compile(arg);
|
Pattern.compile(arg);
|
||||||
list.add(new RegexPatterns(arg));
|
policies.add(new RegexPatterns(arg));
|
||||||
} else if (name.equals(PasswordHistory.NAME)) {
|
} else if (name.equals(PasswordHistory.NAME)) {
|
||||||
list.add(new PasswordHistory(arg));
|
policies.add(new PasswordHistory(arg, this));
|
||||||
} else if (name.equals(ForceExpiredPasswordChange.NAME)) {
|
} else if (name.equals(ForceExpiredPasswordChange.NAME)) {
|
||||||
list.add(new ForceExpiredPasswordChange(arg));
|
policies.add(new ForceExpiredPasswordChange(arg));
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Unsupported policy");
|
throw new IllegalArgumentException("Unsupported policy");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getHashAlgorithm() {
|
public String getHashAlgorithm() {
|
||||||
|
@ -396,10 +388,12 @@ public class PasswordPolicy implements Serializable {
|
||||||
|
|
||||||
private static class PasswordHistory implements Policy {
|
private static class PasswordHistory implements Policy {
|
||||||
private static final String NAME = "passwordHistory";
|
private static final String NAME = "passwordHistory";
|
||||||
|
private final PasswordPolicy passwordPolicy;
|
||||||
private int passwordHistoryPolicyValue;
|
private int passwordHistoryPolicyValue;
|
||||||
|
|
||||||
public PasswordHistory(String arg)
|
public PasswordHistory(String arg, PasswordPolicy passwordPolicy)
|
||||||
{
|
{
|
||||||
|
this.passwordPolicy = passwordPolicy;
|
||||||
passwordHistoryPolicyValue = intArg(NAME, 3, arg);
|
passwordHistoryPolicyValue = intArg(NAME, 3, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,13 +404,10 @@ public class PasswordPolicy implements Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(KeycloakSession session, UserModel user, String password) {
|
public Error validate(KeycloakSession session, UserModel user, String password) {
|
||||||
|
|
||||||
if (passwordHistoryPolicyValue != -1) {
|
if (passwordHistoryPolicyValue != -1) {
|
||||||
|
|
||||||
UserCredentialValueModel cred = getCredentialValueModel(user, UserCredentialModel.PASSWORD);
|
UserCredentialValueModel cred = getCredentialValueModel(user, UserCredentialModel.PASSWORD);
|
||||||
if (cred != null) {
|
if (cred != null) {
|
||||||
PasswordHashProvider hashProvider = session.getProvider(PasswordHashProvider.class, cred.getAlgorithm());
|
if(PasswordHashManager.verify(session, passwordPolicy, password, cred)) {
|
||||||
if(hashProvider.verify(password, cred)) {
|
|
||||||
return new Error(INVALID_PASSWORD_HISTORY, passwordHistoryPolicyValue);
|
return new Error(INVALID_PASSWORD_HISTORY, passwordHistoryPolicyValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -424,8 +415,7 @@ public class PasswordPolicy implements Serializable {
|
||||||
List<UserCredentialValueModel> passwordExpiredCredentials = getCredentialValueModels(user, passwordHistoryPolicyValue - 1,
|
List<UserCredentialValueModel> passwordExpiredCredentials = getCredentialValueModels(user, passwordHistoryPolicyValue - 1,
|
||||||
UserCredentialModel.PASSWORD_HISTORY);
|
UserCredentialModel.PASSWORD_HISTORY);
|
||||||
for (UserCredentialValueModel credential : passwordExpiredCredentials) {
|
for (UserCredentialValueModel credential : passwordExpiredCredentials) {
|
||||||
PasswordHashProvider hashProvider = session.getProvider(PasswordHashProvider.class, cred.getAlgorithm());
|
if (PasswordHashManager.verify(session, passwordPolicy, password, credential)) {
|
||||||
if (hashProvider.verify(password, credential)) {
|
|
||||||
return new Error(INVALID_PASSWORD_HISTORY, passwordHistoryPolicyValue);
|
return new Error(INVALID_PASSWORD_HISTORY, passwordHistoryPolicyValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue