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 6a6c1ff..f010dd3 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 6763e7d..8b978a4 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 + ")");