diff --git a/server-spi-private/src/main/java/org/keycloak/credential/hash/Pbkdf2PasswordHashProvider.java b/server-spi-private/src/main/java/org/keycloak/credential/hash/Pbkdf2PasswordHashProvider.java index 6a6c1ff3eb..f010dd3729 100644 --- a/server-spi-private/src/main/java/org/keycloak/credential/hash/Pbkdf2PasswordHashProvider.java +++ b/server-spi-private/src/main/java/org/keycloak/credential/hash/Pbkdf2PasswordHashProvider.java @@ -49,7 +49,12 @@ public class Pbkdf2PasswordHashProvider implements PasswordHashProvider { @Override public boolean policyCheck(PasswordPolicy policy, CredentialModel credential) { - return credential.getHashIterations() == policy.getHashIterations() && providerId.equals(credential.getAlgorithm()); + int policyHashIterations = policy.getHashIterations(); + if (policyHashIterations == -1) { + policyHashIterations = defaultIterations; + } + + return credential.getHashIterations() == policyHashIterations && providerId.equals(credential.getAlgorithm()); } @Override diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java index 6763e7d20d..8b978a4058 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java @@ -45,6 +45,7 @@ import org.keycloak.testsuite.AbstractTestRealmKeycloakTest; import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.admin.ApiUtil; import org.keycloak.testsuite.client.KeycloakTestingClient; +import org.keycloak.testsuite.pages.AccountUpdateProfilePage; import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.AppPage.RequestType; import org.keycloak.testsuite.pages.ErrorPage; @@ -67,6 +68,7 @@ import java.security.NoSuchAlgorithmException; import java.security.spec.KeySpec; import java.util.Map; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; @@ -78,6 +80,9 @@ import static org.junit.Assert.fail; */ public class PasswordHashingTest extends AbstractTestRealmKeycloakTest { + @Page + private AccountUpdateProfilePage updateProfilePage; + @Deployment public static WebArchive deploy() { return RunOnServerDeployment.create(PasswordHashingTest.class, AbstractTestRealmKeycloakTest.class); @@ -147,6 +152,42 @@ public class PasswordHashingTest extends AbstractTestRealmKeycloakTest { assertEncoded(credential, "password", credential.getSalt(), "PBKDF2WithHmacSHA256", 1); } + // KEYCLOAK-5282 + @Test + public void testPasswordNotRehasedUnchangedIterations() throws Exception { + setPasswordPolicy(""); + + String username = "testPasswordNotRehasedUnchangedIterations"; + createUser(username); + + CredentialModel credential = fetchCredentials(username); + String credentialId = credential.getId(); + byte[] salt = credential.getSalt(); + + setPasswordPolicy("hashIterations"); + + loginPage.open(); + loginPage.login(username, "password"); + + credential = fetchCredentials(username); + + assertEquals(credentialId, credential.getId()); + assertArrayEquals(salt, credential.getSalt()); + + setPasswordPolicy("hashIterations(" + Pbkdf2Sha256PasswordHashProviderFactory.DEFAULT_ITERATIONS + ")"); + + updateProfilePage.open(); + updateProfilePage.logout(); + + loginPage.open(); + loginPage.login(username, "password"); + + credential = fetchCredentials(username); + + assertEquals(credentialId, credential.getId()); + assertArrayEquals(salt, credential.getSalt()); + } + @Test public void testPbkdf2Sha1() throws Exception { setPasswordPolicy("hashAlgorithm(" + Pbkdf2PasswordHashProviderFactory.ID + ")");