keycloak-aplcache

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 44b024b..9c5e974 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
@@ -549,6 +549,12 @@ module.controller('RealmTokenDetailCtrl', function($scope, Realm, realm, $http, 
         $scope.realm.accessTokenLifespan = TimeUnit.convert($scope.realm.accessTokenLifespan, from, to);
     });
 
+    $scope.realm.centralLoginLifespanUnit = TimeUnit.autoUnit(realm.accessTokenLifespan);
+    $scope.realm.centralLoginLifespan = TimeUnit.toUnit(realm.centralLoginLifespan, $scope.realm.centralLoginLifespanUnit);
+    $scope.$watch('realm.centralLoginLifespanUnit', function(to, from) {
+        $scope.realm.centralLoginLifespan = TimeUnit.convert($scope.realm.centralLoginLifespan, from, to);
+    });
+
     $scope.realm.refreshTokenLifespanUnit = TimeUnit.autoUnit(realm.refreshTokenLifespan);
     $scope.realm.refreshTokenLifespan = TimeUnit.toUnit(realm.refreshTokenLifespan, $scope.realm.refreshTokenLifespanUnit);
     $scope.$watch('realm.refreshTokenLifespanUnit', function(to, from) {
@@ -582,6 +588,7 @@ module.controller('RealmTokenDetailCtrl', function($scope, Realm, realm, $http, 
         delete realmCopy["accessTokenLifespanUnit"];
         delete realmCopy["refreshTokenLifespanUnit"];
         delete realmCopy["accessCodeLifespanUnit"];
+        delete realmCopy["centralLoginLifespanUnit"];
         delete realmCopy["accessCodeLifespanUserActionUnit"];
 
         realmCopy.accessTokenLifespan = TimeUnit.toSeconds($scope.realm.accessTokenLifespan, $scope.realm.accessTokenLifespanUnit)
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-tokens.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-tokens.html
index 4e8ada4..ac83d09 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-tokens.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-tokens.html
@@ -10,6 +10,32 @@
         <h2><span>{{realm.realm}}</span> Token Settings</h2>
         <form class="form-horizontal" name="realmForm" novalidate>
             <fieldset class="border-top">
+                <div class="form-group">
+                    <label class="col-sm-2 control-label" for="rememberMe">Remember Me</label>
+                    <div class="col-sm-4">
+                        <input ng-model="realm.rememberMe" name="rememberMe" id="rememberMe" onoffswitch />
+                    </div>
+                </div>
+                <div class="form-group input-select">
+                    <label class="col-sm-2 control-label" for="centralLoginLifespan">Central Login lifespan</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.centralLoginLifespan"
+                                       id="centralLoginLifespan" name="centralLoginLifespan"/>
+                            </div>
+                            <div class="col-sm-2 select-kc">
+                                <select name="centralLoginLifespanUnit" data-ng-model="realm.centralLoginLifespanUnit" >
+                                    <option data-ng-selected="!realm.centralLoginLifespanUnit">Seconds</option>
+                                    <option>Minutes</option>
+                                    <option>Hours</option>
+                                    <option>Days</option>
+                                </select>
+                            </div>
+                        </div>
+                    </div>
+                </div>
                 <div class="form-group input-select">
                     <label class="col-sm-2 control-label" for="accessTokenLifespan">Access token lifespan</label>
                     <div class="col-sm-10">
@@ -67,7 +93,7 @@
                     </div>
                 </div>
                 <div class="form-group input-select">
-                    <label class="col-sm-2 control-label" for="refreshTokenLifespan">Refresh token lifespan {{realm.refreshTokenLifespan}}</label>
+                    <label class="col-sm-2 control-label" for="refreshTokenLifespan">Refresh token lifespan</label>
                     <div class="col-sm-10">
                         <div class="row">
                             <div class="col-sm-2">
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 acdca83..dbca874 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
@@ -15,11 +15,13 @@ public class RealmRepresentation {
     protected String realm;
     protected Integer accessTokenLifespan;
     protected Integer refreshTokenLifespan;
+    protected Integer centralLoginLifespan;
     protected Integer accessCodeLifespan;
     protected Integer accessCodeLifespanUserAction;
     protected Boolean enabled;
     protected Boolean sslNotRequired;
     protected Boolean registrationAllowed;
+    protected Boolean rememberMe;
     protected Boolean verifyEmail;
     protected Boolean resetPasswordAllowed;
     protected Boolean social;
@@ -127,6 +129,14 @@ public class RealmRepresentation {
         return refreshTokenLifespan;
     }
 
+    public Integer getCentralLoginLifespan() {
+        return centralLoginLifespan;
+    }
+
+    public void setCentralLoginLifespan(Integer centralLoginLifespan) {
+        this.centralLoginLifespan = centralLoginLifespan;
+    }
+
     public void setRefreshTokenLifespan(Integer refreshTokenLifespan) {
         this.refreshTokenLifespan = refreshTokenLifespan;
     }
@@ -231,6 +241,14 @@ public class RealmRepresentation {
         this.registrationAllowed = registrationAllowed;
     }
 
+    public Boolean isRememberMe() {
+        return rememberMe;
+    }
+
+    public void setRememberMe(Boolean rememberMe) {
+        this.rememberMe = rememberMe;
+    }
+
     public Boolean isVerifyEmail() {
         return verifyEmail;
     }
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 b5682ee..a49e269 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -29,6 +29,9 @@ public interface RealmModel extends RoleContainerModel, RoleMapperModel, ScopeMa
     boolean isRegistrationAllowed();
 
     void setRegistrationAllowed(boolean registrationAllowed);
+    boolean isRememberMe();
+
+    void setRememberMe(boolean rememberMe);
 
     boolean isVerifyEmail();
 
@@ -38,6 +41,10 @@ public interface RealmModel extends RoleContainerModel, RoleMapperModel, ScopeMa
 
     void setResetPasswordAllowed(boolean resetPasswordAllowed);
 
+    int getCentralLoginLifespan();
+
+    void setCentralLoginLifespan(int lifespan);
+
     int getAccessTokenLifespan();
 
     void setAccessTokenLifespan(int tokenLifespan);
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 e29b59d..d2e8370 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
@@ -38,11 +38,13 @@ public class RealmEntity {
     protected boolean verifyEmail;
     protected boolean resetPasswordAllowed;
     protected boolean social;
+    protected boolean rememberMe;
 
     @Column(name="updateProfileOnInitSocLogin")
     protected boolean updateProfileOnInitialSocialLogin;
     protected String passwordPolicy;
 
+    protected int centralLoginLifespan;
     protected int accessTokenLifespan;
     protected int accessCodeLifespan;
     protected int accessCodeLifespanUserAction;
@@ -130,6 +132,14 @@ public class RealmEntity {
         this.registrationAllowed = registrationAllowed;
     }
 
+    public boolean isRememberMe() {
+        return rememberMe;
+    }
+
+    public void setRememberMe(boolean rememberMe) {
+        this.rememberMe = rememberMe;
+    }
+
     public boolean isVerifyEmail() {
         return verifyEmail;
     }
@@ -162,6 +172,14 @@ public class RealmEntity {
         this.updateProfileOnInitialSocialLogin = updateProfileOnInitialSocialLogin;
     }
 
+    public int getCentralLoginLifespan() {
+        return centralLoginLifespan;
+    }
+
+    public void setCentralLoginLifespan(int centralLoginLifespan) {
+        this.centralLoginLifespan = centralLoginLifespan;
+    }
+
     public int getRefreshTokenLifespan() {
         return refreshTokenLifespan;
     }
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 dfa3800..a84b5d7 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
@@ -106,6 +106,17 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
+    public boolean isRememberMe() {
+        return realm.isRememberMe();
+    }
+
+    @Override
+    public void setRememberMe(boolean rememberMe) {
+        realm.setRememberMe(rememberMe);
+        em.flush();
+    }
+
+    @Override
     public boolean isVerifyEmail() {
         return realm.isVerifyEmail();
     }
@@ -139,6 +150,17 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
+    public int getCentralLoginLifespan() {
+        return realm.getCentralLoginLifespan();
+    }
+
+    @Override
+    public void setCentralLoginLifespan(int lifespan) {
+        realm.setCentralLoginLifespan(lifespan);
+        em.flush();
+    }
+
+    @Override
     public int getRefreshTokenLifespan() {
         return realm.getRefreshTokenLifespan();
     }
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 6e8cd8c..7192a6f 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
@@ -108,6 +108,18 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
     }
 
     @Override
+    public boolean isRememberMe() {
+        return realm.isRememberMe();
+    }
+
+    @Override
+    public void setRememberMe(boolean rememberMe) {
+        realm.setRememberMe(rememberMe);
+        updateRealm();
+    }
+
+
+    @Override
     public boolean isVerifyEmail() {
         return realm.isVerifyEmail();
     }
@@ -178,6 +190,18 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
     }
 
     @Override
+    public int getCentralLoginLifespan() {
+        return realm.getCentralLoginLifespan();
+    }
+
+    @Override
+    public void setCentralLoginLifespan(int lifespan) {
+        realm.setCentralLoginLifespan(lifespan);
+        updateRealm();
+    }
+
+
+    @Override
     public int getRefreshTokenLifespan() {
         return realm.getRefreshTokenLifespan();
     }
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 57fe31e..9147249 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
@@ -23,12 +23,14 @@ public class RealmEntity extends AbstractMongoIdentifiableEntity implements Mong
     private boolean enabled;
     private boolean sslNotRequired;
     private boolean registrationAllowed;
+    private boolean rememberMe;
     private boolean verifyEmail;
     private boolean resetPasswordAllowed;
     private boolean social;
     private boolean updateProfileOnInitialSocialLogin;
     private String passwordPolicy;
 
+    private int centralLoginLifespan;
     private int accessTokenLifespan;
     private int accessCodeLifespan;
     private int accessCodeLifespanUserAction;
@@ -87,6 +89,15 @@ public class RealmEntity extends AbstractMongoIdentifiableEntity implements Mong
     }
 
     @MongoField
+    public boolean isRememberMe() {
+        return rememberMe;
+    }
+
+    public void setRememberMe(boolean rememberMe) {
+        this.rememberMe = rememberMe;
+    }
+
+    @MongoField
     public boolean isVerifyEmail() {
         return verifyEmail;
     }
@@ -132,6 +143,15 @@ public class RealmEntity extends AbstractMongoIdentifiableEntity implements Mong
     }
 
     @MongoField
+    public int getCentralLoginLifespan() {
+        return centralLoginLifespan;
+    }
+
+    public void setCentralLoginLifespan(int centralLoginLifespan) {
+        this.centralLoginLifespan = centralLoginLifespan;
+    }
+
+    @MongoField
     public int getAccessTokenLifespan() {
         return accessTokenLifespan;
     }
diff --git a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
index ac95546..49ea96a 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
@@ -46,6 +46,7 @@ public class ApplianceBootstrap {
         realm.addRequiredCredential(CredentialRepresentation.PASSWORD);
         realm.addRequiredOAuthClientCredential(CredentialRepresentation.PASSWORD);
         realm.addRequiredResourceCredential(CredentialRepresentation.PASSWORD);
+        realm.setCentralLoginLifespan(3000);
         realm.setAccessTokenLifespan(60);
         realm.setRefreshTokenLifespan(3600);
         realm.setAccessCodeLifespan(60);
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index d8f4911..237b7dc 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -46,13 +46,12 @@ public class AuthenticationManager {
         token.issuedNow();
         token.subject(user.getId());
         token.audience(realm.getName());
-        if (realm.getAccessTokenLifespan() > 0) {
-            token.expiration((System.currentTimeMillis() / 1000) + realm.getAccessTokenLifespan());
+        if (realm.getCentralLoginLifespan() > 0) {
+            token.expiration((System.currentTimeMillis() / 1000) + realm.getCentralLoginLifespan());
         }
         return token;
     }
 
-
     public NewCookie createLoginCookie(RealmModel realm, UserModel user, UriInfo uriInfo) {
         String cookieName = KEYCLOAK_IDENTITY_COOKIE;
         String cookiePath = getIdentityCookiePath(realm, uriInfo);
@@ -80,7 +79,13 @@ public class AuthenticationManager {
         String encoded = encodeToken(realm, identityToken);
         boolean secureOnly = !realm.isSslNotRequired();
         logger.debug("creatingLoginCookie - name: {0} path: {1}", cookieName, cookiePath);
-        NewCookie cookie = new NewCookie(cookieName, encoded, cookiePath, null, null, NewCookie.DEFAULT_MAX_AGE, secureOnly, true);
+        int maxAge = NewCookie.DEFAULT_MAX_AGE;
+        /*
+        if (realm.isRememberMe()) {
+            maxAge = realm.getCentralLoginLifespan();
+        }
+        */
+        NewCookie cookie = new NewCookie(cookieName, encoded, cookiePath, null, null, maxAge, secureOnly, true);
         return cookie;
     }
 
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 afceb25..9bf9142 100755
--- a/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
+++ b/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
@@ -69,9 +69,11 @@ public class ModelToRepresentation {
         rep.setPublicKey(realm.getPublicKeyPem());
         rep.setPrivateKey(realm.getPrivateKeyPem());
         rep.setRegistrationAllowed(realm.isRegistrationAllowed());
+        rep.setRememberMe(realm.isRememberMe());
         rep.setVerifyEmail(realm.isVerifyEmail());
         rep.setResetPasswordAllowed(realm.isResetPasswordAllowed());
         rep.setAccessTokenLifespan(realm.getAccessTokenLifespan());
+        rep.setCentralLoginLifespan(realm.getCentralLoginLifespan());
         rep.setRefreshTokenLifespan(realm.getRefreshTokenLifespan());
         rep.setAccessCodeLifespan(realm.getAccessCodeLifespan());
         rep.setAccessCodeLifespanUserAction(realm.getAccessCodeLifespanUserAction());
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 d364d5b..4828002 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -97,6 +97,7 @@ public class RealmManager {
         if (rep.isEnabled() != null) realm.setEnabled(rep.isEnabled());
         if (rep.isSocial() != null) realm.setSocial(rep.isSocial());
         if (rep.isRegistrationAllowed() != null) realm.setRegistrationAllowed(rep.isRegistrationAllowed());
+        if (rep.isRememberMe() != null) realm.setRememberMe(rep.isRememberMe());
         if (rep.isVerifyEmail() != null) realm.setVerifyEmail(rep.isVerifyEmail());
         if (rep.isResetPasswordAllowed() != null) realm.setResetPasswordAllowed(rep.isResetPasswordAllowed());
         if (rep.isUpdateProfileOnInitialSocialLogin() != null)
@@ -107,6 +108,7 @@ public class RealmManager {
             realm.setAccessCodeLifespanUserAction(rep.getAccessCodeLifespanUserAction());
         if (rep.getAccessTokenLifespan() != null) realm.setAccessTokenLifespan(rep.getAccessTokenLifespan());
         if (rep.getRefreshTokenLifespan() != null) realm.setRefreshTokenLifespan(rep.getRefreshTokenLifespan());
+        if (rep.getCentralLoginLifespan() != null) realm.setCentralLoginLifespan(rep.getCentralLoginLifespan());
         if (rep.getRequiredCredentials() != null) {
             realm.updateRequiredCredentials(rep.getRequiredCredentials());
         }
@@ -163,7 +165,9 @@ public class RealmManager {
         else newRealm.setAccessTokenLifespan(300);
 
         if (rep.getRefreshTokenLifespan() != null) newRealm.setRefreshTokenLifespan(rep.getRefreshTokenLifespan());
-        else newRealm.setRefreshTokenLifespan(3600);
+        else newRealm.setRefreshTokenLifespan(36000);
+        if (rep.getCentralLoginLifespan() != null) newRealm.setCentralLoginLifespan(rep.getCentralLoginLifespan());
+        else newRealm.setCentralLoginLifespan(300);
 
         if (rep.getAccessCodeLifespan() != null) newRealm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
         else newRealm.setAccessCodeLifespan(60);
@@ -174,6 +178,7 @@ public class RealmManager {
 
         if (rep.isSslNotRequired() != null) newRealm.setSslNotRequired(rep.isSslNotRequired());
         if (rep.isRegistrationAllowed() != null) newRealm.setRegistrationAllowed(rep.isRegistrationAllowed());
+        if (rep.isRememberMe() != null) newRealm.setRememberMe(rep.isRememberMe());
         if (rep.isVerifyEmail() != null) newRealm.setVerifyEmail(rep.isVerifyEmail());
         if (rep.isResetPasswordAllowed() != null) newRealm.setResetPasswordAllowed(rep.isResetPasswordAllowed());
         if (rep.isUpdateProfileOnInitialSocialLogin() != null)
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
index 335bef2..6483823 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
@@ -57,6 +57,7 @@ public class CompositeRoleTest {
             RealmModel realm = manager.createRealm("Test");
             manager.generateRealmKeys(realm);
             realmPublicKey = realm.getPublicKey();
+            realm.setCentralLoginLifespan(3000);
             realm.setAccessTokenLifespan(10000);
             realm.setRefreshTokenLifespan(10000);
             realm.setAccessCodeLifespanUserAction(1000);