keycloak-memoizeit

Details

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);
     }