keycloak-memoizeit

Merge pull request #3070 from mstruk/KEYCLOAK-2571 KEYCLOAK-2571

7/28/2016 8:23:32 AM

Details

diff --git a/server-spi/src/main/java/org/keycloak/events/Errors.java b/server-spi/src/main/java/org/keycloak/events/Errors.java
index 0981806..ea2b887 100755
--- a/server-spi/src/main/java/org/keycloak/events/Errors.java
+++ b/server-spi/src/main/java/org/keycloak/events/Errors.java
@@ -71,4 +71,8 @@ public interface Errors {
     String INVALID_EMAIL = "invalid_email";
     String IDENTITY_PROVIDER_LOGIN_FAILURE = "identity_provider_login_failure";
     String IDENTITY_PROVIDER_ERROR = "identity_provider_error";
+
+    String PASSWORD_CONFIRM_ERROR = "password_confirm_error";
+    String PASSWORD_MISSING = "password_missing";
+    String PASSWORD_REJECTED = "password_rejected";
 }
diff --git a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdatePassword.java b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdatePassword.java
index 47c9d5b..7918815 100755
--- a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdatePassword.java
+++ b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdatePassword.java
@@ -21,6 +21,8 @@ import org.keycloak.Config;
 import org.keycloak.authentication.RequiredActionContext;
 import org.keycloak.authentication.RequiredActionFactory;
 import org.keycloak.authentication.RequiredActionProvider;
+import org.keycloak.events.Details;
+import org.keycloak.events.Errors;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
 import org.keycloak.models.KeycloakSession;
@@ -84,17 +86,23 @@ public class UpdatePassword implements RequiredActionProvider, RequiredActionFac
         String passwordNew = formData.getFirst("password-new");
         String passwordConfirm = formData.getFirst("password-confirm");
 
+        EventBuilder errorEvent = event.clone().event(EventType.UPDATE_PASSWORD_ERROR)
+                .client(context.getClientSession().getClient())
+                .user(context.getClientSession().getUserSession().getUser());
+
         if (Validation.isBlank(passwordNew)) {
             Response challenge = context.form()
                     .setError(Messages.MISSING_PASSWORD)
                     .createResponse(UserModel.RequiredAction.UPDATE_PASSWORD);
             context.challenge(challenge);
+            errorEvent.error(Errors.PASSWORD_MISSING);
             return;
         } else if (!passwordNew.equals(passwordConfirm)) {
             Response challenge = context.form()
                     .setError(Messages.NOTMATCH_PASSWORD)
                     .createResponse(UserModel.RequiredAction.UPDATE_PASSWORD);
             context.challenge(challenge);
+            errorEvent.error(Errors.PASSWORD_CONFIRM_ERROR);
             return;
         }
 
@@ -102,12 +110,14 @@ public class UpdatePassword implements RequiredActionProvider, RequiredActionFac
             context.getSession().users().updateCredential(context.getRealm(), context.getUser(), UserCredentialModel.password(passwordNew));
             context.success();
         } catch (ModelException me) {
+            errorEvent.detail(Details.REASON, me.getMessage()).error(Errors.PASSWORD_REJECTED);
             Response challenge = context.form()
                     .setError(me.getMessage(), me.getParameters())
                     .createResponse(UserModel.RequiredAction.UPDATE_PASSWORD);
             context.challenge(challenge);
             return;
         } catch (Exception ape) {
+            errorEvent.detail(Details.REASON, ape.getMessage()).error(Errors.PASSWORD_REJECTED);
             Response challenge = context.form()
                     .setError(ape.getMessage())
                     .createResponse(UserModel.RequiredAction.UPDATE_PASSWORD);
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index 251cd8e..bf6fb88 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -16,7 +16,7 @@
  */
 package org.keycloak.services.resources;
 
-import org.jboss.logging.Logger;
+import org.keycloak.events.Errors;
 import org.keycloak.forms.account.AccountPages;
 import org.keycloak.forms.account.AccountProvider;
 import org.keycloak.events.Details;
@@ -612,26 +612,34 @@ public class AccountService extends AbstractSecuredLocalService {
         String passwordNew = formData.getFirst("password-new");
         String passwordConfirm = formData.getFirst("password-confirm");
 
+        EventBuilder errorEvent = event.clone().event(EventType.UPDATE_PASSWORD_ERROR)
+                .client(auth.getClient())
+                .user(auth.getClientSession().getUserSession().getUser());
+
         if (requireCurrent) {
             if (Validation.isBlank(password)) {
                 setReferrerOnPage();
+                errorEvent.error(Errors.PASSWORD_MISSING);
                 return account.setError(Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD);
             }
 
             UserCredentialModel cred = UserCredentialModel.password(password);
             if (!session.users().validCredentials(session, realm, user, cred)) {
                 setReferrerOnPage();
+                errorEvent.error(Errors.INVALID_USER_CREDENTIALS);
                 return account.setError(Messages.INVALID_PASSWORD_EXISTING).createResponse(AccountPages.PASSWORD);
             }
         }
 
         if (Validation.isBlank(passwordNew)) {
             setReferrerOnPage();
+            errorEvent.error(Errors.PASSWORD_MISSING);
             return account.setError(Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD);
         }
 
         if (!passwordNew.equals(passwordConfirm)) {
             setReferrerOnPage();
+            errorEvent.error(Errors.PASSWORD_CONFIRM_ERROR);
             return account.setError(Messages.INVALID_PASSWORD_CONFIRM).createResponse(AccountPages.PASSWORD);
         }
 
@@ -639,14 +647,17 @@ public class AccountService extends AbstractSecuredLocalService {
             session.users().updateCredential(realm, user, UserCredentialModel.password(passwordNew));
         } catch (ModelReadOnlyException mre) {
             setReferrerOnPage();
+            errorEvent.error(Errors.NOT_ALLOWED);
             return account.setError(Messages.READ_ONLY_PASSWORD).createResponse(AccountPages.PASSWORD);
-        }catch (ModelException me) {
+        } catch (ModelException me) {
             logger.failedToUpdatePassword(me);
             setReferrerOnPage();
+            errorEvent.detail(Details.REASON, me.getMessage()).error(Errors.PASSWORD_REJECTED);
             return account.setError(me.getMessage(), me.getParameters()).createResponse(AccountPages.PASSWORD);
-        }catch (Exception ape) {
+        } catch (Exception ape) {
             logger.failedToUpdatePassword(ape);
             setReferrerOnPage();
+            errorEvent.detail(Details.REASON, ape.getMessage()).error(Errors.PASSWORD_REJECTED);
             return account.setError(ape.getMessage()).createResponse(AccountPages.PASSWORD);
         }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
index cf8791e..66dee2e 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -892,7 +892,7 @@ public class LoginActionsService {
                 return AuthenticationManager.finishedRequiredActions(session, userSession, clientSession, clientConnection, request, uriInfo, event);
 
             }
-       }
+        }
         if (context.getStatus() == RequiredActionContext.Status.CHALLENGE) {
             return context.getChallenge();
         }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountTest.java
index a4f7257..5f8a51d 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountTest.java
@@ -21,6 +21,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.events.Details;
+import org.keycloak.events.Errors;
 import org.keycloak.events.EventType;
 import org.keycloak.models.utils.TimeBasedOTP;
 import org.keycloak.services.resources.AccountService;
@@ -168,22 +169,20 @@ public class AccountTest extends TestRealmKeycloakTest {
         EventRepresentation event = events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=password").assertEvent();
         String sessionId = event.getSessionId();
         String userId = event.getUserId();
-        changePasswordPage.changePassword("", "new-password", "new-password");
 
+        changePasswordPage.changePassword("", "new-password", "new-password");
         Assert.assertEquals("Please specify password.", profilePage.getError());
+        events.expectAccount(EventType.UPDATE_PASSWORD_ERROR).error(Errors.PASSWORD_MISSING).assertEvent();
 
         changePasswordPage.changePassword("password", "new-password", "new-password2");
-
         Assert.assertEquals("Password confirmation doesn't match.", profilePage.getError());
+        events.expectAccount(EventType.UPDATE_PASSWORD_ERROR).error(Errors.PASSWORD_CONFIRM_ERROR).assertEvent();
 
         changePasswordPage.changePassword("password", "new-password", "new-password");
-
         Assert.assertEquals("Your password has been updated.", profilePage.getSuccess());
-
         events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
 
         changePasswordPage.logout();
-
         events.expectLogout(sessionId).detail(Details.REDIRECT_URI, changePasswordPage.getPath()).assertEvent();
 
         loginPage.open();
@@ -191,7 +190,7 @@ public class AccountTest extends TestRealmKeycloakTest {
 
         Assert.assertEquals("Invalid username or password.", loginPage.getError());
 
-        events.expectLogin().session((String) null).error("invalid_user_credentials")
+        events.expectLogin().session((String) null).error(Errors.INVALID_USER_CREDENTIALS)
                 .removeDetail(Details.CONSENT)
                 .assertEvent();
 
@@ -214,18 +213,14 @@ public class AccountTest extends TestRealmKeycloakTest {
 
         changePasswordPage.open();
         loginPage.login("test-user@localhost", "password");
-
-
         events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=password").assertEvent();
 
         changePasswordPage.changePassword("", "new", "new");
-
         Assert.assertEquals("Please specify password.", profilePage.getError());
+        events.expectAccount(EventType.UPDATE_PASSWORD_ERROR).error(Errors.PASSWORD_MISSING).assertEvent();
 
         changePasswordPage.changePassword("password", "new-password", "new-password");
-
         Assert.assertEquals("Your password has been updated.", profilePage.getSuccess());
-
         events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
     }
 
@@ -235,31 +230,26 @@ public class AccountTest extends TestRealmKeycloakTest {
 
         changePasswordPage.open();
         loginPage.login("test-user@localhost", "password");
-
         events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=password").assertEvent();
 
         changePasswordPage.changePassword("password", "password", "password");
-
         Assert.assertEquals("Invalid password: must not be equal to any of last 2 passwords.", profilePage.getError());
+        events.expectAccount(EventType.UPDATE_PASSWORD_ERROR).error(Errors.PASSWORD_REJECTED).assertEvent();
 
         changePasswordPage.changePassword("password", "password1", "password1");
-
         Assert.assertEquals("Your password has been updated.", profilePage.getSuccess());
-
         events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
 
         changePasswordPage.changePassword("password1", "password", "password");
-
         Assert.assertEquals("Invalid password: must not be equal to any of last 2 passwords.", profilePage.getError());
+        events.expectAccount(EventType.UPDATE_PASSWORD_ERROR).error(Errors.PASSWORD_REJECTED).assertEvent();
 
         changePasswordPage.changePassword("password1", "password1", "password1");
-
         Assert.assertEquals("Invalid password: must not be equal to any of last 2 passwords.", profilePage.getError());
+        events.expectAccount(EventType.UPDATE_PASSWORD_ERROR).error(Errors.PASSWORD_REJECTED).assertEvent();
 
         changePasswordPage.changePassword("password1", "password2", "password2");
-
         Assert.assertEquals("Your password has been updated.", profilePage.getSuccess());
-
         events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
     }
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java
index 98a3fe6..78d20d9 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java
@@ -314,6 +314,7 @@ public class ResetPasswordTest extends TestRealmKeycloakTest {
 
         assertTrue(updatePasswordPage.isCurrent());
         assertEquals(error, updatePasswordPage.getError());
+        events.expectRequiredAction(EventType.UPDATE_PASSWORD_ERROR).error(Errors.PASSWORD_REJECTED).user(userId).detail(Details.USERNAME, "login-test").assertEvent().getSessionId();
     }
 
     @Test
@@ -544,6 +545,8 @@ public class ResetPasswordTest extends TestRealmKeycloakTest {
 
         assertEquals("Invalid password: minimum length 8.", resetPasswordPage.getErrorMessage());
 
+        events.expectRequiredAction(EventType.UPDATE_PASSWORD_ERROR).error(Errors.PASSWORD_REJECTED).user(userId).detail(Details.USERNAME, "login-test").assertEvent().getSessionId();
+
         updatePasswordPage.changePassword("resetPasswordWithPasswordPolicy", "resetPasswordWithPasswordPolicy");
 
         String sessionId = events.expectRequiredAction(EventType.UPDATE_PASSWORD).user(userId).detail(Details.USERNAME, "login-test").assertEvent().getSessionId();