diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
index e212c92..a2fa8c3 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
@@ -921,7 +921,8 @@ public class AuthenticationProcessor {
if (!authenticatedUser.isEnabled()) throw new AuthenticationFlowException(AuthenticationFlowError.USER_DISABLED);
if (realm.isBruteForceProtected() && !realm.isPermanentLockout()) {
if (getBruteForceProtector().isTemporarilyDisabled(session, realm, authenticatedUser)) {
- throw new AuthenticationFlowException(AuthenticationFlowError.USER_TEMPORARILY_DISABLED);
+ getEvent().error(Errors.RESET_CREDENTIAL_DISABLED);
+ ServicesLogger.LOGGER.passwordResetFailed(new AuthenticationFlowException(AuthenticationFlowError.USER_TEMPORARILY_DISABLED));
}
}
}
diff --git a/services/src/main/java/org/keycloak/services/ServicesLogger.java b/services/src/main/java/org/keycloak/services/ServicesLogger.java
index 2d6c473..98420ab 100644
--- a/services/src/main/java/org/keycloak/services/ServicesLogger.java
+++ b/services/src/main/java/org/keycloak/services/ServicesLogger.java
@@ -451,4 +451,8 @@ public interface ServicesLogger extends BasicLogger {
@Message(id=102, value= "URL '%s' doesn't match any trustedHost or trustedDomain")
void urlDoesntMatch(String url);
+ @LogMessage(level = DEBUG)
+ @Message(id=103, value="Failed to reset password. User is temporarily disabled")
+ void passwordResetFailed(@Cause Throwable t);
+
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/BruteForceTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/BruteForceTest.java
index 884762b..6741577 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/BruteForceTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/BruteForceTest.java
@@ -24,6 +24,7 @@ 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.Constants;
import org.keycloak.models.utils.TimeBasedOTP;
import org.keycloak.representations.idm.CredentialRepresentation;
@@ -35,6 +36,7 @@ import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
import org.keycloak.testsuite.pages.AppPage;
import org.keycloak.testsuite.pages.AppPage.RequestType;
import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.pages.LoginPasswordResetPage;
import org.keycloak.testsuite.pages.LoginTotpPage;
import org.keycloak.testsuite.pages.RegisterPage;
import org.keycloak.testsuite.util.GreenMailRule;
@@ -44,12 +46,16 @@ import org.keycloak.testsuite.util.UserBuilder;
import java.net.MalformedURLException;
+import static org.junit.Assert.assertEquals;
+
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
*/
public class BruteForceTest extends AbstractTestRealmKeycloakTest {
+ private static String userId;
+
@Override
public void configureTestRealm(RealmRepresentation testRealm) {
UserRepresentation user = RealmRepUtil.findUser(testRealm, "test-user@localhost");
@@ -62,6 +68,8 @@ public class BruteForceTest extends AbstractTestRealmKeycloakTest {
testRealm.setBruteForceProtected(true);
testRealm.setFailureFactor(2);
+ userId = user.getId();
+
RealmRepUtil.findClientByClientId(testRealm, "test-app").setDirectAccessGrantsEnabled(true);
testRealm.getUsers().add(UserBuilder.create().username("user2").email("user2@localhost").password("password").build());
}
@@ -74,7 +82,6 @@ public class BruteForceTest extends AbstractTestRealmKeycloakTest {
@After
public void slowItDown() throws Exception {
Thread.sleep(100);
-
}
@@ -91,6 +98,9 @@ public class BruteForceTest extends AbstractTestRealmKeycloakTest {
protected LoginPage loginPage;
@Page
+ protected LoginPasswordResetPage resetPasswordPage;
+
+ @Page
private RegisterPage registerPage;
@Page
@@ -215,8 +225,6 @@ public class BruteForceTest extends AbstractTestRealmKeycloakTest {
Assert.assertNull(response.getAccessToken());
}
-
-
@Test
public void testGrantMissingOtp() throws Exception {
{
@@ -384,6 +392,27 @@ public class BruteForceTest extends AbstractTestRealmKeycloakTest {
}
+ @Test
+ public void testResetPassword() throws Exception {
+ String userId = adminClient.realm("test").users().search("test-user@localhost", null, null, null, 0, 1).get(0).getId();
+
+ loginSuccess();
+ loginInvalidPassword();
+ loginInvalidPassword();
+ expectTemporarilyDisabled();
+
+ loginPage.resetPassword();
+ resetPasswordPage.assertCurrent();
+ resetPasswordPage.changePassword("test-user@localhost");
+ loginPage.assertCurrent();
+
+ assertEquals("You should receive an email shortly with further instructions.", loginPage.getSuccessMessage());
+
+ events.expectRequiredAction(EventType.RESET_PASSWORD_ERROR).user(userId);
+ events.clear();
+ clearUserFailures();
+ }
+
public void expectTemporarilyDisabled() throws Exception {
expectTemporarilyDisabled("test-user@localhost", null);
}