keycloak-aplcache

Changes

Details

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 382be7c..74b9b36 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
@@ -11,13 +11,13 @@
         <form class="form-horizontal" name="realmForm" novalidate>
             <fieldset class="border-top">
                 <div class="form-group input-select">
-                    <label class="col-sm-2 control-label" for="tokenLifespan">Token lifespan</label>
+                    <label class="col-sm-2 control-label" for="accessTokenLifespan">Access Token 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.tokenLifespan"
-                                       id="tokenLifespan" name="tokenLifespan"/>
+                                       max="31536000" data-ng-model="realm.accessTokenLifespan"
+                                       id="accessTokenLifespan" name="accessTokenLifespan"/>
                             </div>
                             <div class="col-sm-2 select-kc">
                                 <select name="tokenLifespanUnit" data-ng-model="realm.tokenLifespanUnit" >
diff --git a/core/src/main/java/org/keycloak/representations/AccessToken.java b/core/src/main/java/org/keycloak/representations/AccessToken.java
index fd93257..8341c57 100755
--- a/core/src/main/java/org/keycloak/representations/AccessToken.java
+++ b/core/src/main/java/org/keycloak/representations/AccessToken.java
@@ -19,6 +19,19 @@ public class AccessToken extends JsonWebToken {
         @JsonProperty("verify_caller")
         protected Boolean verifyCaller;
 
+        public Access() {
+        }
+
+        public Access clone() {
+            Access access = new Access();
+            access.verifyCaller = verifyCaller;
+            if (roles != null) {
+                access.roles = new HashSet<String>();
+                access.roles.addAll(roles);
+            }
+            return access;
+        }
+
         public Set<String> getRoles() {
             return roles;
         }
diff --git a/core/src/main/java/org/keycloak/representations/idm/PublishedRealmRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/PublishedRealmRepresentation.java
index 904b692..4f1f2ea 100755
--- a/core/src/main/java/org/keycloak/representations/idm/PublishedRealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/PublishedRealmRepresentation.java
@@ -29,9 +29,6 @@ public class PublishedRealmRepresentation {
     @JsonProperty("grants")
     protected String grantUrl;
 
-    @JsonProperty("identity-grants")
-    protected String identityGrantUrl;
-
     @JsonProperty("admin-role")
     protected String adminRole;
 
@@ -124,12 +121,4 @@ public class PublishedRealmRepresentation {
     public void setGrantUrl(String grantUrl) {
         this.grantUrl = grantUrl;
     }
-
-    public String getIdentityGrantUrl() {
-        return identityGrantUrl;
-    }
-
-    public void setIdentityGrantUrl(String identityGrantUrl) {
-        this.identityGrantUrl = identityGrantUrl;
-    }
 }
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 e11dc57..e4d70bb 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
@@ -13,7 +13,7 @@ public class RealmRepresentation {
     protected String self; // link
     protected String id;
     protected String realm;
-    protected Integer tokenLifespan;
+    protected Integer accessTokenLifespan;
     protected Integer accessCodeLifespan;
     protected Integer accessCodeLifespanUserAction;
     protected Boolean enabled;
@@ -114,12 +114,12 @@ public class RealmRepresentation {
         this.sslNotRequired = sslNotRequired;
     }
 
-    public Integer getTokenLifespan() {
-        return tokenLifespan;
+    public Integer getAccessTokenLifespan() {
+        return accessTokenLifespan;
     }
 
-    public void setTokenLifespan(Integer tokenLifespan) {
-        this.tokenLifespan = tokenLifespan;
+    public void setAccessTokenLifespan(Integer accessTokenLifespan) {
+        this.accessTokenLifespan = accessTokenLifespan;
     }
 
     public List<UserRoleMappingRepresentation> getRoleMappings() {
diff --git a/core/src/main/java/org/keycloak/representations/RefreshToken.java b/core/src/main/java/org/keycloak/representations/RefreshToken.java
new file mode 100755
index 0000000..7d90931
--- /dev/null
+++ b/core/src/main/java/org/keycloak/representations/RefreshToken.java
@@ -0,0 +1,36 @@
+package org.keycloak.representations;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RefreshToken extends AccessToken {
+    public RefreshToken() {
+        type("REFRESH");
+    }
+
+    /**
+     * Deep copies issuer, subject, issuedFor, realmAccess, and resourceAccess
+     * from AccessToken.
+     *
+     * @param token
+     */
+    public RefreshToken(AccessToken token) {
+        this();
+        this.issuer = token.issuer;
+        this.subject = token.subject;
+        this.issuedFor = token.issuedFor;
+        if (token.realmAccess != null) {
+            realmAccess = token.realmAccess.clone();
+        }
+        if (token.resourceAccess != null) {
+            resourceAccess = new HashMap<String, Access>();
+            for (Map.Entry<String, Access> entry : token.resourceAccess.entrySet()) {
+                resourceAccess.put(entry.getKey(), entry.getValue().clone());
+            }
+        }
+    }
+}
diff --git a/examples/demo-template/testrealm.json b/examples/demo-template/testrealm.json
index 1183de8..9f0fb13 100755
--- a/examples/demo-template/testrealm.json
+++ b/examples/demo-template/testrealm.json
@@ -1,7 +1,7 @@
 {
     "realm": "demo",
     "enabled": true,
-    "tokenLifespan": 3000,
+    "accessTokenLifespan": 3000,
     "accessCodeLifespan": 10,
     "accessCodeLifespanUserAction": 6000,
     "sslNotRequired": true,
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 6f22121..a0aad37 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -38,9 +38,13 @@ public interface RealmModel extends RoleContainerModel, RoleMapperModel, ScopeMa
 
     void setResetPasswordAllowed(boolean resetPasswordAllowed);
 
-    int getTokenLifespan();
+    int getAccessTokenLifespan();
 
-    void setTokenLifespan(int tokenLifespan);
+    void setAccessTokenLifespan(int tokenLifespan);
+
+    int getRefreshTokenLifespan();
+
+    void setRefreshTokenLifespan(int tokenLifespan);
 
     int getAccessCodeLifespan();
 
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 e6967e3..d744bff 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
@@ -43,9 +43,10 @@ public class RealmEntity {
     protected boolean updateProfileOnInitialSocialLogin;
     protected String passwordPolicy;
 
-    protected int tokenLifespan;
+    protected int accessTokenLifespan;
     protected int accessCodeLifespan;
     protected int accessCodeLifespanUserAction;
+    protected int refreshTokenLifespan;
 
     @Column(length = 2048)
     protected String publicKeyPem;
@@ -161,12 +162,20 @@ public class RealmEntity {
         this.updateProfileOnInitialSocialLogin = updateProfileOnInitialSocialLogin;
     }
 
-    public int getTokenLifespan() {
-        return tokenLifespan;
+    public int getRefreshTokenLifespan() {
+        return refreshTokenLifespan;
     }
 
-    public void setTokenLifespan(int tokenLifespan) {
-        this.tokenLifespan = tokenLifespan;
+    public void setRefreshTokenLifespan(int refreshTokenLifespan) {
+        this.refreshTokenLifespan = refreshTokenLifespan;
+    }
+
+    public int getAccessTokenLifespan() {
+        return accessTokenLifespan;
+    }
+
+    public void setAccessTokenLifespan(int accessTokenLifespan) {
+        this.accessTokenLifespan = accessTokenLifespan;
     }
 
     public int getAccessCodeLifespan() {
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 a4a6cb7..608788e 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
@@ -128,13 +128,24 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
-    public int getTokenLifespan() {
-        return realm.getTokenLifespan();
+    public int getAccessTokenLifespan() {
+        return realm.getAccessTokenLifespan();
     }
 
     @Override
-    public void setTokenLifespan(int tokenLifespan) {
-        realm.setTokenLifespan(tokenLifespan);
+    public void setAccessTokenLifespan(int tokenLifespan) {
+        realm.setAccessTokenLifespan(tokenLifespan);
+        em.flush();
+    }
+
+    @Override
+    public int getRefreshTokenLifespan() {
+        return realm.getRefreshTokenLifespan();
+    }
+
+    @Override
+    public void setRefreshTokenLifespan(int tokenLifespan) {
+        realm.setRefreshTokenLifespan(tokenLifespan);
         em.flush();
     }
 
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 91aa0bf..06991cc 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
@@ -167,13 +167,24 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
     }
 
     @Override
-    public int getTokenLifespan() {
-        return realm.getTokenLifespan();
+    public int getAccessTokenLifespan() {
+        return realm.getAccessTokenLifespan();
     }
 
     @Override
-    public void setTokenLifespan(int tokenLifespan) {
-        realm.setTokenLifespan(tokenLifespan);
+    public void setAccessTokenLifespan(int tokenLifespan) {
+        realm.setAccessTokenLifespan(tokenLifespan);
+        updateRealm();
+    }
+
+    @Override
+    public int getRefreshTokenLifespan() {
+        return realm.getRefreshTokenLifespan();
+    }
+
+    @Override
+    public void setRefreshTokenLifespan(int tokenLifespan) {
+        realm.setRefreshTokenLifespan(tokenLifespan);
         updateRealm();
     }
 
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 6ee2fdf..57fe31e 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
@@ -29,9 +29,10 @@ public class RealmEntity extends AbstractMongoIdentifiableEntity implements Mong
     private boolean updateProfileOnInitialSocialLogin;
     private String passwordPolicy;
 
-    private int tokenLifespan;
+    private int accessTokenLifespan;
     private int accessCodeLifespan;
     private int accessCodeLifespanUserAction;
+    private int refreshTokenLifespan;
 
     private String publicKeyPem;
     private String privateKeyPem;
@@ -131,12 +132,21 @@ public class RealmEntity extends AbstractMongoIdentifiableEntity implements Mong
     }
 
     @MongoField
-    public int getTokenLifespan() {
-        return tokenLifespan;
+    public int getAccessTokenLifespan() {
+        return accessTokenLifespan;
     }
 
-    public void setTokenLifespan(int tokenLifespan) {
-        this.tokenLifespan = tokenLifespan;
+    public void setAccessTokenLifespan(int accessTokenLifespan) {
+        this.accessTokenLifespan = accessTokenLifespan;
+    }
+
+    @MongoField
+    public int getRefreshTokenLifespan() {
+        return refreshTokenLifespan;
+    }
+
+    public void setRefreshTokenLifespan(int refreshTokenLifespan) {
+        this.refreshTokenLifespan = refreshTokenLifespan;
     }
 
     @MongoField
diff --git a/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java b/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java
index cd18852..ea6fa66 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java
@@ -47,7 +47,7 @@ public class AdapterTest extends AbstractModelTest {
         realmModel.setName("JUGGLER");
         realmModel.setPrivateKeyPem("0234234");
         realmModel.setPublicKeyPem("0234234");
-        realmModel.setTokenLifespan(1000);
+        realmModel.setAccessTokenLifespan(1000);
         realmModel.setUpdateProfileOnInitialSocialLogin(true);
         realmModel.addDefaultRole("foo");
 
@@ -56,7 +56,7 @@ public class AdapterTest extends AbstractModelTest {
         Assert.assertNotNull(realmModel);
         Assert.assertEquals(realmModel.getAccessCodeLifespan(), 100);
         Assert.assertEquals(600, realmModel.getAccessCodeLifespanUserAction());
-        Assert.assertEquals(realmModel.getTokenLifespan(), 1000);
+        Assert.assertEquals(realmModel.getAccessTokenLifespan(), 1000);
         Assert.assertEquals(realmModel.isEnabled(), true);
         Assert.assertEquals(realmModel.getName(), "JUGGLER");
         Assert.assertEquals(realmModel.getPrivateKeyPem(), "0234234");
@@ -75,7 +75,7 @@ public class AdapterTest extends AbstractModelTest {
         realmModel.setName("JUGGLER");
         realmModel.setPrivateKeyPem("0234234");
         realmModel.setPublicKeyPem("0234234");
-        realmModel.setTokenLifespan(1000);
+        realmModel.setAccessTokenLifespan(1000);
         realmModel.setUpdateProfileOnInitialSocialLogin(true);
         realmModel.addDefaultRole("foo");
 
@@ -84,7 +84,7 @@ public class AdapterTest extends AbstractModelTest {
         Assert.assertNotNull(realmModel);
         Assert.assertEquals(realmModel.getAccessCodeLifespan(), 100);
         Assert.assertEquals(600, realmModel.getAccessCodeLifespanUserAction());
-        Assert.assertEquals(realmModel.getTokenLifespan(), 1000);
+        Assert.assertEquals(realmModel.getAccessTokenLifespan(), 1000);
         Assert.assertEquals(realmModel.isEnabled(), true);
         Assert.assertEquals(realmModel.getName(), "JUGGLER");
         Assert.assertEquals(realmModel.getPrivateKeyPem(), "0234234");
diff --git a/model/tests/src/test/java/org/keycloak/model/test/AuthenticationManagerTest.java b/model/tests/src/test/java/org/keycloak/model/test/AuthenticationManagerTest.java
index 324802b..c4d316c 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/AuthenticationManagerTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/AuthenticationManagerTest.java
@@ -127,7 +127,7 @@ public class AuthenticationManagerTest extends AbstractModelTest {
         realm.setName("Test");
         realm.setPrivateKeyPem("0234234");
         realm.setPublicKeyPem("0234234");
-        realm.setTokenLifespan(1000);
+        realm.setAccessTokenLifespan(1000);
         realm.addRequiredCredential(CredentialRepresentation.PASSWORD);
 
         am = new AuthenticationManager();
diff --git a/model/tests/src/test/java/org/keycloak/model/test/ModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/ModelTest.java
index bdc7d3b..33e8490 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/ModelTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/ModelTest.java
@@ -22,7 +22,7 @@ public class ModelTest extends AbstractModelTest {
         realm.setSocial(true);
         realm.setSslNotRequired(true);
         realm.setVerifyEmail(true);
-        realm.setTokenLifespan(1000);
+        realm.setAccessTokenLifespan(1000);
         realm.setPasswordPolicy(new PasswordPolicy("length"));
         realm.setAccessCodeLifespan(1001);
         realm.setAccessCodeLifespanUserAction(1002);
@@ -55,7 +55,7 @@ public class ModelTest extends AbstractModelTest {
         Assert.assertEquals(expected.isSocial(), actual.isSocial());
         Assert.assertEquals(expected.isSslNotRequired(), actual.isSslNotRequired());
         Assert.assertEquals(expected.isVerifyEmail(), actual.isVerifyEmail());
-        Assert.assertEquals(expected.getTokenLifespan(), actual.getTokenLifespan());
+        Assert.assertEquals(expected.getAccessTokenLifespan(), actual.getAccessTokenLifespan());
 
         Assert.assertEquals(expected.getAccessCodeLifespan(), actual.getAccessCodeLifespan());
         Assert.assertEquals(expected.getAccessCodeLifespanUserAction(), actual.getAccessCodeLifespanUserAction());
diff --git a/model/tests/src/test/resources/testcomposites.json b/model/tests/src/test/resources/testcomposites.json
index 2ac02ce..6c11b4e 100755
--- a/model/tests/src/test/resources/testcomposites.json
+++ b/model/tests/src/test/resources/testcomposites.json
@@ -2,7 +2,7 @@
     "id": "Test",
     "realm": "Test",
     "enabled": true,
-    "tokenLifespan": 600,
+    "accessTokenLifespan": 600,
     "accessCodeLifespan": 600,
     "accessCodeLifespanUserAction": 600,
     "sslNotRequired": true,
diff --git a/model/tests/src/test/resources/testrealm.json b/model/tests/src/test/resources/testrealm.json
index a78c234..e1148da 100755
--- a/model/tests/src/test/resources/testrealm.json
+++ b/model/tests/src/test/resources/testrealm.json
@@ -1,7 +1,7 @@
 {
     "realm": "test-realm",
     "enabled": true,
-    "tokenLifespan": 6000,
+    "accessTokenLifespan": 6000,
     "accessCodeLifespan": 30,
     "accessCodeLifespanUserAction": 600,
     "requiredCredentials": [ "password" ],
diff --git a/model/tests/src/test/resources/testrealm-demo.json b/model/tests/src/test/resources/testrealm-demo.json
index 7cf1072..136a144 100755
--- a/model/tests/src/test/resources/testrealm-demo.json
+++ b/model/tests/src/test/resources/testrealm-demo.json
@@ -1,7 +1,7 @@
 {
     "realm": "demo",
     "enabled": true,
-    "tokenLifespan": 300,
+    "accessTokenLifespan": 300,
     "accessCodeLifespan": 10,
     "accessCodeLifespanUserAction": 600,
     "sslNotRequired": true,
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 f4ea7df..93a8e47 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
@@ -11,8 +11,6 @@ import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.representations.idm.CredentialRepresentation;
 
-import java.util.UUID;
-
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
@@ -48,7 +46,7 @@ public class ApplianceBootstrap {
         realm.addRequiredCredential(CredentialRepresentation.PASSWORD);
         realm.addRequiredOAuthClientCredential(CredentialRepresentation.PASSWORD);
         realm.addRequiredResourceCredential(CredentialRepresentation.PASSWORD);
-        realm.setTokenLifespan(300);
+        realm.setAccessTokenLifespan(300);
         realm.setAccessCodeLifespan(60);
         realm.setAccessCodeLifespanUserAction(300);
         realm.setSslNotRequired(true);
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 7d48d3e..14adb6b 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -46,8 +46,8 @@ public class AuthenticationManager {
         token.issuedNow();
         token.subject(user.getId());
         token.audience(realm.getName());
-        if (realm.getTokenLifespan() > 0) {
-            token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan());
+        if (realm.getAccessTokenLifespan() > 0) {
+            token.expiration((System.currentTimeMillis() / 1000) + realm.getAccessTokenLifespan());
         }
         return token;
     }
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 d2bacba..c9e921b 100755
--- a/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
+++ b/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
@@ -71,7 +71,7 @@ public class ModelToRepresentation {
         rep.setRegistrationAllowed(realm.isRegistrationAllowed());
         rep.setVerifyEmail(realm.isVerifyEmail());
         rep.setResetPasswordAllowed(realm.isResetPasswordAllowed());
-        rep.setTokenLifespan(realm.getTokenLifespan());
+        rep.setAccessTokenLifespan(realm.getAccessTokenLifespan());
         rep.setAccessCodeLifespan(realm.getAccessCodeLifespan());
         rep.setAccessCodeLifespanUserAction(realm.getAccessCodeLifespanUserAction());
         rep.setSmtpServer(realm.getSmtpConfig());
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 5cc26ce..4148ca0 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -7,7 +7,6 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.PasswordPolicy;
 import org.keycloak.models.RealmModel;
-import org.keycloak.models.RequiredCredentialModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.SocialLinkModel;
 import org.keycloak.models.UserCredentialModel;
@@ -28,14 +27,10 @@ import org.keycloak.representations.idm.UserRoleMappingRepresentation;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * Per request object
@@ -110,7 +105,7 @@ public class RealmManager {
         if (rep.getAccessCodeLifespan() != null) realm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
         if (rep.getAccessCodeLifespanUserAction() != null)
             realm.setAccessCodeLifespanUserAction(rep.getAccessCodeLifespanUserAction());
-        if (rep.getTokenLifespan() != null) realm.setTokenLifespan(rep.getTokenLifespan());
+        if (rep.getAccessTokenLifespan() != null) realm.setAccessTokenLifespan(rep.getAccessTokenLifespan());
         if (rep.getRequiredCredentials() != null) {
             realm.updateRequiredCredentials(rep.getRequiredCredentials());
         }
@@ -163,8 +158,8 @@ public class RealmManager {
         if (rep.isEnabled() != null) newRealm.setEnabled(rep.isEnabled());
         if (rep.isSocial() != null) newRealm.setSocial(rep.isSocial());
 
-        if (rep.getTokenLifespan() != null) newRealm.setTokenLifespan(rep.getTokenLifespan());
-        else newRealm.setTokenLifespan(300);
+        if (rep.getAccessTokenLifespan() != null) newRealm.setAccessTokenLifespan(rep.getAccessTokenLifespan());
+        else newRealm.setAccessTokenLifespan(300);
 
         if (rep.getAccessCodeLifespan() != null) newRealm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
         else newRealm.setAccessCodeLifespan(60);
diff --git a/services/src/main/java/org/keycloak/services/managers/TokenManager.java b/services/src/main/java/org/keycloak/services/managers/TokenManager.java
index f6555a0..74b5bd4 100755
--- a/services/src/main/java/org/keycloak/services/managers/TokenManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/TokenManager.java
@@ -12,10 +12,12 @@ import org.keycloak.representations.AccessToken;
 import org.keycloak.util.Base64Url;
 import org.keycloak.util.JsonSerialization;
 
+import javax.ws.rs.core.MultivaluedHashMap;
 import javax.ws.rs.core.MultivaluedMap;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -78,12 +80,44 @@ public class TokenManager {
 
 
     public AccessCodeEntry createAccessCode(String scopeParam, String state, String redirect, RealmModel realm, UserModel client, UserModel user) {
+        AccessCodeEntry code = createAccessCodeEntry(scopeParam, state, redirect, realm, client, user);
+        accessCodeMap.put(code.getId(), code);
+        return code;
+    }
+
+    private AccessCodeEntry createAccessCodeEntry(String scopeParam, String state, String redirect, RealmModel realm, UserModel client, UserModel user) {
         AccessCodeEntry code = new AccessCodeEntry();
-        AccessScope scopeMap = null;
-        if (scopeParam != null) scopeMap = decodeScope(scopeParam);
         List<RoleModel> realmRolesRequested = code.getRealmRolesRequested();
         MultivaluedMap<String, RoleModel> resourceRolesRequested = code.getResourceRolesRequested();
 
+        AccessToken token = createClientAccessToken(scopeParam, realm, client, user, realmRolesRequested, resourceRolesRequested);
+
+        code.setToken(token);
+        code.setRealm(realm);
+        code.setExpiration((System.currentTimeMillis() / 1000) + realm.getAccessCodeLifespan());
+        code.setClient(client);
+        code.setUser(user);
+        code.setState(state);
+        code.setRedirectUri(redirect);
+        String accessCode = null;
+        try {
+            accessCode = new JWSBuilder().content(code.getId().getBytes("UTF-8")).rsa256(realm.getPrivateKey());
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+        code.setCode(accessCode);
+        return code;
+    }
+
+    public AccessToken createClientAccessToken(String scopeParam, RealmModel realm, UserModel client, UserModel user) {
+        return createClientAccessToken(scopeParam, realm, client, user, new LinkedList<RoleModel>(), new MultivaluedHashMap<String, RoleModel>());
+    }
+
+
+    public AccessToken createClientAccessToken(String scopeParam, RealmModel realm, UserModel client, UserModel user, List<RoleModel> realmRolesRequested, MultivaluedMap<String, RoleModel> resourceRolesRequested) {
+        AccessScope scopeMap = null;
+        if (scopeParam != null) scopeMap = decodeScope(scopeParam);
+
 
         Set<RoleModel> roleMappings = realm.getRoleMappings(user);
         Set<RoleModel> scopeMappings = realm.getScopeMappings(client);
@@ -113,22 +147,22 @@ public class TokenManager {
             }
         }
 
-        createToken(code, realm, client, user);
-        code.setRealm(realm);
-        code.setExpiration((System.currentTimeMillis() / 1000) + realm.getAccessCodeLifespan());
-        code.setClient(client);
-        code.setUser(user);
-        code.setState(state);
-        code.setRedirectUri(redirect);
-        accessCodeMap.put(code.getId(), code);
-        String accessCode = null;
-        try {
-            accessCode = new JWSBuilder().content(code.getId().getBytes("UTF-8")).rsa256(realm.getPrivateKey());
-        } catch (UnsupportedEncodingException e) {
-            throw new RuntimeException(e);
+        AccessToken token = initToken(realm, client, user);
+
+        if (realmRolesRequested.size() > 0) {
+            for (RoleModel role : realmRolesRequested) {
+                addComposites(token, role);
+            }
         }
-        code.setCode(accessCode);
-        return code;
+
+        if (resourceRolesRequested.size() > 0) {
+            for (List<RoleModel> roles : resourceRolesRequested.values()) {
+                for (RoleModel role : roles) {
+                    addComposites(token, role);
+                }
+            }
+        }
+        return token;
     }
 
     protected AccessToken initToken(RealmModel realm, UserModel client, UserModel user) {
@@ -138,8 +172,8 @@ public class TokenManager {
         token.audience(realm.getName());
         token.issuedNow();
         token.issuedFor(client.getLoginName());
-        if (realm.getTokenLifespan() > 0) {
-            token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan());
+        if (realm.getAccessTokenLifespan() > 0) {
+            token.expiration((System.currentTimeMillis() / 1000) + realm.getAccessTokenLifespan());
         }
         Set<String> allowedOrigins = client.getWebOrigins();
         if (allowedOrigins != null) {
@@ -176,26 +210,6 @@ public class TokenManager {
 
     }
 
-    protected void createToken(AccessCodeEntry accessCodeEntry, RealmModel realm, UserModel client, UserModel user) {
-
-        AccessToken token = initToken(realm, client, user);
-
-        if (accessCodeEntry.getRealmRolesRequested().size() > 0) {
-            for (RoleModel role : accessCodeEntry.getRealmRolesRequested()) {
-                addComposites(token, role);
-            }
-        }
-
-        if (accessCodeEntry.getResourceRolesRequested().size() > 0) {
-            for (List<RoleModel> roles : accessCodeEntry.getResourceRolesRequested().values()) {
-                for (RoleModel role : roles) {
-                    addComposites(token, role);
-                }
-            }
-        }
-        accessCodeEntry.setToken(token);
-    }
-
     public String encodeScope(AccessScope scope) {
         String token = null;
         try {
@@ -224,8 +238,8 @@ public class TokenManager {
         token.issuedNow();
         token.subject(user.getId());
         token.audience(realm.getName());
-        if (realm.getTokenLifespan() > 0) {
-            token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan());
+        if (realm.getAccessTokenLifespan() > 0) {
+            token.expiration((System.currentTimeMillis() / 1000) + realm.getAccessTokenLifespan());
         }
         for (RoleModel role : realm.getRoleMappings(user)) {
             addComposites(token, role);
diff --git a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
index 1b699aa..944f1a9 100755
--- a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
@@ -53,13 +53,11 @@ public class PublicRealmResource {
         String authUri = TokenService.loginPageUrl(uriInfo).build(realm.getName()).toString();
         String codeUri = TokenService.accessCodeToTokenUrl(uriInfo).build(realm.getName()).toString();
         String grantUrl = TokenService.grantAccessTokenUrl(uriInfo).build(realm.getName()).toString();
-        String idGrantUrl = TokenService.grantIdentityTokenUrl(uriInfo).build(realm.getName()).toString();
 
         html.append("<html><body><h1>Realm: ").append(realm.getName()).append("</h1>");
         html.append("<p>auth: ").append(authUri).append("</p>");
         html.append("<p>code: ").append(codeUri).append("</p>");
         html.append("<p>grant: ").append(grantUrl).append("</p>");
-        html.append("<p>identity grant: ").append(idGrantUrl).append("</p>");
         html.append("<p>public key: ").append(realm.getPublicKeyPem()).append("</p>");
         html.append("</body></html>");
 
@@ -77,8 +75,6 @@ public class PublicRealmResource {
         rep.setAuthorizationUrl(TokenService.loginPageUrl(uriInfo).build(realm.getName()).toString());
         rep.setCodeUrl(TokenService.accessCodeToTokenUrl(uriInfo).build(realm.getName()).toString());
         rep.setGrantUrl(TokenService.grantAccessTokenUrl(uriInfo).build(realm.getName()).toString());
-        String idGrantUrl = TokenService.grantIdentityTokenUrl(uriInfo).build(realm.getName()).toString();
-        rep.setIdentityGrantUrl(idGrantUrl);
         return rep;
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/TokenService.java b/services/src/main/java/org/keycloak/services/resources/TokenService.java
index cf86534..f38c985 100755
--- a/services/src/main/java/org/keycloak/services/resources/TokenService.java
+++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java
@@ -29,6 +29,7 @@ import org.keycloak.services.resources.flows.OAuthFlows;
 import org.keycloak.services.validation.Validation;
 import org.keycloak.util.BasicAuthHelper;
 
+import javax.ws.rs.BadRequestException;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
 import javax.ws.rs.HeaderParam;
@@ -108,11 +109,6 @@ public class TokenService {
 
     }
 
-    public static UriBuilder grantIdentityTokenUrl(UriInfo uriInfo) {
-        return tokenServiceBaseUrl(uriInfo).path(TokenService.class, "grantIdentityToken");
-
-    }
-
     public static UriBuilder loginPageUrl(UriInfo uriInfo) {
         return tokenServiceBaseUrl(uriInfo).path(TokenService.class, "loginPage");
     }
@@ -129,44 +125,18 @@ public class TokenService {
         return tokenServiceBaseUrl(uriInfo).path(TokenService.class, "processOAuth");
     }
 
-    @Path("grants/identity-token")
+    @Path("grants/access")
     @POST
     @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
     @Produces(MediaType.APPLICATION_JSON)
-    public Response grantIdentityToken(final MultivaluedMap<String, String> form) {
+    public Response grantAccessToken(final @HeaderParam(HttpHeaders.AUTHORIZATION) String authorizationHeader,
+                                     final MultivaluedMap<String, String> form) {
         if (!checkSsl()) {
             throw new NotAcceptableException("HTTPS required");
         }
 
-        String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
-        if (username == null) {
-            throw new NotAuthorizedException("No user");
-        }
-        if (!realm.isEnabled()) {
-            throw new NotAuthorizedException("Disabled realm");
-        }
-        UserModel user = realm.getUser(username);
-
-        AuthenticationStatus status = authManager.authenticateForm(realm, user, form);
-        if (status != AuthenticationStatus.SUCCESS) {
-            throw new NotAuthorizedException(status);
-        }
-
-        tokenManager = new TokenManager();
-        AccessToken token = authManager.createIdentityToken(realm, user);
-        String encoded = tokenManager.encodeToken(realm, token);
-        AccessTokenResponse res = accessTokenResponse(token, encoded);
-        return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
-    }
+        UserModel client = authorizeClient(authorizationHeader);
 
-    @Path("grants/access")
-    @POST
-    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response grantAccessToken(final MultivaluedMap<String, String> form) {
-        if (!checkSsl()) {
-            throw new NotAcceptableException("HTTPS required");
-        }
 
         String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
         if (username == null) {
@@ -185,7 +155,8 @@ public class TokenService {
         if (authManager.authenticateForm(realm, user, form) != AuthenticationStatus.SUCCESS) {
             throw new NotAuthorizedException("Auth failed");
         }
-        AccessToken token = tokenManager.createAccessToken(realm, user);
+        String scope = form.getFirst("scope");
+        AccessToken token = tokenManager.createClientAccessToken(scope, realm, client, user);
         String encoded = tokenManager.encodeToken(realm, token);
         AccessTokenResponse res = accessTokenResponse(token, encoded);
         return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
@@ -341,47 +312,14 @@ public class TokenService {
             throw new NotAuthorizedException("Realm not enabled");
         }
 
-        if (authorizationHeader == null) {
-            throw new NotAuthorizedException("No Authorization header to authenticate client", "Basic realm=\"" + realm.getName() + "\"");
-        }
-
-        String[] usernameSecret = BasicAuthHelper.parseHeader(authorizationHeader);
-        if (usernameSecret == null) {
-            throw new NotAuthorizedException("No Authorization header to authenticate client", "Basic realm=\"" + realm.getName() + "\"");
-        }
-
-        String client_id = usernameSecret[0];
-        String clientSecret = usernameSecret[1];
-        UserModel client = realm.getUser(client_id);
-        if (client == null) {
-            logger.debug("Could not find user");
-            Map<String, String> error = new HashMap<String, String>();
-            error.put("error", "invalid_client");
-            error.put("error_description", "Could not find user");
-            return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
-        }
-
-        if (!client.isEnabled()) {
-            logger.debug("user is not enabled");
-            Map<String, String> error = new HashMap<String, String>();
-            error.put("error", "invalid_client");
-            error.put("error_description", "User is not enabled");
-            return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
-        }
-
-        if (!realm.validateSecret(client, clientSecret)) {
-            Map<String, String> error = new HashMap<String, String>();
-            error.put("error", "unauthorized_client");
-            return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
-        }
+        UserModel client = authorizeClient(authorizationHeader);
 
         String code = formData.getFirst("code");
         if (code == null) {
-            logger.debug("code not specified");
             Map<String, String> error = new HashMap<String, String>();
             error.put("error", "invalid_request");
             error.put("error_description", "code not specified");
-            return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
+            throw new BadRequestException("Code not specified", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
 
         }
 
@@ -435,6 +373,41 @@ public class TokenService {
         return Cors.add(request, Response.ok(res)).allowedOrigins(client).allowedMethods("POST").build();
     }
 
+    protected UserModel authorizeClient(String authorizationHeader) {
+        if (authorizationHeader == null) {
+            throw new NotAuthorizedException("No Authorization header to authenticate client", "Basic realm=\"" + realm.getName() + "\"");
+        }
+
+        String[] usernameSecret = BasicAuthHelper.parseHeader(authorizationHeader);
+        if (usernameSecret == null) {
+            throw new NotAuthorizedException("No Authorization header to authenticate client", "Basic realm=\"" + realm.getName() + "\"");
+        }
+
+        String client_id = usernameSecret[0];
+        String clientSecret = usernameSecret[1];
+        UserModel client = realm.getUser(client_id);
+        if (client == null) {
+            Map<String, String> error = new HashMap<String, String>();
+            error.put("error", "invalid_client");
+            error.put("error_description", "Could not find client");
+            throw new BadRequestException("Could not find client", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
+        }
+
+        if (!client.isEnabled()) {
+            Map<String, String> error = new HashMap<String, String>();
+            error.put("error", "invalid_client");
+            error.put("error_description", "Client is not enabled");
+            throw new BadRequestException("Client is not enabled", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
+        }
+
+        if (!realm.validateSecret(client, clientSecret)) {
+            Map<String, String> error = new HashMap<String, String>();
+            error.put("error", "unauthorized_client");
+            throw new BadRequestException("Unauthorized Client", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
+        }
+        return client;
+    }
+
     protected AccessTokenResponse accessTokenResponse(PrivateKey privateKey, AccessToken token) {
         String encodedToken = new JWSBuilder().jsonContent(token).rsa256(privateKey);
 
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 adc8bf5..720ea52 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,7 +57,7 @@ public class CompositeRoleTest {
             RealmModel realm = manager.createRealm("Test");
             manager.generateRealmKeys(realm);
             realmPublicKey = realm.getPublicKey();
-            realm.setTokenLifespan(10000);
+            realm.setAccessTokenLifespan(10000);
             realm.setAccessCodeLifespanUserAction(1000);
             realm.setAccessCodeLifespan(1000);
             realm.setSslNotRequired(true);
diff --git a/testsuite/integration/src/test/resources/testcomposite.json b/testsuite/integration/src/test/resources/testcomposite.json
index 19b662e..cfdd2c7 100755
--- a/testsuite/integration/src/test/resources/testcomposite.json
+++ b/testsuite/integration/src/test/resources/testcomposite.json
@@ -2,7 +2,7 @@
     "id": "Test",
     "realm": "Test",
     "enabled": true,
-    "tokenLifespan": 600,
+    "accessTokenLifespan": 600,
     "accessCodeLifespan": 600,
     "accessCodeLifespanUserAction": 600,
     "sslNotRequired": true,
diff --git a/testsuite/integration/src/test/resources/testrealm.json b/testsuite/integration/src/test/resources/testrealm.json
index e040c2c..72db7ca 100755
--- a/testsuite/integration/src/test/resources/testrealm.json
+++ b/testsuite/integration/src/test/resources/testrealm.json
@@ -2,7 +2,7 @@
     "id": "test",
     "realm": "test",
     "enabled": true,
-    "tokenLifespan": 600,
+    "accessTokenLifespan": 600,
     "accessCodeLifespan": 600,
     "accessCodeLifespanUserAction": 600,
     "sslNotRequired": true,