/*
* 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.PasswordPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.policy.PasswordPolicyManagerProvider;
import java.util.regex.PatternSyntaxException;
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 (IllegalArgumentException e) {
}
}
@Test
public void testRegexPatterns() {
PasswordPolicy policy = null;
try {
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "regexPattern"));
fail("Expected NullPointerException: Regex Pattern cannot be null.");
} catch (IllegalArgumentException e) {
// Expected NPE as regex pattern is null.
}
try {
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "regexPattern(*)"));
fail("Expected PatternSyntaxException: Regex Pattern cannot be null.");
} catch (PatternSyntaxException e) {
// Expected PSE as regex pattern(or any of its token) is not quantifiable.
}
try {
realmModel.setPasswordPolicy(PasswordPolicy.parse(session, "regexPattern(*,**)"));
fail("Expected PatternSyntaxException: Regex Pattern cannot be null.");
} catch (PatternSyntaxException e) {
// Expected PSE as regex pattern(or any of its token) is not quantifiable.
}
//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&-"));
}
}