keycloak-memoizeit

brute force fixes

4/23/2014 6:55:13 PM

Details

diff --git a/examples/demo-template/testrealm.json b/examples/demo-template/testrealm.json
index 2e35b12..81af756 100755
--- a/examples/demo-template/testrealm.json
+++ b/examples/demo-template/testrealm.json
@@ -7,7 +7,6 @@
     "sslNotRequired": true,
     "registrationAllowed": false,
     "social": false,
-    "bruteForceProtected": true,
     "updateProfileOnInitialSocialLogin": false,
     "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
     "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
diff --git a/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java b/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java
index 5645c57..a941f89 100755
--- a/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java
+++ b/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java
@@ -1,7 +1,7 @@
 package org.keycloak.services.managers;
 
 
-import org.jboss.resteasy.logging.Logger;
+import org.jboss.logging.Logger;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.RealmModel;
@@ -78,10 +78,13 @@ public class BruteForceProtector implements Runnable {
     }
 
     public void failure(KeycloakSession session, LoginEvent event) {
+        logger.debug("failure");
         RealmModel realm = getRealmModel(session, event);
         logFailure(event);
         UsernameLoginFailureModel user = getUserModel(session, event);
-        if (user == null) return;
+        if (user == null) {
+            user = realm.addUserLoginFailure(event.username);
+        }
         user.setLastIPFailure(event.ip);
         long currentTime = System.currentTimeMillis();
         long last = user.getLastFailure();
@@ -97,16 +100,22 @@ public class BruteForceProtector implements Runnable {
             }
         }
         user.incrementFailures();
+        logger.debugv("new num failures: {0}" , user.getNumFailures());
 
         int waitSeconds = realm.getWaitIncrementSeconds() * (user.getNumFailures() / realm.getFailureFactor());
+        logger.debugv("waitSeconds: {0}", waitSeconds);
+        logger.debugv("deltaTime: {0}", deltaTime);
         if (waitSeconds == 0) {
-            if (deltaTime > realm.getQuickLoginCheckMilliSeconds()) {
+            if (last > 0 && deltaTime < realm.getQuickLoginCheckMilliSeconds()) {
+                logger.debugv("quick login, set min wait seconds");
                 waitSeconds = realm.getMinimumQuickLoginWaitSeconds();
             }
         }
-        waitSeconds = Math.min(realm.getMaxFailureWaitSeconds(), waitSeconds);
         if (waitSeconds > 0) {
-            user.setFailedLoginNotBefore((int) (currentTime / 1000) + waitSeconds);
+            waitSeconds = Math.min(realm.getMaxFailureWaitSeconds(), waitSeconds);
+            int notBefore = (int) (currentTime / 1000) + waitSeconds;
+            logger.debugv("set notBefore: {0}", notBefore);
+            user.setFailedLoginNotBefore(notBefore);
         }
     }
 
@@ -152,6 +161,7 @@ public class BruteForceProtector implements Runnable {
                     queue.drainTo(events, TRANSACTION_SIZE);
                     Collections.sort(events); // we sort to avoid deadlock due to ordered updates.  Maybe I'm overthinking this.
                     KeycloakSession session = factory.createSession();
+                    session.getTransaction().begin();
                     try {
                         for (LoginEvent event : events) {
                             if (event instanceof FailedLogin) {
@@ -231,6 +241,7 @@ public class BruteForceProtector implements Runnable {
 
         int currTime = (int)(System.currentTimeMillis()/1000);
         if (currTime < failure.getFailedLoginNotBefore()) {
+            logger.debugv("Current: {0} notBefore: {1}", currTime , failure.getFailedLoginNotBefore());
             return true;
         }
         return false;
diff --git a/testsuite/integration/src/test/resources/testcomposite.json b/testsuite/integration/src/test/resources/testcomposite.json
index dd4e378..61038ea 100755
--- a/testsuite/integration/src/test/resources/testcomposite.json
+++ b/testsuite/integration/src/test/resources/testcomposite.json
@@ -6,7 +6,6 @@
     "accessCodeLifespan": 600,
     "accessCodeLifespanUserAction": 600,
     "sslNotRequired": true,
-    "bruteForceProtected": true,
     "registrationAllowed": true,
     "resetPasswordAllowed": true,
     "requiredCredentials": [ "password" ],
diff --git a/testsuite/integration/src/test/resources/testrealm.json b/testsuite/integration/src/test/resources/testrealm.json
index d3ea49f..a7cf0d4 100755
--- a/testsuite/integration/src/test/resources/testrealm.json
+++ b/testsuite/integration/src/test/resources/testrealm.json
@@ -5,7 +5,6 @@
     "sslNotRequired": true,
     "registrationAllowed": true,
     "resetPasswordAllowed": true,
-    "bruteForceProtected": true,
     "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
     "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
     "requiredCredentials": [ "password" ],