commit
a6e4245185
16 changed files with 490 additions and 252 deletions
|
@ -37,12 +37,14 @@ public class Pbkdf2PasswordHashProvider implements PasswordHashProvider {
|
|||
private final String providerId;
|
||||
|
||||
private final String pbkdf2Algorithm;
|
||||
private int defaultIterations;
|
||||
|
||||
public static final int DERIVED_KEY_SIZE = 512;
|
||||
|
||||
public Pbkdf2PasswordHashProvider(String providerId, String pbkdf2Algorithm) {
|
||||
public Pbkdf2PasswordHashProvider(String providerId, String pbkdf2Algorithm, int defaultIterations) {
|
||||
this.providerId = providerId;
|
||||
this.pbkdf2Algorithm = pbkdf2Algorithm;
|
||||
this.defaultIterations = defaultIterations;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -52,6 +54,10 @@ public class Pbkdf2PasswordHashProvider implements PasswordHashProvider {
|
|||
|
||||
@Override
|
||||
public void encode(String rawPassword, int iterations, CredentialModel credential) {
|
||||
if (iterations == -1) {
|
||||
iterations = defaultIterations;
|
||||
}
|
||||
|
||||
byte[] salt = getSalt();
|
||||
String encodedPassword = encode(rawPassword, iterations, salt);
|
||||
|
||||
|
|
|
@ -30,9 +30,11 @@ public class Pbkdf2PasswordHashProviderFactory implements PasswordHashProviderFa
|
|||
|
||||
public static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA1";
|
||||
|
||||
public static final int DEFAULT_ITERATIONS = 20000;
|
||||
|
||||
@Override
|
||||
public PasswordHashProvider create(KeycloakSession session) {
|
||||
return new Pbkdf2PasswordHashProvider(ID, PBKDF2_ALGORITHM);
|
||||
return new Pbkdf2PasswordHashProvider(ID, PBKDF2_ALGORITHM, 20000);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,9 +15,11 @@ public class Pbkdf2Sha256PasswordHashProviderFactory implements PasswordHashProv
|
|||
|
||||
public static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA256";
|
||||
|
||||
public static final int DEFAULT_ITERATIONS = 27500;
|
||||
|
||||
@Override
|
||||
public PasswordHashProvider create(KeycloakSession session) {
|
||||
return new Pbkdf2PasswordHashProvider(ID, PBKDF2_ALGORITHM);
|
||||
return new Pbkdf2PasswordHashProvider(ID, PBKDF2_ALGORITHM, DEFAULT_ITERATIONS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,9 +15,11 @@ public class Pbkdf2Sha512PasswordHashProviderFactory implements PasswordHashProv
|
|||
|
||||
public static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA512";
|
||||
|
||||
public static final int DEFAULT_ITERATIONS = 30000;
|
||||
|
||||
@Override
|
||||
public PasswordHashProvider create(KeycloakSession session) {
|
||||
return new Pbkdf2PasswordHashProvider(ID, PBKDF2_ALGORITHM);
|
||||
return new Pbkdf2PasswordHashProvider(ID, PBKDF2_ALGORITHM, DEFAULT_ITERATIONS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.keycloak.migration.migrators.MigrateTo2_3_0;
|
|||
import org.keycloak.migration.migrators.MigrateTo2_5_0;
|
||||
import org.keycloak.migration.migrators.MigrateTo3_0_0;
|
||||
import org.keycloak.migration.migrators.MigrateTo3_1_0;
|
||||
import org.keycloak.migration.migrators.MigrateTo3_2_0;
|
||||
import org.keycloak.migration.migrators.Migration;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
||||
|
@ -60,7 +61,8 @@ public class MigrationModelManager {
|
|||
new MigrateTo2_3_0(),
|
||||
new MigrateTo2_5_0(),
|
||||
new MigrateTo3_0_0(),
|
||||
new MigrateTo3_1_0()
|
||||
new MigrateTo3_1_0(),
|
||||
new MigrateTo3_2_0()
|
||||
};
|
||||
|
||||
public static void migrate(KeycloakSession session) {
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.migration.migrators;
|
||||
|
||||
|
||||
import org.keycloak.migration.ModelVersion;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.PasswordPolicy;
|
||||
import org.keycloak.models.RealmModel;
|
||||
|
||||
public class MigrateTo3_2_0 implements Migration {
|
||||
|
||||
public static final ModelVersion VERSION = new ModelVersion("3.1.0");
|
||||
|
||||
@Override
|
||||
public void migrate(KeycloakSession session) {
|
||||
for (RealmModel realm : session.realms().getRealms()) {
|
||||
PasswordPolicy.Builder builder = realm.getPasswordPolicy().toBuilder();
|
||||
if (!builder.contains(PasswordPolicy.HASH_ALGORITHM_ID) && "20000".equals(builder.get(PasswordPolicy.HASH_ITERATIONS_ID))) {
|
||||
realm.setPasswordPolicy(builder.remove(PasswordPolicy.HASH_ITERATIONS_ID).build(session));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelVersion getVersion() {
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
}
|
|
@ -60,7 +60,7 @@ public class HashIterationsPasswordPolicyProviderFactory implements PasswordPoli
|
|||
|
||||
@Override
|
||||
public Object parseConfig(String value) {
|
||||
return value != null ? Integer.parseInt(value) : PasswordPolicy.HASH_ITERATIONS_DEFAULT;
|
||||
return parseInteger(value, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.keycloak.policy.PasswordPolicyProvider;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -32,62 +33,33 @@ public class PasswordPolicy implements Serializable {
|
|||
|
||||
public static final String HASH_ALGORITHM_ID = "hashAlgorithm";
|
||||
|
||||
public static final String HASH_ALGORITHM_DEFAULT = "pbkdf2";
|
||||
public static final String HASH_ALGORITHM_DEFAULT = "pbkdf2-sha256";
|
||||
|
||||
public static final String HASH_ITERATIONS_ID = "hashIterations";
|
||||
|
||||
public static final int HASH_ITERATIONS_DEFAULT = 20000;
|
||||
public static final int HASH_ITERATIONS_DEFAULT = 27500;
|
||||
|
||||
public static final String PASSWORD_HISTORY_ID = "passwordHistory";
|
||||
|
||||
public static final String FORCE_EXPIRED_ID = "forceExpiredPasswordChange";
|
||||
|
||||
private String policyString;
|
||||
private Map<String, Object> policyConfig;
|
||||
private Builder builder;
|
||||
|
||||
public static PasswordPolicy empty() {
|
||||
return new PasswordPolicy(null, new HashMap<>());
|
||||
}
|
||||
|
||||
public static PasswordPolicy parse(KeycloakSession session, String policyString) {
|
||||
Map<String, Object> policyConfig = new HashMap<>();
|
||||
|
||||
if (policyString != null && !policyString.trim().isEmpty()) {
|
||||
for (String policy : policyString.split(" and ")) {
|
||||
policy = policy.trim();
|
||||
|
||||
String key;
|
||||
String config = null;
|
||||
|
||||
int i = policy.indexOf('(');
|
||||
if (i == -1) {
|
||||
key = policy.trim();
|
||||
} else {
|
||||
key = policy.substring(0, i).trim();
|
||||
config = policy.substring(i + 1, policy.length() - 1);
|
||||
}
|
||||
|
||||
PasswordPolicyProvider provider = session.getProvider(PasswordPolicyProvider.class, key);
|
||||
if (provider == null) {
|
||||
throw new PasswordPolicyConfigException("Password policy not found");
|
||||
}
|
||||
|
||||
Object o;
|
||||
try {
|
||||
o = provider.parseConfig(config);
|
||||
} catch (PasswordPolicyConfigException e) {
|
||||
throw new ModelException("Invalid config for " + key + ": " + e.getMessage());
|
||||
}
|
||||
|
||||
policyConfig.put(key, o);
|
||||
}
|
||||
}
|
||||
|
||||
return new PasswordPolicy(policyString, policyConfig);
|
||||
public static Builder build() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
private PasswordPolicy(String policyString, Map<String, Object> policyConfig) {
|
||||
this.policyString = policyString;
|
||||
public static PasswordPolicy parse(KeycloakSession session, String policyString) {
|
||||
return new Builder(policyString).build(session);
|
||||
}
|
||||
|
||||
private PasswordPolicy(Builder builder, Map<String, Object> policyConfig) {
|
||||
this.builder = builder;
|
||||
this.policyConfig = policyConfig;
|
||||
}
|
||||
|
||||
|
@ -111,7 +83,7 @@ public class PasswordPolicy implements Serializable {
|
|||
if (policyConfig.containsKey(HASH_ITERATIONS_ID)) {
|
||||
return getPolicyConfig(HASH_ITERATIONS_ID);
|
||||
} else {
|
||||
return HASH_ITERATIONS_DEFAULT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,7 +105,117 @@ public class PasswordPolicy implements Serializable {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return policyString;
|
||||
return builder.asString();
|
||||
}
|
||||
|
||||
public Builder toBuilder() {
|
||||
return builder.clone();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private LinkedHashMap<String, String> map;
|
||||
|
||||
private Builder() {
|
||||
this.map = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
private Builder(LinkedHashMap<String, String> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
private Builder(String policyString) {
|
||||
map = new LinkedHashMap<>();
|
||||
|
||||
if (policyString != null && !policyString.trim().isEmpty()) {
|
||||
for (String policy : policyString.split(" and ")) {
|
||||
policy = policy.trim();
|
||||
|
||||
String key;
|
||||
String config = null;
|
||||
|
||||
int i = policy.indexOf('(');
|
||||
if (i == -1) {
|
||||
key = policy.trim();
|
||||
} else {
|
||||
key = policy.substring(0, i).trim();
|
||||
config = policy.substring(i + 1, policy.length() - 1);
|
||||
}
|
||||
|
||||
map.put(key, config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(String key) {
|
||||
return map.containsKey(key);
|
||||
}
|
||||
|
||||
public String get(String key) {
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
public Builder put(String key, String value) {
|
||||
map.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder remove(String key) {
|
||||
map.remove(key);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PasswordPolicy build(KeycloakSession session) {
|
||||
Map<String, Object> config = new HashMap<>();
|
||||
for (Map.Entry<String, String> e : map.entrySet()) {
|
||||
|
||||
PasswordPolicyProvider provider = session.getProvider(PasswordPolicyProvider.class, e.getKey());
|
||||
if (provider == null) {
|
||||
throw new PasswordPolicyConfigException("Password policy not found");
|
||||
}
|
||||
|
||||
Object o;
|
||||
try {
|
||||
o = provider.parseConfig(e.getValue());
|
||||
} catch (PasswordPolicyConfigException ex) {
|
||||
throw new ModelException("Invalid config for " + e.getKey() + ": " + ex.getMessage());
|
||||
}
|
||||
|
||||
config.put(e.getKey(), o);
|
||||
}
|
||||
return new PasswordPolicy(this, config);
|
||||
}
|
||||
|
||||
public String asString() {
|
||||
if (map.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
boolean first = true;
|
||||
for (Map.Entry<String, String> e : map.entrySet()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
sb.append(" and ");
|
||||
}
|
||||
|
||||
sb.append(e.getKey());
|
||||
|
||||
String c = e.getValue();
|
||||
if (c != null && !c.trim().isEmpty()) {
|
||||
sb.append("(");
|
||||
sb.append(c);
|
||||
sb.append(")");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Builder clone() {
|
||||
return new Builder((LinkedHashMap<String, String>) map.clone());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -226,8 +226,6 @@ public class RealmManager {
|
|||
realm.setLoginWithEmailAllowed(true);
|
||||
|
||||
realm.setEventsListeners(Collections.singleton("jboss-logging"));
|
||||
|
||||
realm.setPasswordPolicy(PasswordPolicy.parse(session, "hashIterations(20000)"));
|
||||
}
|
||||
|
||||
public boolean removeRealm(RealmModel realm) {
|
||||
|
|
|
@ -31,7 +31,7 @@ public class LogChecker {
|
|||
|
||||
private static final Logger log = Logger.getLogger(LogChecker.class);
|
||||
|
||||
private static final String[] IGNORED = new String[] { ".*Jetty ALPN support not found.*" };
|
||||
private static final String[] IGNORED = new String[] { ".*Jetty ALPN support not found.*", ".*org.keycloak.events.*" };
|
||||
|
||||
public static void checkServerLog(File logFile) throws IOException {
|
||||
log.info(String.format("Checking server log: '%s'", logFile.getAbsolutePath()));
|
||||
|
|
|
@ -173,7 +173,7 @@ public class RealmTest extends AbstractAdminTest {
|
|||
|
||||
adminClient.realms().create(rep);
|
||||
|
||||
assertEquals("hashIterations(20000)", adminClient.realm("new-realm").toRepresentation().getPasswordPolicy());
|
||||
assertEquals(null, adminClient.realm("new-realm").toRepresentation().getPasswordPolicy());
|
||||
|
||||
adminClient.realms().realm("new-realm").remove();
|
||||
|
||||
|
|
|
@ -103,34 +103,38 @@ public class PasswordHashingTest extends AbstractTestRealmKeycloakTest {
|
|||
|
||||
@Test
|
||||
public void testPasswordRehashedOnAlgorithmChanged() throws Exception {
|
||||
setPasswordPolicy("hashAlgorithm(" + Pbkdf2Sha256PasswordHashProviderFactory.ID + ") and hashIterations(1)");
|
||||
|
||||
String username = "testPasswordRehashedOnAlgorithmChanged";
|
||||
createUser(username);
|
||||
|
||||
CredentialModel credential = fetchCredentials(username);
|
||||
|
||||
assertEquals(Pbkdf2PasswordHashProviderFactory.ID, credential.getAlgorithm());
|
||||
assertEquals(Pbkdf2Sha256PasswordHashProviderFactory.ID, credential.getAlgorithm());
|
||||
|
||||
assertEncoded(credential, "password", credential.getSalt(), "PBKDF2WithHmacSHA1", 20000);
|
||||
assertEncoded(credential, "password", credential.getSalt(), "PBKDF2WithHmacSHA256", 1);
|
||||
|
||||
setPasswordPolicy("hashAlgorithm(" + Pbkdf2Sha256PasswordHashProviderFactory.ID + ")");
|
||||
setPasswordPolicy("hashAlgorithm(" + Pbkdf2PasswordHashProviderFactory.ID + ") and hashIterations(1)");
|
||||
|
||||
loginPage.open();
|
||||
loginPage.login(username, "password");
|
||||
|
||||
credential = fetchCredentials(username);
|
||||
|
||||
assertEquals(Pbkdf2Sha256PasswordHashProviderFactory.ID, credential.getAlgorithm());
|
||||
assertEncoded(credential, "password", credential.getSalt(), "PBKDF2WithHmacSHA256", 20000);
|
||||
assertEquals(Pbkdf2PasswordHashProviderFactory.ID, credential.getAlgorithm());
|
||||
assertEncoded(credential, "password", credential.getSalt(), "PBKDF2WithHmacSHA1", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPasswordRehashedOnIterationsChanged() throws Exception {
|
||||
setPasswordPolicy("hashIterations(10000)");
|
||||
|
||||
String username = "testPasswordRehashedOnIterationsChanged";
|
||||
createUser(username);
|
||||
|
||||
CredentialModel credential = fetchCredentials(username);
|
||||
|
||||
assertEquals(20000, credential.getHashIterations());
|
||||
assertEquals(10000, credential.getHashIterations());
|
||||
|
||||
setPasswordPolicy("hashIterations(1)");
|
||||
|
||||
|
@ -140,7 +144,7 @@ public class PasswordHashingTest extends AbstractTestRealmKeycloakTest {
|
|||
credential = fetchCredentials(username);
|
||||
|
||||
assertEquals(1, credential.getHashIterations());
|
||||
assertEncoded(credential, "password", credential.getSalt(), "PBKDF2WithHmacSHA1", 1);
|
||||
assertEncoded(credential, "password", credential.getSalt(), "PBKDF2WithHmacSHA256", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -153,6 +157,16 @@ public class PasswordHashingTest extends AbstractTestRealmKeycloakTest {
|
|||
assertEncoded(credential, "password", credential.getSalt(), "PBKDF2WithHmacSHA1", 20000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefault() throws Exception {
|
||||
setPasswordPolicy("");
|
||||
String username = "testDefault";
|
||||
createUser(username);
|
||||
|
||||
CredentialModel credential = fetchCredentials(username);
|
||||
assertEncoded(credential, "password", credential.getSalt(), "PBKDF2WithHmacSHA256", 27500);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPbkdf2Sha256() throws Exception {
|
||||
setPasswordPolicy("hashAlgorithm(" + Pbkdf2Sha256PasswordHashProviderFactory.ID + ")");
|
||||
|
@ -160,7 +174,7 @@ public class PasswordHashingTest extends AbstractTestRealmKeycloakTest {
|
|||
createUser(username);
|
||||
|
||||
CredentialModel credential = fetchCredentials(username);
|
||||
assertEncoded(credential, "password", credential.getSalt(), "PBKDF2WithHmacSHA256", 20000);
|
||||
assertEncoded(credential, "password", credential.getSalt(), "PBKDF2WithHmacSHA256", 27500);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -170,7 +184,7 @@ public class PasswordHashingTest extends AbstractTestRealmKeycloakTest {
|
|||
createUser(username);
|
||||
|
||||
CredentialModel credential = fetchCredentials(username);
|
||||
assertEncoded(credential, "password", credential.getSalt(), "PBKDF2WithHmacSHA512", 20000);
|
||||
assertEncoded(credential, "password", credential.getSalt(), "PBKDF2WithHmacSHA512", 30000);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ import org.keycloak.testsuite.runonserver.RunHelpers;
|
|||
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
|
||||
import org.keycloak.testsuite.util.OAuthClient;
|
||||
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT;
|
||||
import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT_LINKS;
|
||||
import static org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_CLIENT_ID;
|
||||
|
@ -132,6 +133,7 @@ public class MigrationTest extends AbstractKeycloakTest {
|
|||
testMigrationTo2_5_0();
|
||||
testMigrationTo2_5_1();
|
||||
testMigrationTo3_0_0();
|
||||
testMigrationTo3_2_0();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -210,7 +212,12 @@ public class MigrationTest extends AbstractKeycloakTest {
|
|||
private void testMigrationTo3_0_0() {
|
||||
testRoleManageAccountLinks(masterRealm, migrationRealm);
|
||||
}
|
||||
|
||||
|
||||
private void testMigrationTo3_2_0() {
|
||||
assertNull(masterRealm.toRepresentation().getPasswordPolicy());
|
||||
assertNull(migrationRealm.toRepresentation().getPasswordPolicy());
|
||||
}
|
||||
|
||||
private void testRoleManageAccountLinks(RealmResource... realms) {
|
||||
log.info("testing role manage account links");
|
||||
for (RealmResource realm : realms) {
|
||||
|
|
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.policy;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.models.ModelException;
|
||||
import org.keycloak.models.PasswordPolicy;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.policy.PasswordPolicyManagerProvider;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
|
||||
import org.keycloak.testsuite.util.RealmBuilder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class PasswordPolicyTest extends AbstractKeycloakTest {
|
||||
|
||||
@Deployment
|
||||
public static WebArchive deploy() {
|
||||
return RunOnServerDeployment.create();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLength() {
|
||||
testingClient.server("passwordPolicy").run(session -> {
|
||||
RealmModel realmModel = session.getContext().getRealm();
|
||||
PasswordPolicyManagerProvider policyManager = session.getProvider(PasswordPolicyManagerProvider.class);
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "length"));
|
||||
|
||||
Assert.assertEquals("invalidPasswordMinLengthMessage", policyManager.validate("jdoe", "1234567").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{8}, policyManager.validate("jdoe", "1234567").getParameters());
|
||||
assertNull(policyManager.validate("jdoe", "12345678"));
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "length(4)"));
|
||||
|
||||
Assert.assertEquals("invalidPasswordMinLengthMessage", policyManager.validate("jdoe", "123").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{4}, policyManager.validate("jdoe", "123").getParameters());
|
||||
assertNull(policyManager.validate("jdoe", "1234"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDigits() {
|
||||
testingClient.server("passwordPolicy").run(session -> {
|
||||
RealmModel realmModel = session.getContext().getRealm();
|
||||
PasswordPolicyManagerProvider policyManager = session.getProvider(PasswordPolicyManagerProvider.class);
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "digits"));
|
||||
Assert.assertEquals("invalidPasswordMinDigitsMessage", policyManager.validate("jdoe", "abcd").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{1}, policyManager.validate("jdoe", "abcd").getParameters());
|
||||
assertNull(policyManager.validate("jdoe", "abcd1"));
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "digits(2)"));
|
||||
Assert.assertEquals("invalidPasswordMinDigitsMessage", policyManager.validate("jdoe", "abcd1").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{2}, policyManager.validate("jdoe", "abcd1").getParameters());
|
||||
assertNull(policyManager.validate("jdoe", "abcd12"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLowerCase() {
|
||||
testingClient.server("passwordPolicy").run(session -> {
|
||||
RealmModel realmModel = session.getContext().getRealm();
|
||||
PasswordPolicyManagerProvider policyManager = session.getProvider(PasswordPolicyManagerProvider.class);
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "lowerCase"));
|
||||
Assert.assertEquals("invalidPasswordMinLowerCaseCharsMessage", policyManager.validate("jdoe", "ABCD1234").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{1}, policyManager.validate("jdoe", "ABCD1234").getParameters());
|
||||
assertNull(policyManager.validate("jdoe", "ABcD1234"));
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "lowerCase(2)"));
|
||||
Assert.assertEquals("invalidPasswordMinLowerCaseCharsMessage", policyManager.validate("jdoe", "ABcD1234").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{2}, policyManager.validate("jdoe", "ABcD1234").getParameters());
|
||||
assertNull(policyManager.validate("jdoe", "aBcD1234"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpperCase() {
|
||||
testingClient.server("passwordPolicy").run(session -> {
|
||||
RealmModel realmModel = session.getContext().getRealm();
|
||||
PasswordPolicyManagerProvider policyManager = session.getProvider(PasswordPolicyManagerProvider.class);
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "upperCase"));
|
||||
Assert.assertEquals("invalidPasswordMinUpperCaseCharsMessage", policyManager.validate("jdoe", "abcd1234").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{1}, policyManager.validate("jdoe", "abcd1234").getParameters());
|
||||
assertNull(policyManager.validate("jdoe", "abCd1234"));
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "upperCase(2)"));
|
||||
Assert.assertEquals("invalidPasswordMinUpperCaseCharsMessage", policyManager.validate("jdoe", "abCd1234").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{2}, policyManager.validate("jdoe", "abCd1234").getParameters());
|
||||
assertNull(policyManager.validate("jdoe", "AbCd1234"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialChars() {
|
||||
testingClient.server("passwordPolicy").run(session -> {
|
||||
RealmModel realmModel = session.getContext().getRealm();
|
||||
PasswordPolicyManagerProvider policyManager = session.getProvider(PasswordPolicyManagerProvider.class);
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "specialChars"));
|
||||
Assert.assertEquals("invalidPasswordMinSpecialCharsMessage", policyManager.validate("jdoe", "abcd1234").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{1}, policyManager.validate("jdoe", "abcd1234").getParameters());
|
||||
assertNull(policyManager.validate("jdoe", "ab&d1234"));
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "specialChars(2)"));
|
||||
Assert.assertEquals("invalidPasswordMinSpecialCharsMessage", policyManager.validate("jdoe", "ab&d1234").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{2}, policyManager.validate("jdoe", "ab&d1234").getParameters());
|
||||
assertNull(policyManager.validate("jdoe", "ab&d-234"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotUsername() {
|
||||
testingClient.server("passwordPolicy").run(session -> {
|
||||
RealmModel realmModel = session.getContext().getRealm();
|
||||
PasswordPolicyManagerProvider policyManager = session.getProvider(PasswordPolicyManagerProvider.class);
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "notUsername"));
|
||||
Assert.assertEquals("invalidPasswordNotUsernameMessage", policyManager.validate("jdoe", "jdoe").getMessage());
|
||||
assertNull(policyManager.validate("jdoe", "ab&d1234"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidPolicyName() {
|
||||
testingClient.server("passwordPolicy").run(session -> {
|
||||
RealmModel realmModel = session.getContext().getRealm();
|
||||
PasswordPolicyManagerProvider policyManager = session.getProvider(PasswordPolicyManagerProvider.class);
|
||||
|
||||
try {
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "noSuchPolicy"));
|
||||
Assert.fail("Expected exception");
|
||||
} catch (ModelException e) {
|
||||
assertEquals("Password policy not found", e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@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"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplex() {
|
||||
testingClient.server("passwordPolicy").run(session -> {
|
||||
RealmModel realmModel = session.getContext().getRealm();
|
||||
PasswordPolicyManagerProvider policyManager = session.getProvider(PasswordPolicyManagerProvider.class);
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "length(8) and digits(2) and lowerCase(2) and upperCase(2) and specialChars(2) and notUsername()"));
|
||||
Assert.assertNotNull(policyManager.validate("jdoe", "12aaBB&"));
|
||||
Assert.assertNotNull(policyManager.validate("jdoe", "aaaaBB&-"));
|
||||
Assert.assertNotNull(policyManager.validate("jdoe", "12AABB&-"));
|
||||
Assert.assertNotNull(policyManager.validate("jdoe", "12aabb&-"));
|
||||
Assert.assertNotNull(policyManager.validate("jdoe", "12aaBBcc"));
|
||||
Assert.assertNotNull(policyManager.validate("12aaBB&-", "12aaBB&-"));
|
||||
|
||||
assertNull(policyManager.validate("jdoe", "12aaBB&-"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilder() {
|
||||
testingClient.server("passwordPolicy").run(session -> {
|
||||
PasswordPolicy.Builder builder = PasswordPolicy.parse(session, "hashIterations(20000)").toBuilder();
|
||||
assertFalse(builder.contains(PasswordPolicy.HASH_ALGORITHM_ID));
|
||||
assertTrue("20000".equals(builder.get(PasswordPolicy.HASH_ITERATIONS_ID)));
|
||||
|
||||
builder.remove(PasswordPolicy.HASH_ITERATIONS_ID);
|
||||
|
||||
assertNull(builder.asString());
|
||||
|
||||
builder = PasswordPolicy.parse(session, "hashIterations(20000) and hashAlgorithm(pbkdf2)").toBuilder();
|
||||
assertTrue(builder.contains(PasswordPolicy.HASH_ALGORITHM_ID));
|
||||
|
||||
builder = PasswordPolicy.parse(session, "hashIterations(20000) and length(100)").toBuilder();
|
||||
builder.remove(PasswordPolicy.HASH_ITERATIONS_ID);
|
||||
assertEquals("length(100)", builder.asString());
|
||||
|
||||
builder = PasswordPolicy.parse(session, "digits(10) and hashIterations(20000) and length(100)").toBuilder();
|
||||
builder.remove(PasswordPolicy.HASH_ITERATIONS_ID);
|
||||
assertEquals("digits(10) and length(100)", builder.asString());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||
testRealms.add(RealmBuilder.create().name("passwordPolicy").build());
|
||||
}
|
||||
|
||||
}
|
|
@ -26,7 +26,7 @@ import org.junit.rules.TemporaryFolder;
|
|||
import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.credential.hash.Pbkdf2PasswordHashProviderFactory;
|
||||
import org.keycloak.credential.hash.Pbkdf2Sha256PasswordHashProviderFactory;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
|
@ -85,7 +85,7 @@ public class AddUserTest {
|
|||
|
||||
CredentialRepresentation credentials = user.getCredentials().get(0);
|
||||
|
||||
assertEquals(Pbkdf2PasswordHashProviderFactory.ID, credentials.getAlgorithm());
|
||||
assertEquals(Pbkdf2Sha256PasswordHashProviderFactory.ID, credentials.getAlgorithm());
|
||||
assertEquals(new Integer(100000), credentials.getHashIterations());
|
||||
|
||||
KeycloakServer server = new KeycloakServer();
|
||||
|
|
|
@ -1,188 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.model;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.models.ModelException;
|
||||
import org.keycloak.models.PasswordPolicy;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.policy.PasswordPolicyManagerProvider;
|
||||
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class PasswordPolicyTest extends AbstractModelTest {
|
||||
|
||||
private RealmModel realmModel;
|
||||
private PasswordPolicyManagerProvider policyManager;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
super.before();
|
||||
realmModel = realmManager.createRealm("JUGGLER");
|
||||
session.getContext().setRealm(realmModel);
|
||||
policyManager = session.getProvider(PasswordPolicyManagerProvider.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLength() {
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "length"));
|
||||
|
||||
Assert.assertEquals("invalidPasswordMinLengthMessage", policyManager.validate("jdoe", "1234567").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{8}, policyManager.validate("jdoe", "1234567").getParameters());
|
||||
Assert.assertNull(policyManager.validate("jdoe", "12345678"));
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "length(4)"));
|
||||
|
||||
Assert.assertEquals("invalidPasswordMinLengthMessage", policyManager.validate("jdoe", "123").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{4}, policyManager.validate("jdoe", "123").getParameters());
|
||||
Assert.assertNull(policyManager.validate("jdoe", "1234"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDigits() {
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "digits"));
|
||||
Assert.assertEquals("invalidPasswordMinDigitsMessage", policyManager.validate("jdoe", "abcd").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{1}, policyManager.validate("jdoe", "abcd").getParameters());
|
||||
Assert.assertNull(policyManager.validate("jdoe", "abcd1"));
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "digits(2)"));
|
||||
Assert.assertEquals("invalidPasswordMinDigitsMessage", policyManager.validate("jdoe", "abcd1").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{2}, policyManager.validate("jdoe", "abcd1").getParameters());
|
||||
Assert.assertNull(policyManager.validate("jdoe", "abcd12"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLowerCase() {
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "lowerCase"));
|
||||
Assert.assertEquals("invalidPasswordMinLowerCaseCharsMessage", policyManager.validate("jdoe", "ABCD1234").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{1}, policyManager.validate("jdoe", "ABCD1234").getParameters());
|
||||
Assert.assertNull(policyManager.validate("jdoe", "ABcD1234"));
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "lowerCase(2)"));
|
||||
Assert.assertEquals("invalidPasswordMinLowerCaseCharsMessage", policyManager.validate("jdoe", "ABcD1234").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{2}, policyManager.validate("jdoe", "ABcD1234").getParameters());
|
||||
Assert.assertNull(policyManager.validate("jdoe", "aBcD1234"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpperCase() {
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "upperCase"));
|
||||
Assert.assertEquals("invalidPasswordMinUpperCaseCharsMessage", policyManager.validate("jdoe", "abcd1234").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{1}, policyManager.validate("jdoe", "abcd1234").getParameters());
|
||||
Assert.assertNull(policyManager.validate("jdoe", "abCd1234"));
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "upperCase(2)"));
|
||||
Assert.assertEquals("invalidPasswordMinUpperCaseCharsMessage", policyManager.validate("jdoe", "abCd1234").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{2}, policyManager.validate("jdoe", "abCd1234").getParameters());
|
||||
Assert.assertNull(policyManager.validate("jdoe", "AbCd1234"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialChars() {
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "specialChars"));
|
||||
Assert.assertEquals("invalidPasswordMinSpecialCharsMessage", policyManager.validate("jdoe", "abcd1234").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{1}, policyManager.validate("jdoe", "abcd1234").getParameters());
|
||||
Assert.assertNull(policyManager.validate("jdoe", "ab&d1234"));
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "specialChars(2)"));
|
||||
Assert.assertEquals("invalidPasswordMinSpecialCharsMessage", policyManager.validate("jdoe", "ab&d1234").getMessage());
|
||||
Assert.assertArrayEquals(new Object[]{2}, policyManager.validate("jdoe", "ab&d1234").getParameters());
|
||||
Assert.assertNull(policyManager.validate("jdoe", "ab&d-234"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotUsername() {
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "notUsername"));
|
||||
Assert.assertEquals("invalidPasswordNotUsernameMessage", policyManager.validate("jdoe", "jdoe").getMessage());
|
||||
Assert.assertNull(policyManager.validate("jdoe", "ab&d1234"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidPolicyName() {
|
||||
try {
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "noSuchPolicy"));
|
||||
Assert.fail("Expected exception");
|
||||
} catch (ModelException e) {
|
||||
assertEquals("Password policy not found", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegexPatterns() {
|
||||
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)"));
|
||||
Assert.assertNull(policyManager.validate("jdoe", "jdoe"));
|
||||
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "regexPattern([a-z][a-z][a-z][a-z][0-9])"));
|
||||
Assert.assertNull(policyManager.validate("jdoe", "jdoe0"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplex() {
|
||||
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "length(8) and digits(2) and lowerCase(2) and upperCase(2) and specialChars(2) and notUsername()"));
|
||||
Assert.assertNotNull(policyManager.validate("jdoe", "12aaBB&"));
|
||||
Assert.assertNotNull(policyManager.validate("jdoe", "aaaaBB&-"));
|
||||
Assert.assertNotNull(policyManager.validate("jdoe", "12AABB&-"));
|
||||
Assert.assertNotNull(policyManager.validate("jdoe", "12aabb&-"));
|
||||
Assert.assertNotNull(policyManager.validate("jdoe", "12aaBBcc"));
|
||||
Assert.assertNotNull(policyManager.validate("12aaBB&-", "12aaBB&-"));
|
||||
|
||||
Assert.assertNull(policyManager.validate("jdoe", "12aaBB&-"));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue