keycloak-aplcache

role description

7/28/2013 10:47:26 AM

Details

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 cddd1ca..080d845 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
@@ -18,7 +18,7 @@ public class RealmRepresentation {
     protected boolean cookieLoginAllowed;
     protected String privateKey;
     protected String publicKey;
-    protected Set<String> roles;
+    protected List<RoleRepresentation> roles;
     protected List<RequiredCredentialRepresentation> requiredCredentials;
     protected List<UserRepresentation> users;
     protected List<RoleMappingRepresentation> roleMappings;
@@ -146,11 +146,11 @@ public class RealmRepresentation {
         this.accessCodeLifespan = accessCodeLifespan;
     }
 
-    public Set<String> getRoles() {
+    public List<RoleRepresentation> getRoles() {
         return roles;
     }
 
-    public void setRoles(Set<String> roles) {
+    public void setRoles(List<RoleRepresentation> roles) {
         this.roles = roles;
     }
 
diff --git a/core/src/main/java/org/keycloak/representations/idm/ResourceRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ResourceRepresentation.java
index 15c49f9..84d499f 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ResourceRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ResourceRepresentation.java
@@ -16,7 +16,7 @@ public class ResourceRepresentation {
     protected boolean surrogateAuthRequired;
     protected boolean useRealmMappings;
     protected List<CredentialRepresentation> credentials;
-    protected Set<String> roles;
+    protected List<RoleRepresentation> roles;
     protected List<RoleMappingRepresentation> roleMappings;
     protected List<ScopeMappingRepresentation> scopeMappings;
 
@@ -44,17 +44,17 @@ public class ResourceRepresentation {
         this.surrogateAuthRequired = surrogateAuthRequired;
     }
 
-    public Set<String> getRoles() {
+    public List<RoleRepresentation> getRoles() {
         return roles;
     }
 
-    public void setRoles(Set<String> roles) {
+    public void setRoles(List<RoleRepresentation> roles) {
         this.roles = roles;
     }
 
-    public ResourceRepresentation role(String role) {
-        if (this.roles == null) this.roles = new HashSet<String>();
-        this.roles.add(role);
+    public ResourceRepresentation role(String role, String description) {
+        if (this.roles == null) this.roles = new ArrayList<RoleRepresentation>();
+        this.roles.add(new RoleRepresentation(role, description));
         return this;
     }
 
diff --git a/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java
new file mode 100755
index 0000000..60fbc6b
--- /dev/null
+++ b/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java
@@ -0,0 +1,34 @@
+package org.keycloak.representations.idm;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RoleRepresentation {
+    protected String name;
+    protected String description;
+
+    public RoleRepresentation() {
+    }
+
+    public RoleRepresentation(String name, String description) {
+        this.name = name;
+        this.description = description;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+}
diff --git a/examples/as7-eap-demo/server/src/main/webapp/META-INF/testrealm.json b/examples/as7-eap-demo/server/src/main/webapp/META-INF/testrealm.json
index db10768..dc9375a 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/META-INF/testrealm.json
+++ b/examples/as7-eap-demo/server/src/main/webapp/META-INF/testrealm.json
@@ -27,6 +27,10 @@
             ]
       }
    ],
+   "roles" : [
+      { "name" : "user", "description" : "User privileges" },
+      { "name" : "admin", "description" : "Administrator privileges" }
+   ],
    "roleMappings" : [
        {
           "username" : "bburke@redhat.com",
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 080e688..9f5e8c8 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -5,6 +5,7 @@ import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.RequiredCredentialRepresentation;
 import org.keycloak.representations.idm.ResourceRepresentation;
 import org.keycloak.representations.idm.RoleMappingRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
 import org.keycloak.representations.idm.ScopeMappingRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
 import org.keycloak.services.models.RealmModel;
@@ -23,6 +24,7 @@ import org.picketlink.idm.model.User;
 
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Response;
+import java.io.Serializable;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.security.NoSuchAlgorithmException;
@@ -38,6 +40,9 @@ import java.util.concurrent.atomic.AtomicLong;
  */
 public class RealmManager {
     private static AtomicLong counter = new AtomicLong(1);
+    public static final String RESOURCE_ROLE = "KEYCLOAK_RESOURCE";
+    public static final String OAUTH_CLIENT_ROLE = "KEYCLOAK_OAUTH_CLIENT";
+    public static final String WILDCARD_ROLE = "*";
 
     public static String generateId() {
         return counter.getAndIncrement() + "-" + System.currentTimeMillis();
@@ -71,7 +76,8 @@ public class RealmManager {
         SimpleAgent agent = new SimpleAgent(RealmModel.REALM_AGENT_ID);
         idm.add(agent);
         RealmModel realm = new RealmModel(newRealm, identitySession);
-        idm.add(new SimpleRole("*"));
+        idm.add(new SimpleRole(WILDCARD_ROLE));
+        idm.add(new SimpleRole(RESOURCE_ROLE));
         return realm;
     }
 
@@ -145,8 +151,9 @@ public class RealmManager {
         }
 
         if (rep.getRoles() != null) {
-            for (String roleString : rep.getRoles()) {
-                SimpleRole role = new SimpleRole(roleString.trim());
+            for (RoleRepresentation roleRep : rep.getRoles()) {
+                SimpleRole role = new SimpleRole(roleRep.getName());
+                if (roleRep.getDescription() != null) role.setAttribute(new Attribute<String>("description", roleRep.getDescription()));
                 newRealm.getIdm().add(role);
             }
         }
@@ -186,6 +193,7 @@ public class RealmManager {
     }
 
     protected void createResources(RealmRepresentation rep, RealmModel realm, Map<String, User> userMap) {
+        Role loginRole = realm.getIdm().getRole(RealmManager.RESOURCE_ROLE);
         for (ResourceRepresentation resourceRep : rep.getResources()) {
             ResourceModel resource = realm.addResource(resourceRep.getName());
             resource.setManagementUrl(resourceRep.getAdminUrl());
@@ -202,11 +210,13 @@ public class RealmManager {
                 }
             }
             userMap.put(resourceUser.getLoginName(), resourceUser);
+            realm.getIdm().grantRole(resourceUser, loginRole);
 
 
             if (resourceRep.getRoles() != null) {
-                for (String roleString : resourceRep.getRoles()) {
-                    SimpleRole role = new SimpleRole(roleString.trim());
+                for (RoleRepresentation roleRep : resourceRep.getRoles()) {
+                    SimpleRole role = new SimpleRole(roleRep.getName());
+                    if (roleRep.getDescription() != null) role.setAttribute(new Attribute<String>("description", roleRep.getDescription()));
                     resource.getIdm().add(role);
                 }
             }
diff --git a/services/src/main/java/org/keycloak/services/models/RealmModel.java b/services/src/main/java/org/keycloak/services/models/RealmModel.java
index 6ab850a..171e57d 100755
--- a/services/src/main/java/org/keycloak/services/models/RealmModel.java
+++ b/services/src/main/java/org/keycloak/services/models/RealmModel.java
@@ -38,6 +38,8 @@ import java.util.Map;
 import java.util.Set;
 
 /**
+ * Meant to be a per-request object
+ *
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
@@ -57,6 +59,7 @@ public class RealmModel {
     protected IdentitySession identitySession;
     protected volatile transient PublicKey publicKey;
     protected volatile transient PrivateKey privateKey;
+    protected IdentityManager idm;
 
     public RealmModel(Realm realm, IdentitySession session) {
         this.realm = realm;
@@ -65,7 +68,8 @@ public class RealmModel {
     }
 
     public IdentityManager getIdm() {
-        return identitySession.createIdentityManager(realm);
+        if (idm == null) idm = identitySession.createIdentityManager(realm);
+        return idm;
     }
 
     public void updateRealm() {
diff --git a/services/src/main/java/org/keycloak/services/models/ResourceModel.java b/services/src/main/java/org/keycloak/services/models/ResourceModel.java
index c47785b..f9b5ca3 100755
--- a/services/src/main/java/org/keycloak/services/models/ResourceModel.java
+++ b/services/src/main/java/org/keycloak/services/models/ResourceModel.java
@@ -25,6 +25,7 @@ public class ResourceModel {
     protected ResourceRelationship agent;
     protected RealmModel realm;
     protected IdentitySession identitySession;
+    protected IdentityManager idm;
 
     public ResourceModel(Tier tier, ResourceRelationship agent, RealmModel realm, IdentitySession session) {
         this.tier = tier;
@@ -34,7 +35,8 @@ public class ResourceModel {
     }
 
     public IdentityManager getIdm() {
-        return identitySession.createIdentityManager(tier);
+        if (idm == null) idm = identitySession.createIdentityManager(tier);
+        return idm;
     }
 
     public void updateResource() {
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 eaaaf74..eb52cfe 100755
--- a/services/src/main/java/org/keycloak/services/resources/TokenService.java
+++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java
@@ -13,12 +13,14 @@ import org.keycloak.representations.SkeletonKeyToken;
 import org.keycloak.services.JspRequestParameters;
 import org.keycloak.services.managers.AccessCodeEntry;
 import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.managers.ResourceAdminManager;
 import org.keycloak.services.managers.TokenManager;
 import org.keycloak.services.models.RealmModel;
 import org.keycloak.services.models.RequiredCredentialModel;
 import org.keycloak.services.models.ResourceModel;
 import org.picketlink.idm.IdentitySession;
+import org.picketlink.idm.model.Role;
 import org.picketlink.idm.model.User;
 
 import javax.ws.rs.Consumes;
@@ -389,12 +391,19 @@ public class TokenService {
             identitySession.close();
             return null;
         }
+        Role resourceRole = realm.getIdm().getRole(RealmManager.RESOURCE_ROLE);
+        Role oauthClientRole = realm.getIdm().getRole(RealmManager.OAUTH_CLIENT_ROLE);
+        if (!realm.getIdm().hasRole(client, resourceRole) && !realm.getIdm().hasRole(client, oauthClientRole)) {
+            securityFailureForward("Login requester not allowed to request login.");
+            identitySession.close();
+            return null;
+
+        }
 
         User user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
         if (user != null) {
             return redirectAccessCode(scopeParam, state, redirect, client, user);
         }
-        // todo make sure client is allowed to request a login
 
         forwardToLoginForm(redirect, clientId, scopeParam, state);
         return null;
diff --git a/services/src/test/java/org/keycloak/test/AdapterTest.java b/services/src/test/java/org/keycloak/test/AdapterTest.java
index f798539..36b3d6b 100755
--- a/services/src/test/java/org/keycloak/test/AdapterTest.java
+++ b/services/src/test/java/org/keycloak/test/AdapterTest.java
@@ -166,7 +166,7 @@ public class AdapterTest {
         idm.add(new SimpleRole("admin"));
         idm.add(new SimpleRole("user"));
         List<Role> roles = realmModel.getRoles();
-        Assert.assertEquals(3, roles.size());
+        Assert.assertEquals(4, roles.size());
         SimpleUser user = new SimpleUser("bburke");
         idm.add(user);
         Role role = idm.getRole("user");
diff --git a/services/src/test/resources/testrealm.json b/services/src/test/resources/testrealm.json
index b58bdd8..a8d0cbf 100755
--- a/services/src/test/resources/testrealm.json
+++ b/services/src/test/resources/testrealm.json
@@ -62,7 +62,10 @@
    "resources" : [
        {
           "name" : "Application",
-          "roles" : ["admin", "user"],
+          "roles" : [
+              { "name" : "admin" },
+              { "name" : "user" }
+          ],
           "roleMappings" : [
              {
                 "username" : "wburke",
@@ -82,7 +85,10 @@
        },
               {
                  "name" : "OtherApp",
-                 "roles" : ["admin", "user"],
+          "roles" : [
+              { "name" : "admin" },
+              { "name" : "user" }
+          ],
                  "roleMappings" : [
                     {
                        "username" : "wburke",