keycloak-memoizeit

Merge pull request #340 from patriot1burke/master brute

4/15/2014 12:37:49 PM

Details

diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
index 04be127..a08236d 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
@@ -1119,11 +1119,35 @@ module.controller('RealmAuditEventsCtrl', function($scope, RealmAuditEvents, rea
     $scope.update();
 });
 
-module.controller('RealmBruteForceCtrl', function($scope, Realm, realm, $http, $location, Dialog, Notifications) {
+module.controller('RealmBruteForceCtrl', function($scope, Realm, realm, $http, $location, Dialog, Notifications, TimeUnit) {
     console.log('RealmBruteForceCtrl');
 
     $scope.realm = realm;
 
+    $scope.realm.waitIncrementUnit = TimeUnit.autoUnit(realm.waitIncrementSeconds);
+    $scope.realm.waitIncrement = TimeUnit.toUnit(realm.waitIncrementSeconds, $scope.realm.waitIncrementUnit);
+    $scope.$watch('realm.waitIncrementUnit', function(to, from) {
+        $scope.realm.waitIncrement = TimeUnit.convert($scope.realm.waitIncrement, from, to);
+    });
+
+    $scope.realm.minimumQuickLoginWaitUnit = TimeUnit.autoUnit(realm.minimumQuickLoginWaitSeconds);
+    $scope.realm.minimumQuickLoginWait = TimeUnit.toUnit(realm.minimumQuickLoginWaitSeconds, $scope.realm.minimumQuickLoginWaitUnit);
+    $scope.$watch('realm.minimumQuickLoginWaitUnit', function(to, from) {
+        $scope.realm.minimumQuickLoginWait = TimeUnit.convert($scope.realm.minimumQuickLoginWait, from, to);
+    });
+
+    $scope.realm.maxFailureWaitUnit = TimeUnit.autoUnit(realm.maxFailureWaitSeconds);
+    $scope.realm.maxFailureWait = TimeUnit.toUnit(realm.maxFailureWaitSeconds, $scope.realm.maxFailureWaitUnit);
+    $scope.$watch('realm.maxFailureWaitUnit', function(to, from) {
+        $scope.realm.maxFailureWait = TimeUnit.convert($scope.realm.maxFailureWait, from, to);
+    });
+
+    $scope.realm.maxDeltaTimeUnit = TimeUnit.autoUnit(realm.maxDeltaTimeSeconds);
+    $scope.realm.maxDeltaTime = TimeUnit.toUnit(realm.maxDeltaTimeSeconds, $scope.realm.maxDeltaTimeUnit);
+    $scope.$watch('realm.maxDeltaTimeUnit', function(to, from) {
+        $scope.realm.maxDeltaTime = TimeUnit.convert($scope.realm.maxDeltaTime, from, to);
+    });
+
     var oldCopy = angular.copy($scope.realm);
     $scope.changed = false;
 
@@ -1135,6 +1159,20 @@ module.controller('RealmBruteForceCtrl', function($scope, Realm, realm, $http, $
 
     $scope.save = function() {
         var realmCopy = angular.copy($scope.realm);
+        delete realmCopy["waitIncrementUnit"];
+        delete realmCopy["waitIncrement"];
+        delete realmCopy["minimumQuickLoginWaitUnit"];
+        delete realmCopy["minimumQuickLoginWait"];
+        delete realmCopy["maxFailureWaitUnit"];
+        delete realmCopy["maxFailureWait"];
+        delete realmCopy["maxDeltaTimeUnit"];
+        delete realmCopy["maxDeltaTime"];
+
+        realmCopy.waitIncrementSeconds = TimeUnit.toSeconds($scope.realm.waitIncrement, $scope.realm.waitIncrementUnit)
+        realmCopy.minimumQuickLoginWaitSeconds = TimeUnit.toSeconds($scope.realm.minimumQuickLoginWait, $scope.realm.minimumQuickLoginWaitUnit)
+        realmCopy.maxFailureWaitSeconds = TimeUnit.toSeconds($scope.realm.maxFailureWait, $scope.realm.maxFailureWaitUnit)
+        realmCopy.maxDeltaTimeSeconds = TimeUnit.toSeconds($scope.realm.maxDeltaTime, $scope.realm.maxDeltaTimeUnit)
+
         $scope.changed = false;
         Realm.update(realmCopy, function () {
             $location.url("/realms/" + realm.realm + "/sessions/brute-force");
@@ -1148,3 +1186,4 @@ module.controller('RealmBruteForceCtrl', function($scope, Realm, realm, $http, $
     };
 });
 
+
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/session-brute-force.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/session-brute-force.html
index ae45712..a2c7f47 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/session-brute-force.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/session-brute-force.html
@@ -20,6 +20,102 @@
                         <input ng-model="realm.bruteForceProtected" name="bruteForceProtected" id="bruteForceProtected" onoffswitch />
                     </div>
                 </div>
+                <div class="form-group" data-ng-show="realm.bruteForceProtected">
+                    <label class="col-sm-2 control-label" for="failureFactor">Failure Factor</label>
+
+                    <div class="col-sm-4">
+                        <input class="form-control" type="number" min="1" max="31536000" id="failureFactor" name="failureFactor" data-ng-model="realm.failureFactor" autofocus
+                               required>
+                    </div>
+                </div>
+                <div class="form-group input-select" data-ng-show="realm.bruteForceProtected">
+                    <label class="col-sm-2 control-label" for="waitIncrement">Wait Increment</label>
+                    <div class="col-sm-10">
+                        <div class="row">
+                            <div class="col-sm-2">
+                                <input class="form-control" type="number" required min="1"
+                                       max="31536000" data-ng-model="realm.waitIncrement"
+                                       id="waitIncrement" name="waitIncrement"/>
+                            </div>
+                            <div class="col-sm-2 select-kc">
+                                <select name="waitIncrementUnit" data-ng-model="realm.waitIncrementUnit" >
+                                    <option data-ng-selected="!realm.waitIncrementUnit">Seconds</option>
+                                    <option>Minutes</option>
+                                    <option>Hours</option>
+                                    <option>Days</option>
+                                </select>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="form-group" data-ng-show="realm.bruteForceProtected">
+                    <label class="col-sm-2 control-label" for="quickLoginCheckMilliSeconds">Quick Login Check Milli Seconds</label>
+
+                    <div class="col-sm-4">
+                        <input class="form-control" type="number" min="1" max="31536000" id="quickLoginCheckMilliSeconds" name="quickLoginCheckMilliSeconds" data-ng-model="realm.quickLoginCheckMilliSeconds" autofocus
+                               required>
+                    </div>
+                </div>
+                <div class="form-group input-select" data-ng-show="realm.bruteForceProtected">
+                    <label class="col-sm-2 control-label" for="minimumQuickLoginWait">Minimum Quick Login Wait</label>
+                    <div class="col-sm-10">
+                        <div class="row">
+                            <div class="col-sm-2">
+                                <input class="form-control" type="number" required min="1"
+                                       max="31536000" data-ng-model="realm.minimumQuickLoginWait"
+                                       id="minimumQuickLoginWait" name="minimumQuickLoginWait"/>
+                            </div>
+                            <div class="col-sm-2 select-kc">
+                                <select name="minimumQuickLoginWaitUnit" data-ng-model="realm.minimumQuickLoginWaitUnit" >
+                                    <option data-ng-selected="!realm.minimumQuickLoginWaitUnit">Seconds</option>
+                                    <option>Minutes</option>
+                                    <option>Hours</option>
+                                    <option>Days</option>
+                                </select>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="form-group input-select" data-ng-show="realm.bruteForceProtected">
+                    <label class="col-sm-2 control-label" for="maxFailureWait">Max Wait</label>
+                    <div class="col-sm-10">
+                        <div class="row">
+                            <div class="col-sm-2">
+                                <input class="form-control" type="number" required min="1"
+                                       max="31536000" data-ng-model="realm.maxFailureWait"
+                                       id="maxFailureWait" name="maxFailureWait"/>
+                            </div>
+                            <div class="col-sm-2 select-kc">
+                                <select name="maxFailureWaitUnit" data-ng-model="realm.maxFailureWaitUnit" >
+                                    <option data-ng-selected="!realm.maxFailureWaitUnit">Seconds</option>
+                                    <option>Minutes</option>
+                                    <option>Hours</option>
+                                    <option>Days</option>
+                                </select>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="form-group input-select" data-ng-show="realm.bruteForceProtected">
+                    <label class="col-sm-2 control-label" for="maxDeltaTime">Failure Reset Time</label>
+                    <div class="col-sm-10">
+                        <div class="row">
+                            <div class="col-sm-2">
+                                <input class="form-control" type="number" required min="1"
+                                       max="31536000" data-ng-model="realm.maxDeltaTime"
+                                       id="maxDeltaTime" name="maxDeltaTime"/>
+                            </div>
+                            <div class="col-sm-2 select-kc">
+                                <select name="maxDeltaTimeUnit" data-ng-model="realm.maxDeltaTimeUnit" >
+                                    <option data-ng-selected="!realm.maxDeltaTimeUnit">Seconds</option>
+                                    <option>Minutes</option>
+                                    <option>Hours</option>
+                                    <option>Days</option>
+                                </select>
+                            </div>
+                        </div>
+                    </div>
+                </div>
             </fieldset>
             <div class="pull-right form-actions" data-ng-show="access.manageRealm">
                 <button kc-reset data-ng-show="changed">Clear changes</button>
diff --git a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
index 0228a8b..2812fc4 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
@@ -28,7 +28,16 @@ public class RealmRepresentation {
     protected Boolean resetPasswordAllowed;
     protected Boolean social;
     protected Boolean updateProfileOnInitialSocialLogin;
+    //--- brute force settings
     protected Boolean bruteForceProtected;
+    protected Integer maxFailureWaitSeconds;
+    protected Integer minimumQuickLoginWaitSeconds;
+    protected Integer waitIncrementSeconds;
+    protected Long quickLoginCheckMilliSeconds;
+    protected Integer maxDeltaTimeSeconds;
+    protected Integer failureFactor;
+    //--- end brute force settings
+
     protected String privateKey;
     protected String publicKey;
     protected RolesRepresentation roles;
@@ -384,4 +393,52 @@ public class RealmRepresentation {
     public void setBruteForceProtected(Boolean bruteForceProtected) {
         this.bruteForceProtected = bruteForceProtected;
     }
+
+    public Integer getMaxFailureWaitSeconds() {
+        return maxFailureWaitSeconds;
+    }
+
+    public void setMaxFailureWaitSeconds(Integer maxFailureWaitSeconds) {
+        this.maxFailureWaitSeconds = maxFailureWaitSeconds;
+    }
+
+    public Integer getMinimumQuickLoginWaitSeconds() {
+        return minimumQuickLoginWaitSeconds;
+    }
+
+    public void setMinimumQuickLoginWaitSeconds(Integer minimumQuickLoginWaitSeconds) {
+        this.minimumQuickLoginWaitSeconds = minimumQuickLoginWaitSeconds;
+    }
+
+    public Integer getWaitIncrementSeconds() {
+        return waitIncrementSeconds;
+    }
+
+    public void setWaitIncrementSeconds(Integer waitIncrementSeconds) {
+        this.waitIncrementSeconds = waitIncrementSeconds;
+    }
+
+    public Long getQuickLoginCheckMilliSeconds() {
+        return quickLoginCheckMilliSeconds;
+    }
+
+    public void setQuickLoginCheckMilliSeconds(Long quickLoginCheckMilliSeconds) {
+        this.quickLoginCheckMilliSeconds = quickLoginCheckMilliSeconds;
+    }
+
+    public Integer getMaxDeltaTimeSeconds() {
+        return maxDeltaTimeSeconds;
+    }
+
+    public void setMaxDeltaTimeSeconds(Integer maxDeltaTimeSeconds) {
+        this.maxDeltaTimeSeconds = maxDeltaTimeSeconds;
+    }
+
+    public Integer getFailureFactor() {
+        return failureFactor;
+    }
+
+    public void setFailureFactor(Integer failureFactor) {
+        this.failureFactor = failureFactor;
+    }
 }
diff --git a/model/api/src/main/java/org/keycloak/models/RealmModel.java b/model/api/src/main/java/org/keycloak/models/RealmModel.java
index 6e20605..eda8e30 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -33,9 +33,23 @@ public interface RealmModel extends RoleContainerModel, RoleMapperModel, ScopeMa
 
     void setRememberMe(boolean rememberMe);
 
+    //--- brute force settings
     boolean isBruteForceProtected();
-
     void setBruteForceProtected(boolean value);
+    int getMaxFailureWaitSeconds();
+    void setMaxFailureWaitSeconds(int val);
+    int getWaitIncrementSeconds();
+    void setWaitIncrementSeconds(int val);
+    int getMinimumQuickLoginWaitSeconds();
+    void setMinimumQuickLoginWaitSeconds(int val);
+    long getQuickLoginCheckMilliSeconds();
+    void setQuickLoginCheckMilliSeconds(long val);
+    int getMaxDeltaTimeSeconds();
+    void setMaxDeltaTimeSeconds(int val);
+    int getFailureFactor();
+    void setFailureFactor(int failureFactor);
+    //--- end brute force settings
+
 
     boolean isVerifyEmail();
 
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
index 6885a70..556065f 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
@@ -42,7 +42,16 @@ public class RealmEntity {
     protected boolean resetPasswordAllowed;
     protected boolean social;
     protected boolean rememberMe;
+    //--- brute force settings
     protected boolean bruteForceProtected;
+    protected int maxFailureWaitSeconds;
+    protected int minimumQuickLoginWaitSeconds;
+    protected int waitIncrementSeconds;
+    protected long quickLoginCheckMilliSeconds;
+    protected int maxDeltaTimeSeconds;
+    protected int failureFactor;
+    //--- end brute force settings
+
 
     @Column(name="updateProfileOnInitSocLogin")
     protected boolean updateProfileOnInitialSocialLogin;
@@ -352,6 +361,54 @@ public class RealmEntity {
         this.bruteForceProtected = bruteForceProtected;
     }
 
+    public int getMaxFailureWaitSeconds() {
+        return maxFailureWaitSeconds;
+    }
+
+    public void setMaxFailureWaitSeconds(int maxFailureWaitSeconds) {
+        this.maxFailureWaitSeconds = maxFailureWaitSeconds;
+    }
+
+    public int getMinimumQuickLoginWaitSeconds() {
+        return minimumQuickLoginWaitSeconds;
+    }
+
+    public void setMinimumQuickLoginWaitSeconds(int minimumQuickLoginWaitSeconds) {
+        this.minimumQuickLoginWaitSeconds = minimumQuickLoginWaitSeconds;
+    }
+
+    public int getWaitIncrementSeconds() {
+        return waitIncrementSeconds;
+    }
+
+    public void setWaitIncrementSeconds(int waitIncrementSeconds) {
+        this.waitIncrementSeconds = waitIncrementSeconds;
+    }
+
+    public long getQuickLoginCheckMilliSeconds() {
+        return quickLoginCheckMilliSeconds;
+    }
+
+    public void setQuickLoginCheckMilliSeconds(long quickLoginCheckMilliSeconds) {
+        this.quickLoginCheckMilliSeconds = quickLoginCheckMilliSeconds;
+    }
+
+    public int getMaxDeltaTimeSeconds() {
+        return maxDeltaTimeSeconds;
+    }
+
+    public void setMaxDeltaTimeSeconds(int maxDeltaTimeSeconds) {
+        this.maxDeltaTimeSeconds = maxDeltaTimeSeconds;
+    }
+
+    public int getFailureFactor() {
+        return failureFactor;
+    }
+
+    public void setFailureFactor(int failureFactor) {
+        this.failureFactor = failureFactor;
+    }
+
     public boolean isAuditEnabled() {
         return auditEnabled;
     }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index fce9a3d..2833c64 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -137,6 +137,66 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
+    public int getMaxFailureWaitSeconds() {
+        return realm.getMaxFailureWaitSeconds();
+    }
+
+    @Override
+    public void setMaxFailureWaitSeconds(int val) {
+        realm.setMaxFailureWaitSeconds(val);
+    }
+
+    @Override
+    public int getWaitIncrementSeconds() {
+        return realm.getWaitIncrementSeconds();
+    }
+
+    @Override
+    public void setWaitIncrementSeconds(int val) {
+        realm.setWaitIncrementSeconds(val);
+    }
+
+    @Override
+    public long getQuickLoginCheckMilliSeconds() {
+        return realm.getQuickLoginCheckMilliSeconds();
+    }
+
+    @Override
+    public void setQuickLoginCheckMilliSeconds(long val) {
+        realm.setQuickLoginCheckMilliSeconds(val);
+    }
+
+    @Override
+    public int getMinimumQuickLoginWaitSeconds() {
+        return realm.getMinimumQuickLoginWaitSeconds();
+    }
+
+    @Override
+    public void setMinimumQuickLoginWaitSeconds(int val) {
+        realm.setMinimumQuickLoginWaitSeconds(val);
+    }
+
+    @Override
+    public int getMaxDeltaTimeSeconds() {
+        return realm.getMaxDeltaTimeSeconds();
+    }
+
+    @Override
+    public void setMaxDeltaTimeSeconds(int val) {
+        realm.setMaxDeltaTimeSeconds(val);
+    }
+
+    @Override
+    public int getFailureFactor() {
+        return realm.getFailureFactor();
+    }
+
+    @Override
+    public void setFailureFactor(int failureFactor) {
+        realm.setFailureFactor(failureFactor);
+    }
+
+    @Override
     public boolean isVerifyEmail() {
         return realm.isVerifyEmail();
     }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index 3fc43f2..2052967 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -135,6 +135,68 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
     }
 
     @Override
+    public int getMaxFailureWaitSeconds() {
+        return realm.getMaxFailureWaitSeconds();
+    }
+
+    @Override
+    public void setMaxFailureWaitSeconds(int val) {
+        realm.setMaxFailureWaitSeconds(val);
+    }
+
+    @Override
+    public int getWaitIncrementSeconds() {
+        return realm.getWaitIncrementSeconds();
+    }
+
+    @Override
+    public void setWaitIncrementSeconds(int val) {
+        realm.setWaitIncrementSeconds(val);
+    }
+
+    @Override
+    public long getQuickLoginCheckMilliSeconds() {
+        return realm.getQuickLoginCheckMilliSeconds();
+    }
+
+    @Override
+    public void setQuickLoginCheckMilliSeconds(long val) {
+        realm.setQuickLoginCheckMilliSeconds(val);
+    }
+
+    @Override
+    public int getMinimumQuickLoginWaitSeconds() {
+        return realm.getMinimumQuickLoginWaitSeconds();
+    }
+
+    @Override
+    public void setMinimumQuickLoginWaitSeconds(int val) {
+        realm.setMinimumQuickLoginWaitSeconds(val);
+    }
+
+
+    @Override
+    public int getMaxDeltaTimeSeconds() {
+        return realm.getMaxDeltaTimeSeconds();
+    }
+
+    @Override
+    public void setMaxDeltaTimeSeconds(int val) {
+        realm.setMaxDeltaTimeSeconds(val);
+    }
+
+    @Override
+    public int getFailureFactor() {
+        return realm.getFailureFactor();
+    }
+
+    @Override
+    public void setFailureFactor(int failureFactor) {
+        realm.setFailureFactor(failureFactor);
+    }
+
+
+    @Override
     public boolean isVerifyEmail() {
         return realm.isVerifyEmail();
     }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/RealmEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/RealmEntity.java
index 6786c90..fc0ee56 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/RealmEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/RealmEntity.java
@@ -32,7 +32,15 @@ public class RealmEntity extends AbstractMongoIdentifiableEntity implements Mong
     private boolean social;
     private boolean updateProfileOnInitialSocialLogin;
     private String passwordPolicy;
+    //--- brute force settings
     private boolean bruteForceProtected;
+    private int maxFailureWaitSeconds;
+    private int minimumQuickLoginWaitSeconds;
+    private int waitIncrementSeconds;
+    private long quickLoginCheckMilliSeconds;
+    private int maxDeltaTimeSeconds;
+    private int failureFactor;
+    //--- end brute force settings
 
     private int centralLoginLifespan;
     private int accessTokenLifespan;
@@ -152,6 +160,60 @@ public class RealmEntity extends AbstractMongoIdentifiableEntity implements Mong
     }
 
     @MongoField
+    public int getMaxFailureWaitSeconds() {
+        return maxFailureWaitSeconds;
+    }
+
+    public void setMaxFailureWaitSeconds(int maxFailureWaitSeconds) {
+        this.maxFailureWaitSeconds = maxFailureWaitSeconds;
+    }
+
+    @MongoField
+    public int getMinimumQuickLoginWaitSeconds() {
+        return minimumQuickLoginWaitSeconds;
+    }
+
+    public void setMinimumQuickLoginWaitSeconds(int minimumQuickLoginWaitSeconds) {
+        this.minimumQuickLoginWaitSeconds = minimumQuickLoginWaitSeconds;
+    }
+
+    @MongoField
+    public int getWaitIncrementSeconds() {
+        return waitIncrementSeconds;
+    }
+
+    public void setWaitIncrementSeconds(int waitIncrementSeconds) {
+        this.waitIncrementSeconds = waitIncrementSeconds;
+    }
+
+    @MongoField
+    public long getQuickLoginCheckMilliSeconds() {
+        return quickLoginCheckMilliSeconds;
+    }
+
+    public void setQuickLoginCheckMilliSeconds(long quickLoginCheckMilliSeconds) {
+        this.quickLoginCheckMilliSeconds = quickLoginCheckMilliSeconds;
+    }
+
+    @MongoField
+    public int getMaxDeltaTimeSeconds() {
+        return maxDeltaTimeSeconds;
+    }
+
+    public void setMaxDeltaTimeSeconds(int maxDeltaTimeSeconds) {
+        this.maxDeltaTimeSeconds = maxDeltaTimeSeconds;
+    }
+
+    @MongoField
+    public int getFailureFactor() {
+        return failureFactor;
+    }
+
+    public void setFailureFactor(int failureFactor) {
+        this.failureFactor = failureFactor;
+    }
+
+    @MongoField
     public String getPasswordPolicy() {
         return passwordPolicy;
     }
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 8692bf1..5645c57 100755
--- a/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java
+++ b/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java
@@ -23,13 +23,8 @@ import java.util.concurrent.TimeUnit;
 public class BruteForceProtector implements Runnable {
     protected static Logger logger = Logger.getLogger(BruteForceProtector.class);
 
-    protected int maxFailureWaitSeconds = 900;
-    protected int minimumQuickLoginWaitSeconds = 60;
-    protected int waitIncrementSeconds = 60;
-    protected long quickLoginCheckMilliSeconds = 1000;
-    protected long maxDeltaTimeMilliSeconds = 60 * 60 * 12 * 1000; // 12 hours
-    protected int failureFactor = 30;
     protected volatile boolean run = true;
+    protected int maxDeltaTimeSeconds = 60 * 60 * 12; // 12 hours
     protected KeycloakSessionFactory factory;
     protected CountDownLatch shutdownLatch = new CountDownLatch(1);
 
@@ -83,6 +78,8 @@ public class BruteForceProtector implements Runnable {
     }
 
     public void failure(KeycloakSession session, LoginEvent event) {
+        RealmModel realm = getRealmModel(session, event);
+        logFailure(event);
         UsernameLoginFailureModel user = getUserModel(session, event);
         if (user == null) return;
         user.setLastIPFailure(event.ip);
@@ -95,19 +92,19 @@ public class BruteForceProtector implements Runnable {
         user.setLastFailure(currentTime);
         if (deltaTime > 0) {
             // if last failure was more than MAX_DELTA clear failures
-            if (deltaTime > maxDeltaTimeMilliSeconds) {
+            if (deltaTime > (long)realm.getMaxDeltaTimeSeconds() *1000L) {
                 user.clearFailures();
             }
         }
         user.incrementFailures();
 
-        int waitSeconds = waitIncrementSeconds * (user.getNumFailures() / failureFactor);
+        int waitSeconds = realm.getWaitIncrementSeconds() * (user.getNumFailures() / realm.getFailureFactor());
         if (waitSeconds == 0) {
-            if (deltaTime > quickLoginCheckMilliSeconds) {
-                waitSeconds = minimumQuickLoginWaitSeconds;
+            if (deltaTime > realm.getQuickLoginCheckMilliSeconds()) {
+                waitSeconds = realm.getMinimumQuickLoginWaitSeconds();
             }
         }
-        waitSeconds = Math.min(maxFailureWaitSeconds, waitSeconds);
+        waitSeconds = Math.min(realm.getMaxFailureWaitSeconds(), waitSeconds);
         if (waitSeconds > 0) {
             user.setFailedLoginNotBefore((int) (currentTime / 1000) + waitSeconds);
         }
@@ -153,14 +150,6 @@ public class BruteForceProtector implements Runnable {
                 try {
                     events.add(take);
                     queue.drainTo(events, TRANSACTION_SIZE);
-                    for (LoginEvent event : events) {
-                        if (event instanceof FailedLogin) {
-                            logFailure(event);
-                        } else if (event instanceof SuccessfulLogin) {
-                            logSuccess(event);
-                        }
-                    }
-
                     Collections.sort(events); // we sort to avoid deadlock due to ordered updates.  Maybe I'm overthinking this.
                     KeycloakSession session = factory.createSession();
                     try {
@@ -203,7 +192,7 @@ public class BruteForceProtector implements Runnable {
         long delta = 0;
         if (lastFailure > 0) {
             delta = System.currentTimeMillis() - lastFailure;
-            if (delta > maxDeltaTimeMilliSeconds) {
+            if (delta > (long)maxDeltaTimeSeconds * 1000L) {
                 totalTime = 0;
 
             } else {
@@ -255,51 +244,5 @@ public class BruteForceProtector implements Runnable {
         return lastFailure;
     }
 
-    public int getMaxFailureWaitSeconds() {
-        return maxFailureWaitSeconds;
-    }
-
-    public void setMaxFailureWaitSeconds(int maxFailureWaitSeconds) {
-        this.maxFailureWaitSeconds = maxFailureWaitSeconds;
-    }
-
-    public int getMinimumQuickLoginWaitSeconds() {
-        return minimumQuickLoginWaitSeconds;
-    }
-
-    public void setMinimumQuickLoginWaitSeconds(int minimumQuickLoginWaitSeconds) {
-        this.minimumQuickLoginWaitSeconds = minimumQuickLoginWaitSeconds;
-    }
-
-    public int getWaitIncrementSeconds() {
-        return waitIncrementSeconds;
-    }
-
-    public void setWaitIncrementSeconds(int waitIncrementSeconds) {
-        this.waitIncrementSeconds = waitIncrementSeconds;
-    }
-
-    public long getQuickLoginCheckMilliSeconds() {
-        return quickLoginCheckMilliSeconds;
-    }
 
-    public void setQuickLoginCheckMilliSeconds(long quickLoginCheckMilliSeconds) {
-        this.quickLoginCheckMilliSeconds = quickLoginCheckMilliSeconds;
-    }
-
-    public long getMaxDeltaTimeMilliSeconds() {
-        return maxDeltaTimeMilliSeconds;
-    }
-
-    public void setMaxDeltaTimeMilliSeconds(long maxDeltaTimeMilliSeconds) {
-        this.maxDeltaTimeMilliSeconds = maxDeltaTimeMilliSeconds;
-    }
-
-    public int getFailureFactor() {
-        return failureFactor;
-    }
-
-    public void setFailureFactor(int failureFactor) {
-        this.failureFactor = failureFactor;
-    }
 }
diff --git a/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java b/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
index 24c09b2..197046b 100755
--- a/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
+++ b/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
@@ -79,6 +79,12 @@ public class ModelToRepresentation {
         rep.setRegistrationAllowed(realm.isRegistrationAllowed());
         rep.setRememberMe(realm.isRememberMe());
         rep.setBruteForceProtected(realm.isBruteForceProtected());
+        rep.setMaxFailureWaitSeconds(realm.getMaxFailureWaitSeconds());
+        rep.setMinimumQuickLoginWaitSeconds(realm.getMinimumQuickLoginWaitSeconds());
+        rep.setWaitIncrementSeconds(realm.getWaitIncrementSeconds());
+        rep.setQuickLoginCheckMilliSeconds(realm.getQuickLoginCheckMilliSeconds());
+        rep.setMaxDeltaTimeSeconds(realm.getMaxDeltaTimeSeconds());
+        rep.setFailureFactor(realm.getFailureFactor());
         rep.setVerifyEmail(realm.isVerifyEmail());
         rep.setResetPasswordAllowed(realm.isResetPasswordAllowed());
         rep.setAccessTokenLifespan(realm.getAccessTokenLifespan());
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index b710af6..f6e9beb 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -79,7 +79,9 @@ public class RealmManager {
         if (id == null) id = KeycloakModelUtils.generateId();
         RealmModel realm = identitySession.createRealm(id, name);
         realm.setName(name);
-        realm.setBruteForceProtected(false); // default settings off for now todo set it on
+
+        // setup defaults
+        setupRealmDefaults(realm);
 
         setupAdminManagement(realm);
         setupAccountManagement(realm);
@@ -89,6 +91,17 @@ public class RealmManager {
         return realm;
     }
 
+    protected void setupRealmDefaults(RealmModel realm) {
+        // brute force
+        realm.setBruteForceProtected(false); // default settings off for now todo set it on
+        realm.setMaxFailureWaitSeconds(900);
+        realm.setMinimumQuickLoginWaitSeconds(60);
+        realm.setWaitIncrementSeconds(60);
+        realm.setQuickLoginCheckMilliSeconds(1000);
+        realm.setMaxDeltaTimeSeconds(60 * 60 * 12); // 12 hours
+        realm.setFailureFactor(30);
+    }
+
     public boolean removeRealm(RealmModel realm) {
         boolean removed = identitySession.removeRealm(realm.getId());
 
@@ -123,6 +136,12 @@ public class RealmManager {
         if (rep.isEnabled() != null) realm.setEnabled(rep.isEnabled());
         if (rep.isSocial() != null) realm.setSocial(rep.isSocial());
         if (rep.isBruteForceProtected() != null) realm.setBruteForceProtected(rep.isBruteForceProtected());
+        if (rep.getMaxFailureWaitSeconds() != null) realm.setMaxFailureWaitSeconds(rep.getMaxFailureWaitSeconds());
+        if (rep.getMinimumQuickLoginWaitSeconds() != null) realm.setMinimumQuickLoginWaitSeconds(rep.getMinimumQuickLoginWaitSeconds());
+        if (rep.getWaitIncrementSeconds() != null) realm.setWaitIncrementSeconds(rep.getWaitIncrementSeconds());
+        if (rep.getQuickLoginCheckMilliSeconds() != null) realm.setQuickLoginCheckMilliSeconds(rep.getQuickLoginCheckMilliSeconds());
+        if (rep.getMaxDeltaTimeSeconds() != null) realm.setMaxDeltaTimeSeconds(rep.getMaxDeltaTimeSeconds());
+        if (rep.getFailureFactor() != null) realm.setFailureFactor(rep.getFailureFactor());
         if (rep.isRegistrationAllowed() != null) realm.setRegistrationAllowed(rep.isRegistrationAllowed());
         if (rep.isRememberMe() != null) realm.setRememberMe(rep.isRememberMe());
         if (rep.isVerifyEmail() != null) realm.setVerifyEmail(rep.isVerifyEmail());
@@ -230,6 +249,12 @@ public class RealmManager {
         if (rep.isEnabled() != null) newRealm.setEnabled(rep.isEnabled());
         if (rep.isSocial() != null) newRealm.setSocial(rep.isSocial());
         if (rep.isBruteForceProtected() != null) newRealm.setBruteForceProtected(rep.isBruteForceProtected());
+        if (rep.getMaxFailureWaitSeconds() != null) newRealm.setMaxFailureWaitSeconds(rep.getMaxFailureWaitSeconds());
+        if (rep.getMinimumQuickLoginWaitSeconds() != null) newRealm.setMinimumQuickLoginWaitSeconds(rep.getMinimumQuickLoginWaitSeconds());
+        if (rep.getWaitIncrementSeconds() != null) newRealm.setWaitIncrementSeconds(rep.getWaitIncrementSeconds());
+        if (rep.getQuickLoginCheckMilliSeconds() != null) newRealm.setQuickLoginCheckMilliSeconds(rep.getQuickLoginCheckMilliSeconds());
+        if (rep.getMaxDeltaTimeSeconds() != null) newRealm.setMaxDeltaTimeSeconds(rep.getMaxDeltaTimeSeconds());
+        if (rep.getFailureFactor() != null) newRealm.setFailureFactor(rep.getFailureFactor());
 
         if (rep.getNotBefore() != null) newRealm.setNotBefore(rep.getNotBefore());