diff --git a/services/src/main/java/org/keycloak/services/resources/account/AccountCredentialResource.java b/services/src/main/java/org/keycloak/services/resources/account/AccountCredentialResource.java
index 125de8b..9078987 100644
--- a/services/src/main/java/org/keycloak/services/resources/account/AccountCredentialResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/account/AccountCredentialResource.java
@@ -1,6 +1,5 @@
package org.keycloak.services.resources.account;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.keycloak.credential.CredentialModel;
import org.keycloak.credential.CredentialProvider;
import org.keycloak.credential.PasswordCredentialProvider;
@@ -66,6 +65,15 @@ public class AccountCredentialResource {
event.error(org.keycloak.events.Errors.INVALID_USER_CREDENTIALS);
return ErrorResponse.error(Messages.INVALID_PASSWORD_EXISTING, Response.Status.BAD_REQUEST);
}
+
+ if (update.getNewPassword() == null) {
+ return ErrorResponse.error(Messages.INVALID_PASSWORD_EXISTING, Response.Status.BAD_REQUEST);
+ }
+
+ String confirmation = update.getConfirmation();
+ if ((confirmation != null) && !update.getNewPassword().equals(confirmation)) {
+ return ErrorResponse.error(Messages.NOTMATCH_PASSWORD, Response.Status.BAD_REQUEST);
+ }
try {
session.userCredentialManager().updateCredential(realm, user, UserCredentialModel.password(update.getNewPassword(), false));
@@ -99,11 +107,11 @@ public class AccountCredentialResource {
}
- @JsonIgnoreProperties(ignoreUnknown=true)
public static class PasswordUpdate {
private String currentPassword;
private String newPassword;
+ private String confirmation;
public String getCurrentPassword() {
return currentPassword;
@@ -120,6 +128,14 @@ public class AccountCredentialResource {
public void setNewPassword(String newPassword) {
this.newPassword = newPassword;
}
+
+ public String getConfirmation() {
+ return confirmation;
+ }
+
+ public void setConfirmation(String confirmation) {
+ this.confirmation = confirmation;
+ }
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountRestServiceTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountRestServiceTest.java
index 52ffe3e..aa9c089 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountRestServiceTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountRestServiceTest.java
@@ -219,6 +219,13 @@ public class AccountRestServiceTest extends AbstractTestRealmKeycloakTest {
//Change the password back
updatePassword("Str0ng3rP4ssw0rd", "password", 200);
}
+
+ @Test
+ public void testPasswordConfirmation() throws IOException {
+ updatePassword("password", "Str0ng3rP4ssw0rd", "confirmationDoesNotMatch", 400);
+
+ updatePassword("password", "Str0ng3rP4ssw0rd", "Str0ng3rP4ssw0rd", 200);
+ }
private AccountCredentialResource.PasswordDetails getPasswordDetails() throws IOException {
AccountCredentialResource.PasswordDetails details = SimpleHttp.doGet(getAccountUrl("credentials/password"), client).auth(tokenUtil.getToken()).asJson(new TypeReference<AccountCredentialResource.PasswordDetails>() {});
@@ -228,9 +235,14 @@ public class AccountRestServiceTest extends AbstractTestRealmKeycloakTest {
}
private void updatePassword(String currentPass, String newPass, int expectedStatus) throws IOException {
+ updatePassword(currentPass, newPass, null, expectedStatus);
+ }
+
+ private void updatePassword(String currentPass, String newPass, String confirmation, int expectedStatus) throws IOException {
AccountCredentialResource.PasswordUpdate passwordUpdate = new AccountCredentialResource.PasswordUpdate();
passwordUpdate.setCurrentPassword(currentPass);
passwordUpdate.setNewPassword(newPass);
+ passwordUpdate.setConfirmation(confirmation);
int status = SimpleHttp.doPost(getAccountUrl("credentials/password"), client).auth(tokenUtil.getToken()).json(passwordUpdate).asStatus();
assertEquals(expectedStatus, status);
}