keycloak-aplcache

composite roles

1/29/2014 11:19:32 PM

Changes

model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationUserRoleMappingEntity.java 29(+0 -29)

model/pom.xml 2(+1 -1)

services/pom.xml 2(+2 -0)

Details

diff --git a/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java
index 4a16101..59119a6 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java
@@ -8,6 +8,7 @@ public class RoleRepresentation {
     protected String id;
     protected String name;
     protected String description;
+    protected boolean composite;
 
     public RoleRepresentation() {
     }
@@ -40,4 +41,12 @@ public class RoleRepresentation {
     public void setDescription(String description) {
         this.description = description;
     }
+
+    public boolean isComposite() {
+        return composite;
+    }
+
+    public void setComposite(boolean composite) {
+        this.composite = composite;
+    }
 }
diff --git a/model/api/src/main/java/org/keycloak/models/ApplicationModel.java b/model/api/src/main/java/org/keycloak/models/ApplicationModel.java
index e5374b8..4657644 100755
--- a/model/api/src/main/java/org/keycloak/models/ApplicationModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ApplicationModel.java
@@ -1,12 +1,13 @@
 package org.keycloak.models;
 
 import java.util.List;
+import java.util.Set;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public interface ApplicationModel extends RoleContainerModel, RoleMapperModel, ScopeMapperModel {
+public interface ApplicationModel extends RoleContainerModel {
     void updateApplication();
 
     UserModel getApplicationUser();
@@ -38,4 +39,10 @@ public interface ApplicationModel extends RoleContainerModel, RoleMapperModel, S
     void addDefaultRole(String name);
 
     void updateDefaultRoles(String[] defaultRoles);
+
+    Set<RoleModel> getApplicationRoleMappings(UserModel user);
+
+    Set<RoleModel> getApplicationScopeMappings(UserModel user);
+
+    void addScope(RoleModel role);
 }
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 184e6aa..ac75c7a 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -157,4 +157,8 @@ public interface RealmModel extends RoleContainerModel, RoleMapperModel, ScopeMa
     Map<String, String> getSocialConfig();
 
     void setSocialConfig(Map<String, String> socialConfig);
+
+    Set<RoleModel> getRealmRoleMappings(UserModel user);
+
+    Set<RoleModel> getRealmScopeMappings(UserModel user);
 }
diff --git a/model/api/src/main/java/org/keycloak/models/RoleMapperModel.java b/model/api/src/main/java/org/keycloak/models/RoleMapperModel.java
index a9a9938..3c74451 100755
--- a/model/api/src/main/java/org/keycloak/models/RoleMapperModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RoleMapperModel.java
@@ -9,14 +9,7 @@ import java.util.Set;
  */
 public interface RoleMapperModel {
     boolean hasRole(UserModel user, RoleModel role);
-
     void grantRole(UserModel user, RoleModel role);
-
-    Set<String> getRoleMappingValues(UserModel user);
-
-    List<RoleModel> getRoleMappings(UserModel user);
-
+    Set<RoleModel> getRoleMappings(UserModel user);
     void deleteRoleMapping(UserModel user, RoleModel role);
-
-    boolean hasRole(UserModel user, String role);
 }
diff --git a/model/api/src/main/java/org/keycloak/models/RoleModel.java b/model/api/src/main/java/org/keycloak/models/RoleModel.java
index a8e8ebe..c2a9507 100755
--- a/model/api/src/main/java/org/keycloak/models/RoleModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RoleModel.java
@@ -1,5 +1,7 @@
 package org.keycloak.models;
 
+import java.util.Set;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
@@ -14,4 +16,18 @@ public interface RoleModel {
     String getId();
 
     void setName(String name);
+
+    boolean isComposite();
+
+    void setComposite(boolean flag);
+
+    void addCompositeRole(RoleModel role);
+
+    void removeCompositeRole(RoleModel role);
+
+    Set<RoleModel> getComposites();
+
+    RoleContainerModel getContainer();
+
+
 }
diff --git a/model/api/src/main/java/org/keycloak/models/ScopeMapperModel.java b/model/api/src/main/java/org/keycloak/models/ScopeMapperModel.java
index a94ac8d..d675290 100755
--- a/model/api/src/main/java/org/keycloak/models/ScopeMapperModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ScopeMapperModel.java
@@ -8,13 +8,7 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 public interface ScopeMapperModel {
-    void addScopeMapping(UserModel agent, String roleName);
-
-    Set<String> getScopeMappingValues(UserModel agent);
-
-    List<RoleModel> getScopeMappings(UserModel agent);
-
+    Set<RoleModel> getScopeMappings(UserModel agent);
     void addScopeMapping(UserModel agent, RoleModel role);
-
     void deleteScopeMapping(UserModel user, RoleModel role);
 }
diff --git a/model/api/src/main/java/org/keycloak/models/UserCredentialModel.java b/model/api/src/main/java/org/keycloak/models/UserCredentialModel.java
index a20450c..410ae87 100755
--- a/model/api/src/main/java/org/keycloak/models/UserCredentialModel.java
+++ b/model/api/src/main/java/org/keycloak/models/UserCredentialModel.java
@@ -13,6 +13,17 @@ public class UserCredentialModel {
     protected String value;
     protected String device;
 
+    public UserCredentialModel() {
+    }
+
+    public static UserCredentialModel password(String password) {
+        UserCredentialModel model = new UserCredentialModel();
+        model.setType(PASSWORD);
+        model.setValue(password);
+        return model;
+    }
+
+
     public String getType() {
         return type;
     }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java
index 356fc0c..6f46042 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java
@@ -1,16 +1,22 @@
 package org.keycloak.models.jpa;
 
 import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleContainerModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.jpa.entities.*;
+import org.keycloak.representations.idm.ApplicationMappingsRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
 
 import javax.persistence.EntityManager;
 import javax.persistence.TypedQuery;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -21,8 +27,10 @@ public class ApplicationAdapter implements ApplicationModel {
 
     protected EntityManager em;
     protected ApplicationEntity application;
+    protected RealmModel realm;
 
-    public ApplicationAdapter(EntityManager em, ApplicationEntity application) {
+    public ApplicationAdapter(RealmModel realm, EntityManager em, ApplicationEntity application) {
+        this.realm = realm;
         this.em = em;
         this.application = application;
     }
@@ -94,31 +102,30 @@ public class ApplicationAdapter implements ApplicationModel {
 
     @Override
     public RoleModel getRole(String name) {
-        Collection<RoleEntity> roles = application.getRoles();
-        if (roles == null) return null;
-        for (RoleEntity role : roles) {
-            if (role.getName().equals(name)) {
-                return new RoleAdapter(role);
-            }
-        }
-        return null;
+        TypedQuery<ApplicationRoleEntity> query = em.createNamedQuery("getAppRoleByName", ApplicationRoleEntity.class);
+        query.setParameter("name", name);
+        query.setParameter("application", application);
+        List<ApplicationRoleEntity> roles = query.getResultList();
+        if (roles.size() == 0) return null;
+        return new RoleAdapter(realm, em, roles.get(0));
     }
 
     @Override
     public RoleModel addRole(String name) {
         RoleModel role = getRole(name);
         if (role != null) return role;
-        RoleEntity entity = new RoleEntity();
+        ApplicationRoleEntity entity = new ApplicationRoleEntity();
         entity.setName(name);
+        entity.setApplication(application);
         em.persist(entity);
         application.getRoles().add(entity);
         em.flush();
-        return new RoleAdapter(entity);
+        return new RoleAdapter(realm, em, entity);
     }
 
     @Override
     public boolean removeRoleById(String id) {
-        RoleEntity role = em.find(RoleEntity.class, id);
+        ApplicationRoleEntity role = em.find(ApplicationRoleEntity.class, id);
         if (role == null) {
             return false;
         }
@@ -126,11 +133,10 @@ public class ApplicationAdapter implements ApplicationModel {
         application.getRoles().remove(role);
         application.getDefaultRoles().remove(role);
 
-        em.createQuery("delete from " + ApplicationScopeMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate();
-        em.createQuery("delete from " + ApplicationUserRoleMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate();
-        em.createQuery("delete from " + RealmScopeMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate();
-        em.createQuery("delete from " + RealmUserRoleMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate();
-
+        em.createQuery("delete from " + UserScopeMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate();
+        em.createQuery("delete from " + UserRoleMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate();
+        role.setApplication(null);
+        em.flush();
         em.remove(role);
 
         return true;
@@ -139,156 +145,59 @@ public class ApplicationAdapter implements ApplicationModel {
     @Override
     public List<RoleModel> getRoles() {
         ArrayList<RoleModel> list = new ArrayList<RoleModel>();
-        Collection<RoleEntity> roles = application.getRoles();
+        Collection<ApplicationRoleEntity> roles = application.getRoles();
         if (roles == null) return list;
         for (RoleEntity entity : roles) {
-            list.add(new RoleAdapter(entity));
+            list.add(new RoleAdapter(realm, em, entity));
         }
         return list;
     }
 
     @Override
     public RoleModel getRoleById(String id) {
-        RoleEntity entity = em.find(RoleEntity.class, id);
-        if (entity == null) return null;
-        return new RoleAdapter(entity);
-    }
-
-    @Override
-    public boolean hasRole(UserModel user, RoleModel role) {
-        TypedQuery<ApplicationUserRoleMappingEntity> query = getApplicationUserRoleMappingEntityTypedQuery((UserAdapter) user, (RoleAdapter) role);
-        return query.getResultList().size() > 0;
-    }
-
-    protected TypedQuery<ApplicationUserRoleMappingEntity> getApplicationUserRoleMappingEntityTypedQuery(UserAdapter user, RoleAdapter role) {
-        TypedQuery<ApplicationUserRoleMappingEntity> query = em.createNamedQuery("userHasApplicationRole", ApplicationUserRoleMappingEntity.class);
-        query.setParameter("user", ((UserAdapter)user).getUser());
-        query.setParameter("role", ((RoleAdapter)role).getRole());
-        query.setParameter("application", application);
-        return query;
-    }
-
-    @Override
-    public void grantRole(UserModel user, RoleModel role) {
-        if (hasRole(user, role)) return;
-        ApplicationUserRoleMappingEntity entity = new ApplicationUserRoleMappingEntity();
-        entity.setApplication(application);
-        entity.setUser(((UserAdapter) user).getUser());
-        entity.setRole(((RoleAdapter)role).getRole());
-        em.persist(entity);
-        em.flush();
+        return realm.getRoleById(id);
     }
 
     @Override
-    public List<RoleModel> getRoleMappings(UserModel user) {
-        TypedQuery<ApplicationUserRoleMappingEntity> query = em.createNamedQuery("userApplicationMappings", ApplicationUserRoleMappingEntity.class);
-        query.setParameter("user", ((UserAdapter)user).getUser());
-        query.setParameter("application", application);
-        List<ApplicationUserRoleMappingEntity> entities = query.getResultList();
-        List<RoleModel> roles = new ArrayList<RoleModel>();
-        for (ApplicationUserRoleMappingEntity entity : entities) {
-            roles.add(new RoleAdapter(entity.getRole()));
-        }
-        return roles;
-    }
+    public Set<RoleModel> getApplicationRoleMappings(UserModel user) {
+        Set<RoleModel> roleMappings = realm.getRoleMappings(user);
 
-    @Override
-    public Set<String> getRoleMappingValues(UserModel user) {
-        TypedQuery<ApplicationUserRoleMappingEntity> query = em.createNamedQuery("userApplicationMappings", ApplicationUserRoleMappingEntity.class);
-        query.setParameter("user", ((UserAdapter)user).getUser());
-        query.setParameter("application", application);
-        List<ApplicationUserRoleMappingEntity> entities = query.getResultList();
-        Set<String> roles = new HashSet<String>();
-        for (ApplicationUserRoleMappingEntity entity : entities) {
-            roles.add(entity.getRole().getName());
-        }
-        return roles;
-    }
-
-    @Override
-    public void deleteRoleMapping(UserModel user, RoleModel role) {
-        TypedQuery<ApplicationUserRoleMappingEntity> query = getApplicationUserRoleMappingEntityTypedQuery((UserAdapter) user, (RoleAdapter) role);
-        List<ApplicationUserRoleMappingEntity> results = query.getResultList();
-        if (results.size() == 0) return;
-        for (ApplicationUserRoleMappingEntity entity : results) {
-            em.remove(entity);
+        Set<RoleModel> appRoles = new HashSet<RoleModel>();
+        for (RoleModel role : roleMappings) {
+            RoleContainerModel container = role.getContainer();
+            if (container instanceof RealmModel) {
+            } else {
+                ApplicationModel app = (ApplicationModel)container;
+                if (app.getId().equals(getId())) {
+                   appRoles.add(role);
+                }
+            }
         }
-    }
 
-    @Override
-    public boolean hasRole(UserModel user, String roleName) {
-        RoleModel role = getRole(roleName);
-        if (role == null) return false;
-        return hasRole(user, role);
+        return appRoles;
     }
 
     @Override
-    public void addScopeMapping(UserModel agent, String roleName) {
-        RoleModel role = getRole(roleName);
-        if (role == null) throw new RuntimeException("role does not exist");
-        addScopeMapping(agent, role);
-    }
+    public Set<RoleModel> getApplicationScopeMappings(UserModel user) {
+        Set<RoleModel> roleMappings = realm.getScopeMappings(user);
 
-    @Override
-    public Set<String> getScopeMappingValues(UserModel agent) {
-        TypedQuery<ApplicationScopeMappingEntity> query = em.createNamedQuery("userApplicationScopeMappings", ApplicationScopeMappingEntity.class);
-        query.setParameter("user", ((UserAdapter)agent).getUser());
-        query.setParameter("application", application);
-        List<ApplicationScopeMappingEntity> entities = query.getResultList();
-        Set<String> roles = new HashSet<String>();
-        for (ApplicationScopeMappingEntity entity : entities) {
-            roles.add(entity.getRole().getName());
-        }
-        return roles;
-    }
-
-    @Override
-    public List<RoleModel> getScopeMappings(UserModel agent) {
-        TypedQuery<ApplicationScopeMappingEntity> query = em.createNamedQuery("userApplicationScopeMappings", ApplicationScopeMappingEntity.class);
-        query.setParameter("user", ((UserAdapter)agent).getUser());
-        query.setParameter("application", application);
-        List<ApplicationScopeMappingEntity> entities = query.getResultList();
-        List<RoleModel> roles = new ArrayList<RoleModel>();
-        for (ApplicationScopeMappingEntity entity : entities) {
-            roles.add(new RoleAdapter(entity.getRole()));
+        Set<RoleModel> appRoles = new HashSet<RoleModel>();
+        for (RoleModel role : roleMappings) {
+            RoleContainerModel container = role.getContainer();
+            if (container instanceof RealmModel) {
+            } else {
+                ApplicationModel app = (ApplicationModel)container;
+                if (app.getId().equals(getId())) {
+                    appRoles.add(role);
+                }
+            }
         }
-        return roles;
-    }
 
-    @Override
-    public void addScopeMapping(UserModel agent, RoleModel role) {
-        if (hasScope(agent, role)) return;
-        ApplicationScopeMappingEntity entity = new ApplicationScopeMappingEntity();
-        entity.setApplication(application);
-        entity.setUser(((UserAdapter) agent).getUser());
-        entity.setRole(((RoleAdapter)role).getRole());
-        em.persist(entity);
-        em.flush();
+        return appRoles;
     }
 
-    @Override
-    public void deleteScopeMapping(UserModel user, RoleModel role) {
-        TypedQuery<ApplicationScopeMappingEntity> query = getApplicationScopeMappingQuery((UserAdapter) user, (RoleAdapter) role);
-        List<ApplicationScopeMappingEntity> results = query.getResultList();
-        if (results.size() == 0) return;
-        for (ApplicationScopeMappingEntity entity : results) {
-            em.remove(entity);
-        }
-    }
-
-    public boolean hasScope(UserModel user, RoleModel role) {
-        TypedQuery<ApplicationScopeMappingEntity> query = getApplicationScopeMappingQuery((UserAdapter) user, (RoleAdapter) role);
-        return query.getResultList().size() > 0;
-    }
 
 
-    protected TypedQuery<ApplicationScopeMappingEntity> getApplicationScopeMappingQuery(UserAdapter user, RoleAdapter role) {
-        TypedQuery<ApplicationScopeMappingEntity> query = em.createNamedQuery("userHasApplicationScope", ApplicationScopeMappingEntity.class);
-        query.setParameter("user", ((UserAdapter)user).getUser());
-        query.setParameter("role", ((RoleAdapter)role).getRole());
-        query.setParameter("application", application);
-        return query;
-    }
 
     @Override
     public List<String> getDefaultRoles() {
@@ -347,4 +256,9 @@ public class ApplicationAdapter implements ApplicationModel {
         }
         em.flush();
     }
+
+    @Override
+    public void addScope(RoleModel role) {
+        realm.addScopeMapping(getApplicationUser(), role);
+    }
 }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AbstractRoleMappingEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AbstractRoleMappingEntity.java
new file mode 100755
index 0000000..c840453
--- /dev/null
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AbstractRoleMappingEntity.java
@@ -0,0 +1,46 @@
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.MappedSuperclass;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@MappedSuperclass
+public class AbstractRoleMappingEntity {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    protected long id;
+    @ManyToOne
+    protected UserEntity user;
+    @ManyToOne
+    protected RoleEntity role;
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public UserEntity getUser() {
+        return user;
+    }
+
+    public void setUser(UserEntity user) {
+        this.user = user;
+    }
+
+    public RoleEntity getRole() {
+        return role;
+    }
+
+    public void setRole(RoleEntity role) {
+        this.role = role;
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationEntity.java
index c0e2144..667fd48 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationEntity.java
@@ -31,9 +31,8 @@ public class ApplicationEntity {
     @OneToOne(fetch = FetchType.EAGER)
     private UserEntity applicationUser;
 
-    @OneToMany(fetch = FetchType.EAGER, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
-    @JoinTable(name="APPLICATION_ROLES")
-    Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
+    @OneToMany(fetch = FetchType.EAGER, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "application")
+    Collection<ApplicationRoleEntity> roles = new ArrayList<ApplicationRoleEntity>();
 
     @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
     @JoinTable(name="APPLICATION_DEFAULT_ROLES")
@@ -83,11 +82,11 @@ public class ApplicationEntity {
         this.applicationUser = applicationUser;
     }
 
-    public Collection<RoleEntity> getRoles() {
+    public Collection<ApplicationRoleEntity> getRoles() {
         return roles;
     }
 
-    public void setRoles(Collection<RoleEntity> roles) {
+    public void setRoles(Collection<ApplicationRoleEntity> roles) {
         this.roles = roles;
     }
 
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 067b8dc..58c1f17 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
@@ -65,9 +65,8 @@ public class RealmEntity {
     @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
     Collection<ApplicationEntity> applications = new ArrayList<ApplicationEntity>();
 
-    @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
-    @JoinTable(name="REALM_ROLES")
-    Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
+    @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
+    Collection<RealmRoleEntity> roles = new ArrayList<RealmRoleEntity>();
 
     @ElementCollection
     @MapKeyColumn(name="name")
@@ -229,17 +228,17 @@ public class RealmEntity {
         this.applications = applications;
     }
 
-    public Collection<RoleEntity> getRoles() {
+    public Collection<RealmRoleEntity> getRoles() {
         return roles;
     }
 
-    public void setRoles(Collection<RoleEntity> roles) {
+    public void setRoles(Collection<RealmRoleEntity> roles) {
         this.roles = roles;
     }
 
-    public void addRole(RoleEntity role) {
+    public void addRole(RealmRoleEntity role) {
         if (roles == null) {
-            roles = new ArrayList<RoleEntity>();
+            roles = new ArrayList<RealmRoleEntity>();
         }
         roles.add(role);
     }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java
index 38beeb3..f65a59f 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java
@@ -1,22 +1,34 @@
 package org.keycloak.models.jpa.entities;
 
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
 import javax.persistence.Id;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.JoinTable;
+import javax.persistence.OneToMany;
+import java.util.ArrayList;
+import java.util.Collection;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
 @Entity
-public class RoleEntity {
+public abstract class RoleEntity {
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private String id;
 
     private String name;
     private String description;
+    private boolean composite;
+    @OneToMany(fetch = FetchType.LAZY, cascade = {}, orphanRemoval = false)
+    @JoinTable(name = "COMPOSITE_ROLE")
+    private Collection<RoleEntity> compositeRoles = new ArrayList<RoleEntity>();
+
 
     public String getId() {
         return id;
@@ -41,4 +53,37 @@ public class RoleEntity {
     public void setDescription(String description) {
         this.description = description;
     }
+
+    public boolean isComposite() {
+        return composite;
+    }
+
+    public void setComposite(boolean composite) {
+        this.composite = composite;
+    }
+
+    public Collection<RoleEntity> getCompositeRoles() {
+        return compositeRoles;
+    }
+
+    public void setCompositeRoles(Collection<RoleEntity> compositeRoles) {
+        this.compositeRoles = compositeRoles;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        RoleEntity that = (RoleEntity) o;
+
+        if (!id.equals(that.id)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return id.hashCode();
+    }
 }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserRoleMappingEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserRoleMappingEntity.java
index efb7478..6a9aec7 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserRoleMappingEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserRoleMappingEntity.java
@@ -1,46 +1,23 @@
 package org.keycloak.models.jpa.entities;
 
+import javax.persistence.Entity;
 import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.MappedSuperclass;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-@MappedSuperclass
-public abstract class UserRoleMappingEntity {
-    @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    protected long id;
-    @ManyToOne
-    protected UserEntity user;
-    @ManyToOne
-    protected RoleEntity role;
+@NamedQueries({
+        @NamedQuery(name="userHasRole", query="select m from UserRoleMappingEntity m where m.user = :user and m.role = :role"),
+        @NamedQuery(name="userRoleMappings", query="select m from UserRoleMappingEntity m where m.user = :user")
+})
+@Entity
+public class UserRoleMappingEntity extends AbstractRoleMappingEntity {
 
-    public long getId() {
-        return id;
-    }
-
-    public void setId(long id) {
-        this.id = id;
-    }
-
-    public UserEntity getUser() {
-        return user;
-    }
-
-    public void setUser(UserEntity user) {
-        this.user = user;
-    }
-
-    public RoleEntity getRole() {
-        return role;
-    }
-
-    public void setRole(RoleEntity role) {
-        this.role = role;
-    }
 }
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 25352ca..a627a84 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
@@ -1,6 +1,18 @@
 package org.keycloak.models.jpa;
 
 import org.bouncycastle.openssl.PEMWriter;
+import org.keycloak.models.RoleContainerModel;
+import org.keycloak.models.jpa.entities.ApplicationEntity;
+import org.keycloak.models.jpa.entities.CredentialEntity;
+import org.keycloak.models.jpa.entities.OAuthClientEntity;
+import org.keycloak.models.jpa.entities.RealmEntity;
+import org.keycloak.models.jpa.entities.RealmRoleEntity;
+import org.keycloak.models.jpa.entities.RequiredCredentialEntity;
+import org.keycloak.models.jpa.entities.RoleEntity;
+import org.keycloak.models.jpa.entities.SocialLinkEntity;
+import org.keycloak.models.jpa.entities.UserEntity;
+import org.keycloak.models.jpa.entities.UserRoleMappingEntity;
+import org.keycloak.models.jpa.entities.UserScopeMappingEntity;
 import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
 import org.keycloak.util.PemUtils;
 import org.keycloak.models.ApplicationModel;
@@ -12,7 +24,6 @@ import org.keycloak.models.RoleModel;
 import org.keycloak.models.SocialLinkModel;
 import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserModel;
-import org.keycloak.models.jpa.entities.*;
 import org.keycloak.models.utils.TimeBasedOTP;
 
 import javax.persistence.EntityManager;
@@ -25,6 +36,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -453,7 +465,7 @@ public class RealmAdapter implements RealmModel {
 
         for (ApplicationModel application : getApplications()) {
             for (String r : application.getDefaultRoles()) {
-                application.grantRole(userModel, application.getRole(r));
+                grantRole(userModel, application.getRole(r));
             }
         }
 
@@ -472,10 +484,8 @@ public class RealmAdapter implements RealmModel {
     }
 
     private void removeUser(UserEntity user) {
-        em.createQuery("delete from " + ApplicationScopeMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", user).executeUpdate();
-        em.createQuery("delete from " + ApplicationUserRoleMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", user).executeUpdate();
-        em.createQuery("delete from " + RealmScopeMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", user).executeUpdate();
-        em.createQuery("delete from " + RealmUserRoleMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", user).executeUpdate();
+        em.createQuery("delete from " + UserScopeMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", user).executeUpdate();
+        em.createQuery("delete from " + UserRoleMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", user).executeUpdate();
         em.createQuery("delete from " + SocialLinkEntity.class.getSimpleName() + " where user = :user").setParameter("user", user).executeUpdate();
         em.remove(user);
     }
@@ -552,7 +562,7 @@ public class RealmAdapter implements RealmModel {
         List<ApplicationModel> list = new ArrayList<ApplicationModel>();
         if (realm.getApplications() == null) return list;
         for (ApplicationEntity entity : realm.getApplications()) {
-            list.add(new ApplicationAdapter(em, entity));
+            list.add(new ApplicationAdapter(this, em, entity));
         }
         return list;
     }
@@ -571,31 +581,41 @@ public class RealmAdapter implements RealmModel {
         realm.getApplications().add(applicationData);
         em.persist(applicationData);
         em.flush();
-        ApplicationModel resource = new ApplicationAdapter(em, applicationData);
+        ApplicationModel resource = new ApplicationAdapter(this, em, applicationData);
         em.flush();
         return resource;
     }
 
     @Override
     public boolean removeApplication(String id) {
-        ApplicationEntity application = null;
+        if (id == null) return false;
+        ApplicationModel application = getApplicationById(id);
+        if (application == null) return false;
+
+        for (RoleModel role : application.getRoles()) {
+            application.removeRoleById(role.getId());
+        }
+
+        ApplicationEntity applicationEntity = null;
+        Iterator<ApplicationEntity> it = realm.getApplications().iterator();
+        while (it.hasNext()) {
+            ApplicationEntity ae = it.next();
+            if (ae.getId().equals(id)) {
+                applicationEntity = ae;
+                it.remove();
+                break;
+            }
+        }
         for (ApplicationEntity a : realm.getApplications()) {
             if (a.getId().equals(id)) {
-                application = a;
+                applicationEntity = a;
             }
         }
         if (application == null) {
             return false;
         }
-        realm.getApplications().remove(application);
-        em.createQuery("delete from " + ApplicationScopeMappingEntity.class.getSimpleName() + " where application = :application").setParameter("application", application).executeUpdate();
-        em.createQuery("delete from " + ApplicationUserRoleMappingEntity.class.getSimpleName() + " where application = :application").setParameter("application", application).executeUpdate();
-        em.createQuery("delete from " + ApplicationScopeMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", application.getApplicationUser()).executeUpdate();
-        em.createQuery("delete from " + RealmScopeMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", application.getApplicationUser()).executeUpdate();
-        em.createQuery("delete from " + ApplicationUserRoleMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", application.getApplicationUser()).executeUpdate();
-        em.createQuery("delete from " + RealmUserRoleMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", application.getApplicationUser()).executeUpdate();
-        removeUser(application.getApplicationUser());
-        em.remove(application);
+        em.remove(applicationEntity);
+        removeUser(applicationEntity.getApplicationUser());
         return true;
     }
 
@@ -603,7 +623,7 @@ public class RealmAdapter implements RealmModel {
     public ApplicationModel getApplicationById(String id) {
         ApplicationEntity app = em.find(ApplicationEntity.class, id);
         if (app == null) return null;
-        return new ApplicationAdapter(em, app);
+        return new ApplicationAdapter(this, em, app);
     }
 
     @Override
@@ -758,10 +778,8 @@ public class RealmAdapter implements RealmModel {
     @Override
     public boolean removeOAuthClient(String id) {
         OAuthClientEntity client = em.find(OAuthClientEntity.class, id);
-        em.createQuery("delete from " + ApplicationScopeMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", client.getAgent()).executeUpdate();
-        em.createQuery("delete from " + RealmScopeMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", client.getAgent()).executeUpdate();
-        em.createQuery("delete from " + ApplicationUserRoleMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", client.getAgent()).executeUpdate();
-        em.createQuery("delete from " + RealmUserRoleMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", client.getAgent()).executeUpdate();
+        em.createQuery("delete from " + UserScopeMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", client.getAgent()).executeUpdate();
+        em.createQuery("delete from " + UserRoleMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", client.getAgent()).executeUpdate();
         removeUser(client.getAgent());
         em.remove(client);
         return true;
@@ -820,44 +838,43 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public RoleModel getRole(String name) {
-        Collection<RoleEntity> roles = realm.getRoles();
-        if (roles == null) return null;
-        for (RoleEntity role : roles) {
-            if (role.getName().equals(name)) {
-                return new RoleAdapter(role);
-            }
-        }
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+        TypedQuery<RealmRoleEntity> query = em.createNamedQuery("getRealmRoleByName", RealmRoleEntity.class);
+        query.setParameter("name", name);
+        query.setParameter("realm", realm);
+        List<RealmRoleEntity> roles = query.getResultList();
+        if (roles.size() == 0) return null;
+        return new RoleAdapter(this, em, roles.get(0));
     }
 
     @Override
     public RoleModel addRole(String name) {
         RoleModel role = getRole(name);
         if (role != null) return role;
-        RoleEntity entity = new RoleEntity();
+        RealmRoleEntity entity = new RealmRoleEntity();
         entity.setName(name);
-        em.persist(entity);
+        entity.setRealm(realm);
         realm.getRoles().add(entity);
+        em.persist(entity);
         em.flush();
-        return new RoleAdapter(entity);
+        return new RoleAdapter(this, em, entity);
     }
 
     @Override
     public boolean removeRoleById(String id) {
-        RoleEntity role = em.find(RoleEntity.class, id);
+        RoleModel role = getRoleById(id);
+        if (role == null) return false;
+
         if (role == null) {
             return false;
         }
-
+        RoleEntity roleEntity = ((RoleAdapter)role).getRole();
         realm.getRoles().remove(role);
         realm.getDefaultRoles().remove(role);
 
-        em.createQuery("delete from " + ApplicationScopeMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate();
-        em.createQuery("delete from " + ApplicationUserRoleMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate();
-        em.createQuery("delete from " + RealmScopeMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate();
-        em.createQuery("delete from " + RealmUserRoleMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate();
+        em.createQuery("delete from " + UserRoleMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", roleEntity).executeUpdate();
+        em.createQuery("delete from " + UserScopeMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", roleEntity).executeUpdate();
 
-        em.remove(role);
+        em.remove(roleEntity);
 
         return true;
     }
@@ -865,10 +882,10 @@ public class RealmAdapter implements RealmModel {
     @Override
     public List<RoleModel> getRoles() {
         ArrayList<RoleModel> list = new ArrayList<RoleModel>();
-        Collection<RoleEntity> roles = realm.getRoles();
+        Collection<RealmRoleEntity> roles = realm.getRoles();
         if (roles == null) return list;
         for (RoleEntity entity : roles) {
-            list.add(new RoleAdapter(entity));
+            list.add(new RoleAdapter(this, em, entity));
         }
         return list;
     }
@@ -877,28 +894,46 @@ public class RealmAdapter implements RealmModel {
     public RoleModel getRoleById(String id) {
         RoleEntity entity = em.find(RoleEntity.class, id);
         if (entity == null) return null;
-        return new RoleAdapter(entity);
+        return new RoleAdapter(this, em, entity);
+    }
+
+    protected boolean searchCompositeFor(RoleModel role, RoleModel composite, Set<RoleModel> visited) {
+        if (visited.contains(composite)) return false;
+        visited.add(composite);
+        Set<RoleModel> composites = composite.getComposites();
+        if (composites.contains(role)) return true;
+        for (RoleModel contained : composites) {
+            if (!contained.isComposite()) continue;
+            if (searchCompositeFor(role, contained, visited)) return true;
+        }
+        return false;
     }
 
     @Override
     public boolean hasRole(UserModel user, RoleModel role) {
-        TypedQuery<RealmUserRoleMappingEntity> query = getRealmUserRoleMappingEntityTypedQuery((UserAdapter) user, (RoleAdapter) role);
-        return query.getResultList().size() > 0;
+        Set<RoleModel> roles = getRoleMappings(user);
+        if (roles.contains(role)) return true;
+
+        Set<RoleModel> visited = new HashSet<RoleModel>();
+        for (RoleModel mapping : roles) {
+            if (!mapping.isComposite()) continue;
+            if (searchCompositeFor(role, mapping, visited)) return true;
+
+        }
+        return false;
     }
 
-    protected TypedQuery<RealmUserRoleMappingEntity> getRealmUserRoleMappingEntityTypedQuery(UserAdapter user, RoleAdapter role) {
-        TypedQuery<RealmUserRoleMappingEntity> query = em.createNamedQuery("userHasRealmRole", RealmUserRoleMappingEntity.class);
+    protected TypedQuery<UserRoleMappingEntity> getUserRoleMappingEntityTypedQuery(UserAdapter user, RoleAdapter role) {
+        TypedQuery<UserRoleMappingEntity> query = em.createNamedQuery("userHasRole", UserRoleMappingEntity.class);
         query.setParameter("user", ((UserAdapter)user).getUser());
-        query.setParameter("role", ((RoleAdapter)role).getRole());
-        query.setParameter("realm", realm);
+        query.setParameter("role", ((RoleAdapter) role).getRole());
         return query;
     }
 
     @Override
     public void grantRole(UserModel user, RoleModel role) {
         if (hasRole(user, role)) return;
-        RealmUserRoleMappingEntity entity = new RealmUserRoleMappingEntity();
-        entity.setRealm(realm);
+        UserRoleMappingEntity entity = new UserRoleMappingEntity();
         entity.setUser(((UserAdapter) user).getUser());
         entity.setRole(((RoleAdapter)role).getRole());
         em.persist(entity);
@@ -906,79 +941,69 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
-    public List<RoleModel> getRoleMappings(UserModel user) {
-        TypedQuery<RealmUserRoleMappingEntity> query = em.createNamedQuery("userRealmMappings", RealmUserRoleMappingEntity.class);
-        query.setParameter("user", ((UserAdapter)user).getUser());
-        query.setParameter("realm", realm);
-        List<RealmUserRoleMappingEntity> entities = query.getResultList();
-        List<RoleModel> roles = new ArrayList<RoleModel>();
-        for (RealmUserRoleMappingEntity entity : entities) {
-            roles.add(new RoleAdapter(entity.getRole()));
+    public Set<RoleModel> getRealmRoleMappings(UserModel user) {
+        Set<RoleModel> roleMappings = getRoleMappings(user);
+
+        Set<RoleModel> realmRoles = new HashSet<RoleModel>();
+        for (RoleModel role : roleMappings) {
+            RoleContainerModel container = role.getContainer();
+            if (container instanceof RealmModel) {
+               realmRoles.add(role);
+            }
         }
-        return roles;
+        return realmRoles;
     }
 
+
     @Override
-    public Set<String> getRoleMappingValues(UserModel user) {
-        TypedQuery<RealmUserRoleMappingEntity> query = em.createNamedQuery("userRealmMappings", RealmUserRoleMappingEntity.class);
+    public Set<RoleModel> getRoleMappings(UserModel user) {
+        TypedQuery<UserRoleMappingEntity> query = em.createNamedQuery("userRoleMappings", UserRoleMappingEntity.class);
         query.setParameter("user", ((UserAdapter)user).getUser());
-        query.setParameter("realm", realm);
-        List<RealmUserRoleMappingEntity> entities = query.getResultList();
-        Set<String> roles = new HashSet<String>();
-        for (RealmUserRoleMappingEntity entity : entities) {
-            roles.add(entity.getRole().getName());
+        List<UserRoleMappingEntity> entities = query.getResultList();
+        Set<RoleModel> roles = new HashSet<RoleModel>();
+        for (UserRoleMappingEntity entity : entities) {
+            roles.add(new RoleAdapter(this, em, entity.getRole()));
         }
         return roles;
     }
 
     @Override
     public void deleteRoleMapping(UserModel user, RoleModel role) {
-        TypedQuery<RealmUserRoleMappingEntity> query = getRealmUserRoleMappingEntityTypedQuery((UserAdapter) user, (RoleAdapter) role);
-        List<RealmUserRoleMappingEntity> results = query.getResultList();
+        TypedQuery<UserRoleMappingEntity> query = getUserRoleMappingEntityTypedQuery((UserAdapter) user, (RoleAdapter) role);
+        List<UserRoleMappingEntity> results = query.getResultList();
         if (results.size() == 0) return;
-        for (RealmUserRoleMappingEntity entity : results) {
+        for (UserRoleMappingEntity entity : results) {
             em.remove(entity);
         }
         em.flush();
     }
 
     @Override
-    public boolean hasRole(UserModel user, String roleName) {
-        RoleModel role = getRole(roleName);
-        if (role == null) return false;
-        return hasRole(user, role);
-    }
+    public Set<RoleModel> getRealmScopeMappings(UserModel user) {
+        Set<RoleModel> roleMappings = getScopeMappings(user);
 
-    @Override
-    public void addScopeMapping(UserModel agent, String roleName) {
-        RoleModel role = getRole(roleName);
-        if (role == null) throw new RuntimeException("role does not exist");
-        addScopeMapping(agent, role);
-        em.flush();
-    }
-
-    @Override
-    public Set<String> getScopeMappingValues(UserModel agent) {
-        TypedQuery<RealmScopeMappingEntity> query = em.createNamedQuery("userRealmScopeMappings", RealmScopeMappingEntity.class);
-        query.setParameter("user", ((UserAdapter)agent).getUser());
-        query.setParameter("realm", realm);
-        List<RealmScopeMappingEntity> entities = query.getResultList();
-        Set<String> roles = new HashSet<String>();
-        for (RealmScopeMappingEntity entity : entities) {
-            roles.add(entity.getRole().getName());
+        Set<RoleModel> appRoles = new HashSet<RoleModel>();
+        for (RoleModel role : roleMappings) {
+            RoleContainerModel container = role.getContainer();
+            if (container instanceof RealmModel) {
+                if (((RealmModel)container).getId().equals(getId())) {
+                    appRoles.add(role);
+                }
+            }
         }
-        return roles;
+
+        return appRoles;
     }
 
+
     @Override
-    public List<RoleModel> getScopeMappings(UserModel agent) {
-        TypedQuery<RealmScopeMappingEntity> query = em.createNamedQuery("userRealmScopeMappings", RealmScopeMappingEntity.class);
+    public Set<RoleModel> getScopeMappings(UserModel agent) {
+        TypedQuery<UserScopeMappingEntity> query = em.createNamedQuery("userScopeMappings", UserScopeMappingEntity.class);
         query.setParameter("user", ((UserAdapter)agent).getUser());
-        query.setParameter("realm", realm);
-        List<RealmScopeMappingEntity> entities = query.getResultList();
-        List<RoleModel> roles = new ArrayList<RoleModel>();
-        for (RealmScopeMappingEntity entity : entities) {
-            roles.add(new RoleAdapter(entity.getRole()));
+        List<UserScopeMappingEntity> entities = query.getResultList();
+        Set<RoleModel> roles = new HashSet<RoleModel>();
+        for (UserScopeMappingEntity entity : entities) {
+            roles.add(new RoleAdapter(this, em, entity.getRole()));
         }
         return roles;
     }
@@ -986,8 +1011,7 @@ public class RealmAdapter implements RealmModel {
     @Override
     public void addScopeMapping(UserModel agent, RoleModel role) {
         if (hasScope(agent, role)) return;
-        RealmScopeMappingEntity entity = new RealmScopeMappingEntity();
-        entity.setRealm(realm);
+        UserScopeMappingEntity entity = new UserScopeMappingEntity();
         entity.setUser(((UserAdapter) agent).getUser());
         entity.setRole(((RoleAdapter)role).getRole());
         em.persist(entity);
@@ -996,25 +1020,24 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public void deleteScopeMapping(UserModel user, RoleModel role) {
-        TypedQuery<RealmScopeMappingEntity> query = getRealmScopeMappingQuery((UserAdapter) user, (RoleAdapter) role);
-        List<RealmScopeMappingEntity> results = query.getResultList();
+        TypedQuery<UserScopeMappingEntity> query = getRealmScopeMappingQuery((UserAdapter) user, (RoleAdapter) role);
+        List<UserScopeMappingEntity> results = query.getResultList();
         if (results.size() == 0) return;
-        for (RealmScopeMappingEntity entity : results) {
+        for (UserScopeMappingEntity entity : results) {
             em.remove(entity);
         }
     }
 
     public boolean hasScope(UserModel user, RoleModel role) {
-        TypedQuery<RealmScopeMappingEntity> query = getRealmScopeMappingQuery((UserAdapter) user, (RoleAdapter) role);
+        TypedQuery<UserScopeMappingEntity> query = getRealmScopeMappingQuery((UserAdapter) user, (RoleAdapter) role);
         return query.getResultList().size() > 0;
     }
 
 
-    protected TypedQuery<RealmScopeMappingEntity> getRealmScopeMappingQuery(UserAdapter user, RoleAdapter role) {
-        TypedQuery<RealmScopeMappingEntity> query = em.createNamedQuery("userHasRealmScope", RealmScopeMappingEntity.class);
+    protected TypedQuery<UserScopeMappingEntity> getRealmScopeMappingQuery(UserAdapter user, RoleAdapter role) {
+        TypedQuery<UserScopeMappingEntity> query = em.createNamedQuery("userHasScope", UserScopeMappingEntity.class);
         query.setParameter("user", ((UserAdapter)user).getUser());
         query.setParameter("role", ((RoleAdapter)role).getRole());
-        query.setParameter("realm", realm);
         return query;
     }
 
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
index 5785dec..87c09d0 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
@@ -1,16 +1,28 @@
 package org.keycloak.models.jpa;
 
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleContainerModel;
 import org.keycloak.models.RoleModel;
+import org.keycloak.models.jpa.entities.ApplicationRoleEntity;
+import org.keycloak.models.jpa.entities.RealmRoleEntity;
 import org.keycloak.models.jpa.entities.RoleEntity;
 
+import javax.persistence.EntityManager;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
 public class RoleAdapter implements RoleModel {
     protected RoleEntity role;
+    protected EntityManager em;
+    protected RealmModel realm;
 
-    public RoleAdapter(RoleEntity role) {
+    public RoleAdapter(RealmModel realm, EntityManager em, RoleEntity role) {
+        this.realm = realm;
         this.role = role;
     }
 
@@ -46,4 +58,72 @@ public class RoleAdapter implements RoleModel {
     public void setName(String name) {
         role.setName(name);
     }
+
+    @Override
+    public boolean isComposite() {
+        return role.isComposite();
+    }
+
+    @Override
+    public void setComposite(boolean flag) {
+        role.setComposite(flag);
+    }
+
+    @Override
+    public void addCompositeRole(RoleModel role) {
+        RoleEntity entity = ((RoleAdapter)role).getRole();
+        for (RoleEntity composite : getRole().getCompositeRoles()) {
+            if (composite.equals(entity)) return;
+        }
+        getRole().getCompositeRoles().add(entity);
+    }
+
+    @Override
+    public void removeCompositeRole(RoleModel role) {
+        RoleEntity entity = ((RoleAdapter)role).getRole();
+        Iterator<RoleEntity> it = getRole().getCompositeRoles().iterator();
+        while (it.hasNext()) {
+            if (it.next().equals(entity)) it.remove();
+        }
+    }
+
+    @Override
+    public Set<RoleModel> getComposites() {
+        Set<RoleModel> set = new HashSet<RoleModel>();
+
+        for (RoleEntity composite : getRole().getCompositeRoles()) {
+           set.add(new RoleAdapter(realm, em, composite));
+        }
+        return set;
+    }
+
+    @Override
+    public RoleContainerModel getContainer() {
+        if (role instanceof ApplicationRoleEntity) {
+            ApplicationRoleEntity entity = (ApplicationRoleEntity)role;
+            return new ApplicationAdapter(realm, em, entity.getApplication());
+        } else if (role instanceof RealmRoleEntity) {
+            RealmRoleEntity entity = (RealmRoleEntity)role;
+            return new RealmAdapter(em, entity.getRealm());
+
+        }
+        throw new IllegalStateException("Unknown role entity type");
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        RoleAdapter that = (RoleAdapter) o;
+
+        if (!role.equals(that.role)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return role.hashCode();
+    }
 }

model/pom.xml 2(+1 -1)

diff --git a/model/pom.xml b/model/pom.xml
index 002c7fc..ab454ca 100755
--- a/model/pom.xml
+++ b/model/pom.xml
@@ -35,7 +35,7 @@
     </build>
     <modules>
         <module>api</module>
-        <module>picketlink</module>
+        <!-- <module>picketlink</module> -->
         <module>jpa</module>
         <!-- <module>mongo</module> -->
     </modules>

services/pom.xml 2(+2 -0)

diff --git a/services/pom.xml b/services/pom.xml
index af4945d..7502bbe 100755
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -47,12 +47,14 @@
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
+        <!--
         <dependency>
             <groupId>org.keycloak</groupId>
             <artifactId>keycloak-model-picketlink</artifactId>
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
+        -->
 
         <!--<dependency>
             <groupId>org.keycloak</groupId>
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 04986f3..f557310 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
@@ -74,11 +74,11 @@ public class ApplianceBootstrap {
         realm.updateCredential(adminUser, password);
         adminUser.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
 
-        adminConsole.grantRole(adminUser, adminRole);
+        realm.grantRole(adminUser, adminRole);
 
         ApplicationModel accountApp = realm.getApplicationNameMap().get(Constants.ACCOUNT_APPLICATION);
         for (String r : accountApp.getDefaultRoles()) {
-            accountApp.grantRole(adminUser, accountApp.getRole(r));
+            realm.grantRole(adminUser, accountApp.getRole(r));
         }
     }
 
diff --git a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java b/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
index 72ea03b..721636c 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
@@ -102,7 +102,7 @@ public class ApplicationManager {
                 if (role == null) {
                     role = applicationModel.addRole(roleString.trim());
                 }
-                applicationModel.grantRole(user, role);
+                realm.grantRole(user, role);
             }
         }
     }
@@ -115,7 +115,7 @@ public class ApplicationManager {
                 if (role == null) {
                     role = applicationModel.addRole(roleString.trim());
                 }
-                applicationModel.addScopeMapping(user, role.getName());
+                realm.addScopeMapping(user, role);
             }
         }
     }
@@ -125,6 +125,13 @@ public class ApplicationManager {
         return createApplication(realm, loginRole, resourceRep);
     }
 
+    public ApplicationModel createApplication(RealmModel realm, String name) {
+        RoleModel loginRole = realm.getRole(Constants.APPLICATION_ROLE);
+        ApplicationModel app = realm.addApplication(name);
+        realm.grantRole(app.getApplicationUser(), loginRole);
+        return app;
+    }
+
     public void updateApplication(ApplicationRepresentation rep, ApplicationModel resource) {
         resource.setName(rep.getName());
         resource.setEnabled(rep.isEnabled());
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 5a8542a..60ee3b8 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -9,6 +9,7 @@ import org.keycloak.jose.jws.JWSBuilder;
 import org.keycloak.models.Constants;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.representations.SkeletonKeyToken;
 import org.keycloak.representations.idm.CredentialRepresentation;
@@ -250,16 +251,18 @@ public class AuthenticationManager {
         }
 
         if (!user.isEnabled()) {
-            logger.debug("Account is disabled, contact admin.");
+            logger.debug("Account is disabled, contact admin. " + user.getLoginName());
             return AuthenticationStatus.ACCOUNT_DISABLED;
         }
 
         Set<String> types = new HashSet<String>();
 
         List<RequiredCredentialModel> requiredCredentials = null;
-        if (realm.hasRole(user, Constants.APPLICATION_ROLE)) {
+        RoleModel applicationRole = realm.getRole(Constants.APPLICATION_ROLE);
+        RoleModel identityRequesterRole = realm.getRole(Constants.IDENTITY_REQUESTER_ROLE);
+        if (realm.hasRole(user, applicationRole)) {
             requiredCredentials = realm.getRequiredApplicationCredentials();
-        } else if (realm.hasRole(user, Constants.IDENTITY_REQUESTER_ROLE)) {
+        } else if (realm.hasRole(user, identityRequesterRole)) {
             requiredCredentials = realm.getRequiredOAuthClientCredentials();
         } else {
             requiredCredentials = realm.getRequiredCredentials();
@@ -289,6 +292,7 @@ public class AuthenticationManager {
             } else {
                 logger.debug("validating password for user: " + user.getLoginName());
                 if (!realm.validatePassword(user, password)) {
+                    logger.debug("invalid password for user: " + user.getLoginName());
                     return AuthenticationStatus.INVALID_CREDENTIALS;
                 }
             }
diff --git a/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java b/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
new file mode 100755
index 0000000..7b14523
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
@@ -0,0 +1,112 @@
+package org.keycloak.services.managers;
+
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ModelToRepresentation {
+    public static UserRepresentation toRepresentation(UserModel user) {
+        UserRepresentation rep = new UserRepresentation();
+        rep.setUsername(user.getLoginName());
+        rep.setLastName(user.getLastName());
+        rep.setFirstName(user.getFirstName());
+        rep.setEmail(user.getEmail());
+        rep.setEnabled(user.isEnabled());
+        rep.setEmailVerified(user.isEmailVerified());
+        rep.setTotp(user.isTotp());
+
+        List<String> reqActions = new ArrayList<String>();
+        for (UserModel.RequiredAction ra : user.getRequiredActions()){
+            reqActions.add(ra.name());
+        }
+
+        rep.setRequiredActions(reqActions);
+
+        if (user.getAttributes() != null && !user.getAttributes().isEmpty()) {
+            Map<String, String> attrs = new HashMap<String, String>();
+            attrs.putAll(user.getAttributes());
+            rep.setAttributes(attrs);
+        }
+        return rep;
+    }
+
+    public static RoleRepresentation toRepresentation(RoleModel role) {
+        RoleRepresentation rep = new RoleRepresentation();
+        rep.setId(role.getId());
+        rep.setName(role.getName());
+        rep.setDescription(role.getDescription());
+        rep.setComposite(role.isComposite());
+        return rep;
+    }
+
+    public static RealmRepresentation toRepresentation(RealmModel realm) {
+        RealmRepresentation rep = new RealmRepresentation();
+        rep.setId(realm.getId());
+        rep.setRealm(realm.getName());
+        rep.setEnabled(realm.isEnabled());
+        rep.setSocial(realm.isSocial());
+        rep.setUpdateProfileOnInitialSocialLogin(realm.isUpdateProfileOnInitialSocialLogin());
+        rep.setSslNotRequired(realm.isSslNotRequired());
+        rep.setPublicKey(realm.getPublicKeyPem());
+        rep.setPrivateKey(realm.getPrivateKeyPem());
+        rep.setRegistrationAllowed(realm.isRegistrationAllowed());
+        rep.setVerifyEmail(realm.isVerifyEmail());
+        rep.setResetPasswordAllowed(realm.isResetPasswordAllowed());
+        rep.setTokenLifespan(realm.getTokenLifespan());
+        rep.setAccessCodeLifespan(realm.getAccessCodeLifespan());
+        rep.setAccessCodeLifespanUserAction(realm.getAccessCodeLifespanUserAction());
+        rep.setSmtpServer(realm.getSmtpConfig());
+        rep.setSocialProviders(realm.getSocialConfig());
+        if (realm.getPasswordPolicy() != null) {
+            rep.setPasswordPolicy(realm.getPasswordPolicy().toString());
+        }
+
+        ApplicationModel accountManagementApplication = realm.getApplicationNameMap().get(Constants.ACCOUNT_APPLICATION);
+
+        List<String> defaultRoles = realm.getDefaultRoles();
+        if (!defaultRoles.isEmpty()) {
+            List<String> roleStrings = new ArrayList<String>();
+            roleStrings.addAll(defaultRoles);
+            rep.setDefaultRoles(roleStrings);
+        }
+
+        List<RequiredCredentialModel> requiredCredentialModels = realm.getRequiredCredentials();
+        if (requiredCredentialModels.size() > 0) {
+            rep.setRequiredCredentials(new HashSet<String>());
+            for (RequiredCredentialModel cred : requiredCredentialModels) {
+                rep.getRequiredCredentials().add(cred.getType());
+            }
+        }
+        List<RequiredCredentialModel> requiredResourceCredentialModels = realm.getRequiredApplicationCredentials();
+        if (requiredResourceCredentialModels.size() > 0) {
+            rep.setRequiredApplicationCredentials(new HashSet<String>());
+            for (RequiredCredentialModel cred : requiredResourceCredentialModels) {
+                rep.getRequiredApplicationCredentials().add(cred.getType());
+            }
+        }
+        List<RequiredCredentialModel> requiredOAuthCredentialModels = realm.getRequiredOAuthClientCredentials();
+        if (requiredOAuthCredentialModels.size() > 0) {
+            rep.setRequiredOAuthClientCredentials(new HashSet<String>());
+            for (RequiredCredentialModel cred : requiredOAuthCredentialModels) {
+                rep.getRequiredOAuthClientCredentials().add(cred.getType());
+            }
+        }
+        return rep;
+    }
+}
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 54908a0..c7fb26b 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -309,7 +309,7 @@ public class RealmManager {
                         role = newRealm.addRole(roleString.trim());
                     }
                     UserModel user = userMap.get(scope.getUsername());
-                    newRealm.addScopeMapping(user, role.getName());
+                    newRealm.addScopeMapping(user, role);
                 }
 
             }
@@ -422,93 +422,4 @@ public class RealmManager {
     }
 
 
-    public static UserRepresentation toRepresentation(UserModel user) {
-        UserRepresentation rep = new UserRepresentation();
-        rep.setUsername(user.getLoginName());
-        rep.setLastName(user.getLastName());
-        rep.setFirstName(user.getFirstName());
-        rep.setEmail(user.getEmail());
-        rep.setEnabled(user.isEnabled());
-        rep.setEmailVerified(user.isEmailVerified());
-        rep.setTotp(user.isTotp());
-
-        List<String> reqActions = new ArrayList<String>();
-        for (RequiredAction ra : user.getRequiredActions()){
-            reqActions.add(ra.name());
-        }
-
-        rep.setRequiredActions(reqActions);
-
-        if (user.getAttributes() != null && !user.getAttributes().isEmpty()) {
-            Map<String, String> attrs = new HashMap<String, String>();
-            attrs.putAll(user.getAttributes());
-            rep.setAttributes(attrs);
-        }
-        return rep;
-    }
-
-    public static RoleRepresentation toRepresentation(RoleModel role) {
-        RoleRepresentation rep = new RoleRepresentation();
-        rep.setId(role.getId());
-        rep.setName(role.getName());
-        rep.setDescription(role.getDescription());
-        return rep;
-    }
-
-    public static RealmRepresentation toRepresentation(RealmModel realm) {
-        RealmRepresentation rep = new RealmRepresentation();
-        rep.setId(realm.getId());
-        rep.setRealm(realm.getName());
-        rep.setEnabled(realm.isEnabled());
-        rep.setSocial(realm.isSocial());
-        rep.setUpdateProfileOnInitialSocialLogin(realm.isUpdateProfileOnInitialSocialLogin());
-        rep.setSslNotRequired(realm.isSslNotRequired());
-        rep.setPublicKey(realm.getPublicKeyPem());
-        rep.setPrivateKey(realm.getPrivateKeyPem());
-        rep.setRegistrationAllowed(realm.isRegistrationAllowed());
-        rep.setVerifyEmail(realm.isVerifyEmail());
-        rep.setResetPasswordAllowed(realm.isResetPasswordAllowed());
-        rep.setTokenLifespan(realm.getTokenLifespan());
-        rep.setAccessCodeLifespan(realm.getAccessCodeLifespan());
-        rep.setAccessCodeLifespanUserAction(realm.getAccessCodeLifespanUserAction());
-        rep.setSmtpServer(realm.getSmtpConfig());
-        rep.setSocialProviders(realm.getSocialConfig());
-        if (realm.getPasswordPolicy() != null) {
-            rep.setPasswordPolicy(realm.getPasswordPolicy().toString());
-        }
-
-        ApplicationModel accountManagementApplication = realm.getApplicationNameMap().get(Constants.ACCOUNT_APPLICATION);
-
-        List<String> defaultRoles = realm.getDefaultRoles();
-        if (!defaultRoles.isEmpty()) {
-            List<String> roleStrings = new ArrayList<String>();
-            roleStrings.addAll(defaultRoles);
-            rep.setDefaultRoles(roleStrings);
-        }
-
-        List<RequiredCredentialModel> requiredCredentialModels = realm.getRequiredCredentials();
-        if (requiredCredentialModels.size() > 0) {
-            rep.setRequiredCredentials(new HashSet<String>());
-            for (RequiredCredentialModel cred : requiredCredentialModels) {
-                rep.getRequiredCredentials().add(cred.getType());
-            }
-        }
-        List<RequiredCredentialModel> requiredResourceCredentialModels = realm.getRequiredApplicationCredentials();
-        if (requiredResourceCredentialModels.size() > 0) {
-            rep.setRequiredApplicationCredentials(new HashSet<String>());
-            for (RequiredCredentialModel cred : requiredResourceCredentialModels) {
-                rep.getRequiredApplicationCredentials().add(cred.getType());
-            }
-        }
-        List<RequiredCredentialModel> requiredOAuthCredentialModels = realm.getRequiredOAuthClientCredentials();
-        if (requiredOAuthCredentialModels.size() > 0) {
-            rep.setRequiredOAuthClientCredentials(new HashSet<String>());
-            for (RequiredCredentialModel cred : requiredOAuthCredentialModels) {
-                rep.getRequiredOAuthClientCredentials().add(cred.getType());
-            }
-        }
-        return rep;
-    }
-
-
 }
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 3cd575b..6531942 100755
--- a/services/src/main/java/org/keycloak/services/managers/TokenManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/TokenManager.java
@@ -2,7 +2,6 @@ package org.keycloak.services.managers;
 
 import org.jboss.resteasy.logging.Logger;
 import org.keycloak.jose.jws.JWSBuilder;
-import org.keycloak.util.JsonSerialization;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.RealmModel;
@@ -11,11 +10,12 @@ import org.keycloak.models.UserModel;
 import org.keycloak.representations.SkeletonKeyScope;
 import org.keycloak.representations.SkeletonKeyToken;
 import org.keycloak.util.Base64Url;
+import org.keycloak.util.JsonSerialization;
 
 import javax.ws.rs.core.MultivaluedMap;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
-import java.util.HashSet;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -44,48 +44,60 @@ public class TokenManager {
         return accessCodeMap.remove(key);
     }
 
+    protected boolean desiresScope(SkeletonKeyScope scope, String key, String roleName) {
+        if (scope == null || scope.isEmpty()) return true;
+        List<String> val = scope.get(key);
+        if (val == null) return false;
+        return val.contains(roleName);
 
-    public AccessCodeEntry createAccessCode(String scopeParam, String state, String redirect, RealmModel realm, UserModel client, UserModel user) {
-        boolean applicationResource = realm.hasRole(client, realm.getRole(Constants.APPLICATION_ROLE));
+    }
+
+    protected boolean desiresScopeGroup(SkeletonKeyScope scope, String key) {
+        if (scope == null || scope.isEmpty()) return true;
+        return scope.containsKey(key);
+    }
+
+    protected boolean isEmpty(SkeletonKeyScope scope) {
+        return scope == null || scope.isEmpty();
+    }
 
+
+    public AccessCodeEntry createAccessCode(String scopeParam, String state, String redirect, RealmModel realm, UserModel client, UserModel user) {
         AccessCodeEntry code = new AccessCodeEntry();
         SkeletonKeyScope scopeMap = null;
         if (scopeParam != null) scopeMap = decodeScope(scopeParam);
         List<RoleModel> realmRolesRequested = code.getRealmRolesRequested();
         MultivaluedMap<String, RoleModel> resourceRolesRequested = code.getResourceRolesRequested();
-        Set<String> realmMapping = realm.getRoleMappingValues(user);
-
-        if (realmMapping != null && realmMapping.size() > 0 && (scopeMap == null || scopeMap.containsKey("realm"))) {
-            Set<String> scope = realm.getScopeMappingValues(client);
-            if (scope.size() > 0) {
-                Set<String> scopeRequest = scopeMap != null ? new HashSet<String>(scopeMap.get("realm")) : null;
-                for (String role : realmMapping) {
-                    if ((scopeRequest == null || scopeRequest.contains(role)) && scope.contains(role))
-                        realmRolesRequested.add(realm.getRole(role));
-                }
+
+        Set<RoleModel> realmScopeMappings = realm.getRealmScopeMappings(client);
+        for (RoleModel desiredRole : realmScopeMappings) {
+            if (!realm.hasRole(user, desiredRole)) continue;
+            if (desiresScope(scopeMap, "realm", desiredRole.getName())) {
+                realmRolesRequested.add(desiredRole);
             }
         }
-        for (ApplicationModel resource : realm.getApplications()) {
-            if (applicationResource && resource.getApplicationUser().getLoginName().equals(client.getLoginName())) {
-                for (String role : resource.getRoleMappingValues(user)) {
-                    resourceRolesRequested.addAll(resource.getName(), resource.getRole(role));
+
+        for (ApplicationModel application : realm.getApplications()) {
+            if (!desiresScopeGroup(scopeMap, application.getName())) continue;
+            Set<RoleModel> desiredRoles = application.getApplicationScopeMappings(client);
+            if (desiredRoles.isEmpty()) {
+                if (application.getApplicationUser().getLoginName().equals(client.getLoginName())) {
+                    Set<RoleModel> appRoleMappings = application.getApplicationRoleMappings(user);
+                    for (RoleModel desiredAppRole : appRoleMappings) {
+                        if (desiresScope(scopeMap, application.getName(), desiredAppRole.getName())) {
+                            resourceRolesRequested.add(application.getName(), desiredAppRole);
+                        }
+                    }
                 }
             } else {
-                Set<String> mapping = resource.getRoleMappingValues(user);
-                if (mapping != null && mapping.size() > 0 && (scopeMap == null || scopeMap.containsKey(resource.getName()))) {
-                    Set<String> scope = resource.getScopeMappingValues(client);
-                    if (scope.size() > 0) {
-                        Set<String> scopeRequest = scopeMap != null ? new HashSet<String>(scopeMap.get(resource.getName())) : null;
-                        for (String role : mapping) {
-                            if ((scopeRequest == null || scopeRequest.contains(role)) && scope.contains(role))
-                                resourceRolesRequested.add(resource.getName(), resource.getRole(role));
-                        }
+                for (RoleModel desiredAppRole : desiredRoles) {
+                    if (realm.hasRole(user, desiredAppRole) && desiresScope(scopeMap, application.getName(), desiredAppRole.getName())) {
+                        resourceRolesRequested.add(application.getName(), desiredAppRole);
                     }
                 }
             }
         }
 
-
         createToken(code, realm, client, user);
         code.setRealm(realm);
         code.setExpiration((System.currentTimeMillis() / 1000) + realm.getAccessCodeLifespan());
@@ -121,6 +133,34 @@ public class TokenManager {
         return token;
     }
 
+    protected void addComposites(SkeletonKeyToken token, RoleModel role) {
+        SkeletonKeyToken.Access access = null;
+        if (role.getContainer() instanceof RealmModel) {
+            access = token.getRealmAccess();
+            if (token.getRealmAccess() == null) {
+                access = new SkeletonKeyToken.Access();
+                token.setRealmAccess(access);
+            } else if (token.getRealmAccess().getRoles() != null && token.getRealmAccess().isUserInRole(role.getName()))
+                return;
+
+        } else {
+            ApplicationModel app = (ApplicationModel) role.getContainer();
+            access = token.getResourceAccess(app.getName());
+            if (access == null) {
+                access = token.addAccess(app.getName());
+                if (app.isSurrogateAuthRequired()) access.verifyCaller(true);
+            } else if (access.isUserInRole(role.getName())) return;
+
+        }
+        access.addRole(role.getName());
+        if (!role.isComposite()) return;
+
+        for (RoleModel composite : role.getComposites()) {
+            addComposites(token, composite);
+        }
+
+    }
+
     protected void createToken(AccessCodeEntry accessCodeEntry, RealmModel realm, UserModel client, UserModel user) {
 
         SkeletonKeyToken token = initToken(realm, client, user);
@@ -128,18 +168,14 @@ public class TokenManager {
         if (accessCodeEntry.getRealmRolesRequested().size() > 0) {
             SkeletonKeyToken.Access access = new SkeletonKeyToken.Access();
             for (RoleModel role : accessCodeEntry.getRealmRolesRequested()) {
-                access.addRole(role.getName());
+                addComposites(token, role);
             }
-            token.setRealmAccess(access);
         }
 
         if (accessCodeEntry.getResourceRolesRequested().size() > 0) {
-            Map<String, ApplicationModel> resourceMap = realm.getApplicationNameMap();
-            for (String resourceName : accessCodeEntry.getResourceRolesRequested().keySet()) {
-                ApplicationModel resource = resourceMap.get(resourceName);
-                SkeletonKeyToken.Access access = token.addAccess(resourceName).verifyCaller(resource.isSurrogateAuthRequired());
-                for (RoleModel role : accessCodeEntry.getResourceRolesRequested().get(resourceName)) {
-                    access.addRole(role.getName());
+            for (List<RoleModel> roles : accessCodeEntry.getResourceRolesRequested().values()) {
+                for (RoleModel role : roles) {
+                    addComposites(token, role);
                 }
             }
         }
@@ -169,7 +205,6 @@ public class TokenManager {
 
 
     public SkeletonKeyToken createAccessToken(RealmModel realm, UserModel user) {
-        List<ApplicationModel> resources = realm.getApplications();
         SkeletonKeyToken token = new SkeletonKeyToken();
         token.id(RealmManager.generateId());
         token.issuedNow();
@@ -178,26 +213,8 @@ public class TokenManager {
         if (realm.getTokenLifespan() > 0) {
             token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan());
         }
-
-        Set<String> realmMapping = realm.getRoleMappingValues(user);
-
-        if (realmMapping != null && realmMapping.size() > 0) {
-            SkeletonKeyToken.Access access = new SkeletonKeyToken.Access();
-            for (String role : realmMapping) {
-                access.addRole(role);
-            }
-            token.setRealmAccess(access);
-        }
-        if (resources != null) {
-            for (ApplicationModel resource : resources) {
-                Set<String> mapping = resource.getRoleMappingValues(user);
-                if (mapping == null) continue;
-                SkeletonKeyToken.Access access = token.addAccess(resource.getName())
-                        .verifyCaller(resource.isSurrogateAuthRequired());
-                for (String role : mapping) {
-                    access.addRole(role);
-                }
-            }
+        for (RoleModel role : realm.getRoleMappings(user)) {
+            addComposites(token, role);
         }
         return token;
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index 36f529a..ef86c57 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -33,7 +33,7 @@ import org.keycloak.representations.SkeletonKeyToken;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.services.managers.AccessCodeEntry;
 import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.managers.RealmManager;
+import org.keycloak.services.managers.ModelToRepresentation;
 import org.keycloak.services.managers.TokenManager;
 import org.keycloak.services.messages.Messages;
 import org.keycloak.services.resources.flows.Flows;
@@ -124,7 +124,7 @@ public class AccountService {
             if (!hasAccess(auth, Constants.ACCOUNT_PROFILE_ROLE)) {
                 return Response.status(Response.Status.FORBIDDEN).build();
             }
-            return Cors.add(request, Response.ok(RealmManager.toRepresentation(auth.getUser()))).auth().allowedOrigins(auth.getClient()).build();
+            return Cors.add(request, Response.ok(ModelToRepresentation.toRepresentation(auth.getUser()))).auth().allowedOrigins(auth.getClient()).build();
         } else {
             return Response.notAcceptable(Variant.VariantListBuilder.newInstance().mediaTypes(MediaType.TEXT_HTML_TYPE, MediaType.APPLICATION_JSON_TYPE).build()).build();
         }
@@ -382,7 +382,7 @@ public class AccountService {
 
     private boolean hasAccess(AuthenticationManager.Auth auth, String role) {
         UserModel client = auth.getClient();
-        if (realm.hasRole(client, Constants.APPLICATION_ROLE)) {
+        if (realm.hasRole(client, realm.getRole(Constants.APPLICATION_ROLE))) {
             // Tokens from cookies don't have roles
             UserModel user = auth.getUser();
             if (hasRole(user, Constants.ACCOUNT_MANAGE_ROLE) || (role != null && hasRole(user, role))) {
@@ -401,7 +401,7 @@ public class AccountService {
     }
 
     private boolean hasRole(UserModel user, String role) {
-        return application.hasRole(user, role);
+        return realm.hasRole(user, application.getRole(role));
     }
 
     private String getReferrer() {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
index 52b372a..a2cdc28 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
@@ -191,7 +191,7 @@ public class AdminService {
             throw new NotFoundException();
         }
         RoleModel adminRole = adminConsole.getRole(Constants.ADMIN_CONSOLE_ADMIN_ROLE);
-        if (!adminConsole.hasRole(admin, adminRole)) {
+        if (!saasRealm.hasRole(admin, adminRole)) {
             logger.warn("not a Realm admin");
             throw new NotAuthorizedException("Bearer");
         }
@@ -308,7 +308,8 @@ public class AdminService {
                 logger.debug("bad client");
                 return redirectOnLoginError("invalid login data");
             }
-            if (!adminConsole.hasRole(accessCode.getUser(), Constants.ADMIN_CONSOLE_ADMIN_ROLE)) {
+            RoleModel adminConsoleAdminRole = adminConsole.getRole(Constants.ADMIN_CONSOLE_ADMIN_ROLE);
+            if (!realm.hasRole(accessCode.getUser(), adminConsoleAdminRole)) {
                 logger.debug("not allowed");
                 return redirectOnLoginError("No permission to access console");
             }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index ab8cc39..09f2fc8 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -6,6 +6,7 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.managers.ModelToRepresentation;
 import org.keycloak.services.managers.RealmManager;
 
 import javax.ws.rs.*;
@@ -51,7 +52,7 @@ public class RealmAdminResource extends RoleContainerResource {
     @NoCache
     @Produces("application/json")
     public RealmRepresentation getRealm() {
-        return RealmManager.toRepresentation(realm);
+        return ModelToRepresentation.toRepresentation(realm);
     }
 
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
index 97883cb..fe60118 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
@@ -9,6 +9,7 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.managers.ModelToRepresentation;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.resources.flows.Flows;
 
@@ -59,7 +60,7 @@ public class RealmsAdminResource {
         List<RealmModel> realms = session.getRealms(admin);
         List<RealmRepresentation> reps = new ArrayList<RealmRepresentation>();
         for (RealmModel realm : realms) {
-            reps.add(realmManager.toRepresentation(realm));
+            reps.add(ModelToRepresentation.toRepresentation(realm));
         }
         return reps;
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
index 6253c7c..3d43178 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
@@ -5,6 +5,7 @@ import org.keycloak.models.Constants;
 import org.keycloak.models.RoleContainerModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.services.managers.ModelToRepresentation;
 import org.keycloak.services.resources.flows.Flows;
 
 import javax.ws.rs.*;
@@ -12,7 +13,10 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -34,9 +38,7 @@ public class RoleContainerResource {
         List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
         for (RoleModel roleModel : roleModels) {
             if (!roleModel.getName().startsWith(Constants.INTERNAL_ROLE)) {
-                RoleRepresentation role = new RoleRepresentation(roleModel.getName(), roleModel.getDescription());
-                role.setId(roleModel.getId());
-                roles.add(role);
+                roles.add(ModelToRepresentation.toRepresentation(roleModel));
             }
         }
         return roles;
@@ -51,9 +53,7 @@ public class RoleContainerResource {
         if (roleModel == null || roleModel.getName().startsWith(Constants.INTERNAL_ROLE)) {
             throw new NotFoundException("Could not find role: " + roleName);
         }
-        RoleRepresentation rep = new RoleRepresentation(roleModel.getName(), roleModel.getDescription());
-        rep.setId(roleModel.getId());
-        return rep;
+        return ModelToRepresentation.toRepresentation(roleModel);
     }
 
     @Path("roles/{role-name}")
@@ -79,8 +79,65 @@ public class RoleContainerResource {
         }
         role.setName(rep.getName());
         role.setDescription(rep.getDescription());
+        role.setComposite(rep.isComposite());
     }
 
+    @Path("roles/{role-name}/composites")
+    @POST
+    @Consumes("application/json")
+    public void addComposites(final @PathParam("role-name") String roleName, List<RoleRepresentation> roles) {
+        RoleModel role = roleContainer.getRole(roleName);
+        if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) {
+            throw new NotFoundException("Could not find role: " + roleName);
+        }
+        for (RoleRepresentation rep : roles) {
+            RoleModel composite = roleContainer.getRole(rep.getName());
+            if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) {
+                throw new NotFoundException("Could not find composite role: " + rep.getName());
+            }
+            if (!role.isComposite()) role.setComposite(true);
+            role.addCompositeRole(composite);
+        }
+    }
+
+    @Path("roles/{role-name}/composites")
+    @GET
+    @NoCache
+    @Produces("application/json")
+    public Set<RoleRepresentation> getRoleComposites(final @PathParam("role-name") String roleName) {
+        RoleModel role = roleContainer.getRole(roleName);
+        if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) {
+            throw new NotFoundException("Could not find role: " + roleName);
+        }
+        if (!role.isComposite() || role.getComposites().size() == 0) return Collections.emptySet();
+
+        Set<RoleRepresentation> composites = new HashSet<RoleRepresentation>(role.getComposites().size());
+        for (RoleModel composite : role.getComposites()) {
+            composites.add(ModelToRepresentation.toRepresentation(composite));
+        }
+        return composites;
+    }
+
+
+    @Path("roles/{role-name}/composites")
+    @DELETE
+    @Consumes("application/json")
+    public void deleteComposites(final @PathParam("role-name") String roleName, List<RoleRepresentation> roles) {
+        RoleModel role = roleContainer.getRole(roleName);
+        if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) {
+            throw new NotFoundException("Could not find role: " + roleName);
+        }
+        for (RoleRepresentation rep : roles) {
+            RoleModel composite = roleContainer.getRole(rep.getName());
+            if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) {
+                throw new NotFoundException("Could not find composite role: " + rep.getName());
+            }
+            role.removeCompositeRole(composite);
+        }
+        if (role.getComposites().size() > 0) role.setComposite(false);
+    }
+
+
     @Path("roles")
     @POST
     @Consumes("application/json")
@@ -93,6 +150,7 @@ public class RoleContainerResource {
             throw new NotFoundException();
         }
         role.setDescription(rep.getDescription());
+        role.setComposite(rep.isComposite());
         return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getName()).build()).build();
     }
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java
index b3e6f01..c630d28 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java
@@ -9,6 +9,7 @@ import org.keycloak.models.UserModel;
 import org.keycloak.representations.idm.ApplicationMappingsRepresentation;
 import org.keycloak.representations.idm.MappingsRepresentation;
 import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.services.managers.ModelToRepresentation;
 import org.keycloak.services.managers.RealmManager;
 
 import javax.ws.rs.Consumes;
@@ -23,6 +24,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -44,12 +46,12 @@ public class ScopeMappedResource {
     @NoCache
     public MappingsRepresentation getScopeMappings() {
         MappingsRepresentation all = new MappingsRepresentation();
-        List<RoleModel> realmMappings = realm.getScopeMappings(agent);
+        Set<RoleModel> realmMappings = realm.getRealmScopeMappings(agent);
         RealmManager manager = new RealmManager(session);
         if (realmMappings.size() > 0) {
             List<RoleRepresentation> realmRep = new ArrayList<RoleRepresentation>();
             for (RoleModel roleModel : realmMappings) {
-                realmRep.add(manager.toRepresentation(roleModel));
+                realmRep.add(ModelToRepresentation.toRepresentation(roleModel));
             }
             all.setRealmMappings(realmRep);
         }
@@ -58,7 +60,7 @@ public class ScopeMappedResource {
         if (applications.size() > 0) {
             Map<String, ApplicationMappingsRepresentation> appMappings = new HashMap<String, ApplicationMappingsRepresentation>();
             for (ApplicationModel app : applications) {
-                List<RoleModel> roleMappings = app.getScopeMappings(agent);
+                Set<RoleModel> roleMappings = app.getApplicationScopeMappings(agent);
                 if (roleMappings.size() > 0) {
                     ApplicationMappingsRepresentation mappings = new ApplicationMappingsRepresentation();
                     mappings.setApplicationId(app.getId());
@@ -66,7 +68,7 @@ public class ScopeMappedResource {
                     List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
                     mappings.setMappings(roles);
                     for (RoleModel role : roleMappings) {
-                        roles.add(manager.toRepresentation(role));
+                        roles.add(ModelToRepresentation.toRepresentation(role));
                     }
                     appMappings.put(app.getName(), mappings);
                     all.setApplicationMappings(appMappings);
@@ -81,11 +83,11 @@ public class ScopeMappedResource {
     @Produces("application/json")
     @NoCache
     public List<RoleRepresentation> getRealmScopeMappings() {
-        List<RoleModel> realmMappings = realm.getScopeMappings(agent);
+        Set<RoleModel> realmMappings = realm.getRealmScopeMappings(agent);
         List<RoleRepresentation> realmMappingsRep = new ArrayList<RoleRepresentation>();
         RealmManager manager = new RealmManager(session);
         for (RoleModel roleModel : realmMappings) {
-            realmMappingsRep.add(manager.toRepresentation(roleModel));
+            realmMappingsRep.add(ModelToRepresentation.toRepresentation(roleModel));
         }
         return realmMappingsRep;
     }
@@ -110,7 +112,7 @@ public class ScopeMappedResource {
     @Consumes("application/json")
     public void deleteRealmScopeMappings(List<RoleRepresentation> roles) {
         if (roles == null) {
-            List<RoleModel> roleModels = realm.getScopeMappings(agent);
+            Set<RoleModel> roleModels = realm.getRealmScopeMappings(agent);
             for (RoleModel roleModel : roleModels) {
                 realm.deleteScopeMapping(agent, roleModel);
             }
@@ -137,10 +139,10 @@ public class ScopeMappedResource {
             throw new NotFoundException();
         }
 
-        List<RoleModel> mappings = app.getScopeMappings(agent);
+        Set<RoleModel> mappings = app.getApplicationScopeMappings(agent);
         List<RoleRepresentation> mapRep = new ArrayList<RoleRepresentation>();
         for (RoleModel roleModel : mappings) {
-            mapRep.add(RealmManager.toRepresentation(roleModel));
+            mapRep.add(ModelToRepresentation.toRepresentation(roleModel));
         }
         return mapRep;
     }
@@ -160,7 +162,7 @@ public class ScopeMappedResource {
             if (roleModel == null) {
                 throw new NotFoundException();
             }
-            app.addScopeMapping(agent, roleModel);
+            realm.addScopeMapping(agent, roleModel);
         }
 
     }
@@ -168,7 +170,7 @@ public class ScopeMappedResource {
     @Path("applications/{app}")
     @DELETE
     @Consumes("application/json")
-    public void deleteApplicationRoleMapping(@PathParam("app") String appName, List<RoleRepresentation> roles) {
+    public void deleteApplicationScopeMapping(@PathParam("app") String appName, List<RoleRepresentation> roles) {
         ApplicationModel app = realm.getApplicationByName(appName);
 
         if (app == null) {
@@ -176,9 +178,9 @@ public class ScopeMappedResource {
         }
 
         if (roles == null) {
-            List<RoleModel> roleModels = app.getScopeMappings(agent);
+            Set<RoleModel> roleModels = app.getApplicationScopeMappings(agent);
             for (RoleModel roleModel : roleModels) {
-                app.deleteScopeMapping(agent, roleModel);
+                realm.deleteScopeMapping(agent, roleModel);
             }
 
         } else {
@@ -187,7 +189,7 @@ public class ScopeMappedResource {
                 if (roleModel == null) {
                     throw new NotFoundException();
                 }
-                app.deleteScopeMapping(agent, roleModel);
+                realm.deleteScopeMapping(agent, roleModel);
             }
         }
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index bd643c7..a95c30c 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -10,6 +10,7 @@ import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.representations.idm.*;
+import org.keycloak.services.managers.ModelToRepresentation;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.resources.flows.Flows;
 
@@ -32,6 +33,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -115,7 +117,7 @@ public class UsersResource {
         if (user == null || !isUser(user)) {
             throw new NotFoundException();
         }
-        return new RealmManager(session).toRepresentation(user);
+        return ModelToRepresentation.toRepresentation(user);
     }
 
     @Path("{username}")
@@ -154,7 +156,7 @@ public class UsersResource {
             }
             userModels = realm.searchForUserByAttributes(attributes);
             for (UserModel user : userModels) {
-                results.add(manager.toRepresentation(user));
+                results.add(ModelToRepresentation.toRepresentation(user));
             }
         } else {
             userModels = realm.getUsers();
@@ -162,7 +164,7 @@ public class UsersResource {
 
         for (UserModel user : userModels) {
             if (isUser(user)) {
-                results.add(manager.toRepresentation(user));
+                results.add(ModelToRepresentation.toRepresentation(user));
             }
         }
         return results;
@@ -183,12 +185,12 @@ public class UsersResource {
         }
 
         MappingsRepresentation all = new MappingsRepresentation();
-        List<RoleModel> realmMappings = realm.getRoleMappings(user);
+        Set<RoleModel> realmMappings = realm.getRoleMappings(user);
         RealmManager manager = new RealmManager(session);
         if (realmMappings.size() > 0) {
             List<RoleRepresentation> realmRep = new ArrayList<RoleRepresentation>();
             for (RoleModel roleModel : realmMappings) {
-                realmRep.add(manager.toRepresentation(roleModel));
+                realmRep.add(ModelToRepresentation.toRepresentation(roleModel));
             }
             all.setRealmMappings(realmRep);
         }
@@ -197,7 +199,7 @@ public class UsersResource {
         if (applications.size() > 0) {
             Map<String, ApplicationMappingsRepresentation> appMappings = new HashMap<String, ApplicationMappingsRepresentation>();
             for (ApplicationModel application : applications) {
-                List<RoleModel> roleMappings = application.getRoleMappings(user);
+                Set<RoleModel> roleMappings = application.getApplicationRoleMappings(user);
                 if (roleMappings.size() > 0) {
                     ApplicationMappingsRepresentation mappings = new ApplicationMappingsRepresentation();
                     mappings.setApplicationId(application.getId());
@@ -205,7 +207,7 @@ public class UsersResource {
                     List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
                     mappings.setMappings(roles);
                     for (RoleModel role : roleMappings) {
-                        roles.add(manager.toRepresentation(role));
+                        roles.add(ModelToRepresentation.toRepresentation(role));
                     }
                     appMappings.put(application.getName(), mappings);
                     all.setApplicationMappings(appMappings);
@@ -225,11 +227,11 @@ public class UsersResource {
             throw new NotFoundException();
         }
 
-        List<RoleModel> realmMappings = realm.getRoleMappings(user);
+        Set<RoleModel> realmMappings = realm.getRealmRoleMappings(user);
         List<RoleRepresentation> realmMappingsRep = new ArrayList<RoleRepresentation>();
         RealmManager manager = new RealmManager(session);
         for (RoleModel roleModel : realmMappings) {
-            realmMappingsRep.add(manager.toRepresentation(roleModel));
+            realmMappingsRep.add(ModelToRepresentation.toRepresentation(roleModel));
         }
         return realmMappingsRep;
     }
@@ -266,7 +268,7 @@ public class UsersResource {
         }
 
         if (roles == null) {
-            List<RoleModel> roleModels = realm.getRoleMappings(user);
+            Set<RoleModel> roleModels = realm.getRealmRoleMappings(user);
             for (RoleModel roleModel : roleModels) {
                 realm.deleteRoleMapping(user, roleModel);
             }
@@ -300,10 +302,10 @@ public class UsersResource {
             throw new NotFoundException();
         }
 
-        List<RoleModel> mappings = application.getRoleMappings(user);
+        Set<RoleModel> mappings = application.getApplicationRoleMappings(user);
         List<RoleRepresentation> mapRep = new ArrayList<RoleRepresentation>();
         for (RoleModel roleModel : mappings) {
-            mapRep.add(RealmManager.toRepresentation(roleModel));
+            mapRep.add(ModelToRepresentation.toRepresentation(roleModel));
         }
         logger.debug("getApplicationRoleMappings.size() = {0}", mapRep.size());
         return mapRep;
@@ -330,7 +332,7 @@ public class UsersResource {
             if (roleModel == null) {
                 throw new NotFoundException();
             }
-            application.grantRole(user, roleModel);
+            realm.grantRole(user, roleModel);
         }
 
     }
@@ -351,9 +353,13 @@ public class UsersResource {
         }
 
         if (roles == null) {
-            List<RoleModel> roleModels = application.getRoleMappings(user);
+            Set<RoleModel> roleModels = application.getApplicationRoleMappings(user);
             for (RoleModel roleModel : roleModels) {
-                application.deleteRoleMapping(user, roleModel);
+                if (!(roleModel.getContainer() instanceof ApplicationModel)) {
+                   ApplicationModel app = (ApplicationModel)roleModel.getContainer();
+                    if (!app.getId().equals(application.getId())) continue;
+                }
+                realm.deleteRoleMapping(user, roleModel);
             }
 
         } else {
@@ -362,7 +368,7 @@ public class UsersResource {
                 if (roleModel == null) {
                     throw new NotFoundException();
                 }
-                application.deleteRoleMapping(user, roleModel);
+                realm.deleteRoleMapping(user, roleModel);
             }
         }
     }
diff --git a/services/src/test/java/org/keycloak/test/AdapterTest.java b/services/src/test/java/org/keycloak/test/AdapterTest.java
index 08a0057..3c49cd4 100755
--- a/services/src/test/java/org/keycloak/test/AdapterTest.java
+++ b/services/src/test/java/org/keycloak/test/AdapterTest.java
@@ -170,7 +170,7 @@ public class AdapterTest extends AbstractKeycloakTest {
 
         OAuthClientModel oauth = new OAuthClientManager(realmModel).create("oauth-client");
         oauth = realmModel.getOAuthClient("oauth-client");
-        Assert.assertTrue(realmModel.hasRole(oauth.getOAuthAgent(), Constants.IDENTITY_REQUESTER_ROLE));
+        Assert.assertTrue(realmModel.hasRole(oauth.getOAuthAgent(), realmModel.getRole(Constants.IDENTITY_REQUESTER_ROLE)));
 
 
     }
@@ -188,7 +188,7 @@ public class AdapterTest extends AbstractKeycloakTest {
 
         ApplicationModel app = realmModel.addApplication("test-app");
         RoleModel appRole = app.addRole("test");
-        app.grantRole(user, appRole);
+        realmModel.grantRole(user, appRole);
 
         SocialLinkModel socialLink = new SocialLinkModel("google", user.getLoginName());
         realmModel.addSocialLink(user, socialLink);
@@ -214,8 +214,8 @@ public class AdapterTest extends AbstractKeycloakTest {
         ApplicationModel app = realmModel.addApplication("test-app");
 
         RoleModel appRole = app.addRole("test");
-        app.grantRole(user, appRole);
-        app.addScopeMapping(client.getOAuthAgent(), appRole);
+        realmModel.grantRole(user, appRole);
+        realmModel.addScopeMapping(client.getOAuthAgent(), appRole);
 
         RoleModel realmRole = realmModel.addRole("test");
         realmModel.addScopeMapping(app.getApplicationUser(), realmRole);
@@ -242,8 +242,8 @@ public class AdapterTest extends AbstractKeycloakTest {
         ApplicationModel app = realmModel.addApplication("test-app");
 
         RoleModel appRole = app.addRole("test");
-        app.grantRole(user, appRole);
-        app.addScopeMapping(client.getOAuthAgent(), appRole);
+        realmModel.grantRole(user, appRole);
+        realmModel.addScopeMapping(client.getOAuthAgent(), appRole);
 
         RoleModel realmRole = realmModel.addRole("test");
         realmModel.addScopeMapping(app.getApplicationUser(), realmRole);
@@ -265,8 +265,8 @@ public class AdapterTest extends AbstractKeycloakTest {
         ApplicationModel app = realmModel.addApplication("test-app");
 
         RoleModel appRole = app.addRole("test");
-        app.grantRole(user, appRole);
-        app.addScopeMapping(client.getOAuthAgent(), appRole);
+        realmModel.grantRole(user, appRole);
+        realmModel.addScopeMapping(client.getOAuthAgent(), appRole);
 
         RoleModel realmRole = realmModel.addRole("test");
         realmModel.addScopeMapping(app.getApplicationUser(), realmRole);
diff --git a/services/src/test/java/org/keycloak/test/ImportTest.java b/services/src/test/java/org/keycloak/test/ImportTest.java
index 383c683..d7ad50c 100755
--- a/services/src/test/java/org/keycloak/test/ImportTest.java
+++ b/services/src/test/java/org/keycloak/test/ImportTest.java
@@ -7,6 +7,7 @@ import org.junit.runners.MethodSorters;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
 import org.keycloak.models.SocialLinkModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.representations.idm.RealmRepresentation;
@@ -49,7 +50,7 @@ public class ImportTest extends AbstractKeycloakTest {
 
         UserModel user = realm.getUser("loginclient");
         Assert.assertNotNull(user);
-        Set<String> scopes = realm.getScopeMappingValues(user);
+        Set<RoleModel> scopes = realm.getRealmScopeMappings(user);
         Assert.assertEquals(0, scopes.size());
         Assert.assertEquals(0, realm.getSocialLinks(user).size());
 
@@ -61,8 +62,9 @@ public class ImportTest extends AbstractKeycloakTest {
         UserModel oauthClient = realm.getUser("oauthclient");
         Assert.assertNotNull(application);
         Assert.assertNotNull(oauthClient);
-        Set<String> appScopes = application.getScopeMappingValues(oauthClient);
-        Assert.assertTrue(appScopes.contains("user"));
+        Set<RoleModel> appScopes = application.getApplicationScopeMappings(oauthClient);
+        RoleModel appUserRole = application.getRole("user");
+        Assert.assertTrue(appScopes.contains(appUserRole));
 
         // Test social linking
         UserModel socialUser = realm.getUser("mySocialUser");
diff --git a/services/src/test/java/org/keycloak/test/ModelTest.java b/services/src/test/java/org/keycloak/test/ModelTest.java
index 32a428b..cdec004 100755
--- a/services/src/test/java/org/keycloak/test/ModelTest.java
+++ b/services/src/test/java/org/keycloak/test/ModelTest.java
@@ -10,6 +10,7 @@ import org.keycloak.models.PasswordPolicy;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.managers.ModelToRepresentation;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.resources.KeycloakApplication;
 
@@ -101,7 +102,7 @@ public class ModelTest extends AbstractKeycloakServerTest {
     }
 
     private RealmModel importExport(RealmModel src, String copyName) {
-        RealmRepresentation representation = manager.toRepresentation(src);
+        RealmRepresentation representation = ModelToRepresentation.toRepresentation(src);
         RealmModel copy = manager.createRealm(copyName);
         manager.importRealm(representation, copy);
         return manager.getRealm(copy.getId());
diff --git a/services/src/test/resources/META-INF/persistence.xml b/services/src/test/resources/META-INF/persistence.xml
index ae026ef..2fb76f2 100755
--- a/services/src/test/resources/META-INF/persistence.xml
+++ b/services/src/test/resources/META-INF/persistence.xml
@@ -2,6 +2,7 @@
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
     version="1.0">
+    <!--
     <persistence-unit name="picketlink-keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
         <provider>org.hibernate.ejb.HibernatePersistence</provider>
 
@@ -33,23 +34,22 @@
             <property name="hibernate.format_sql" value="true" />
         </properties>
     </persistence-unit>
+    -->
 
     <persistence-unit name="jpa-keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
         <provider>org.hibernate.ejb.HibernatePersistence</provider>
 
         <class>org.keycloak.models.jpa.entities.ApplicationEntity</class>
-        <class>org.keycloak.models.jpa.entities.ApplicationScopeMappingEntity</class>
-        <class>org.keycloak.models.jpa.entities.ApplicationUserRoleMappingEntity</class>
         <class>org.keycloak.models.jpa.entities.CredentialEntity</class>
         <class>org.keycloak.models.jpa.entities.OAuthClientEntity</class>
         <class>org.keycloak.models.jpa.entities.RealmEntity</class>
-        <class>org.keycloak.models.jpa.entities.RealmScopeMappingEntity</class>
-        <class>org.keycloak.models.jpa.entities.RealmUserRoleMappingEntity</class>
         <class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
-        <class>org.keycloak.models.jpa.entities.RoleEntity</class>
+        <class>org.keycloak.models.jpa.entities.ApplicationRoleEntity</class>
+        <class>org.keycloak.models.jpa.entities.RealmRoleEntity</class>
         <class>org.keycloak.models.jpa.entities.SocialLinkEntity</class>
         <class>org.keycloak.models.jpa.entities.UserEntity</class>
         <class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
+        <class>org.keycloak.models.jpa.entities.UserScopeMappingEntity</class>
 
         <exclude-unlisted-classes>true</exclude-unlisted-classes>
 
diff --git a/testsuite/integration/pom.xml b/testsuite/integration/pom.xml
index d0ee3c9..e3fffc5 100755
--- a/testsuite/integration/pom.xml
+++ b/testsuite/integration/pom.xml
@@ -61,11 +61,13 @@
             <artifactId>keycloak-model-jpa</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <!--
         <dependency>
             <groupId>org.keycloak</groupId>
             <artifactId>keycloak-model-picketlink</artifactId>
             <version>${project.version}</version>
         </dependency>
+        -->
         <dependency>
             <groupId>org.keycloak</groupId>
             <artifactId>keycloak-social-core</artifactId>
diff --git a/testsuite/integration/src/main/resources/META-INF/persistence.xml b/testsuite/integration/src/main/resources/META-INF/persistence.xml
index 5a4df6c..a020d60 100755
--- a/testsuite/integration/src/main/resources/META-INF/persistence.xml
+++ b/testsuite/integration/src/main/resources/META-INF/persistence.xml
@@ -6,18 +6,16 @@
         <provider>org.hibernate.ejb.HibernatePersistence</provider>
 
         <class>org.keycloak.models.jpa.entities.ApplicationEntity</class>
-        <class>org.keycloak.models.jpa.entities.ApplicationScopeMappingEntity</class>
-        <class>org.keycloak.models.jpa.entities.ApplicationUserRoleMappingEntity</class>
         <class>org.keycloak.models.jpa.entities.CredentialEntity</class>
         <class>org.keycloak.models.jpa.entities.OAuthClientEntity</class>
         <class>org.keycloak.models.jpa.entities.RealmEntity</class>
-        <class>org.keycloak.models.jpa.entities.RealmScopeMappingEntity</class>
-        <class>org.keycloak.models.jpa.entities.RealmUserRoleMappingEntity</class>
         <class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
-        <class>org.keycloak.models.jpa.entities.RoleEntity</class>
+        <class>org.keycloak.models.jpa.entities.ApplicationRoleEntity</class>
+        <class>org.keycloak.models.jpa.entities.RealmRoleEntity</class>
         <class>org.keycloak.models.jpa.entities.SocialLinkEntity</class>
         <class>org.keycloak.models.jpa.entities.UserEntity</class>
         <class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
+        <class>org.keycloak.models.jpa.entities.UserScopeMappingEntity</class>
 
         <exclude-unlisted-classes>true</exclude-unlisted-classes>
 
@@ -32,6 +30,7 @@
         </properties>
     </persistence-unit>
 
+    <!--
     <persistence-unit name="picketlink-keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
         <provider>org.hibernate.ejb.HibernatePersistence</provider>
 
@@ -63,4 +62,5 @@
             <property name="hibernate.format_sql" value="true" />
         </properties>
     </persistence-unit>
+    -->
 </persistence>
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
index 7a8f2a2..f520c70 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
@@ -58,7 +58,7 @@ public class ProfileTest {
             UserModel user2 = appRealm.addUser("test-user-no-access@localhost");
             user2.setEnabled(true);
             for (String r : accountApp.getDefaultRoles()) {
-                accountApp.deleteRoleMapping(user2, accountApp.getRole(r));
+                appRealm.deleteRoleMapping(user2, accountApp.getRole(r));
             }
             UserCredentialModel creds = new UserCredentialModel();
             creds.setType(CredentialRepresentation.PASSWORD);
@@ -66,12 +66,12 @@ public class ProfileTest {
             appRealm.updateCredential(user2, creds);
 
             ApplicationModel app = appRealm.getApplicationNameMap().get("test-app");
-            accountApp.addScopeMapping(app.getApplicationUser(), org.keycloak.models.Constants.ACCOUNT_PROFILE_ROLE);
+            appRealm.addScopeMapping(app.getApplicationUser(), accountApp.getRole(org.keycloak.models.Constants.ACCOUNT_PROFILE_ROLE));
 
             app.getApplicationUser().addWebOrigin("http://localtest.me:8081");
 
             UserModel thirdParty = appRealm.getUser("third-party");
-            accountApp.addScopeMapping(thirdParty, org.keycloak.models.Constants.ACCOUNT_PROFILE_ROLE);
+            appRealm.addScopeMapping(thirdParty, accountApp.getRole(org.keycloak.models.Constants.ACCOUNT_PROFILE_ROLE));
         }
     });
 
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
new file mode 100755
index 0000000..ddde357
--- /dev/null
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
@@ -0,0 +1,157 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.testsuite.composites;
+
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.SkeletonKeyToken;
+import org.keycloak.services.managers.ApplicationManager;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.ApplicationServlet;
+import org.keycloak.testsuite.OAuthClient;
+import org.keycloak.testsuite.OAuthClient.AccessTokenResponse;
+import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.rule.AbstractKeycloakRule;
+import org.keycloak.testsuite.rule.WebResource;
+import org.keycloak.testsuite.rule.WebRule;
+import org.openqa.selenium.WebDriver;
+
+import java.security.PublicKey;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class CompositeRoleTest {
+
+    public static PublicKey realmPublicKey;
+    @ClassRule
+    public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule(){
+        @Override
+        protected void configure(RealmManager manager, RealmModel adminRealm) {
+            RealmModel realm = manager.createRealm("Test");
+            manager.generateRealmKeys(realm);
+            realmPublicKey = realm.getPublicKey();
+            realm.setTokenLifespan(10000);
+            realm.setSslNotRequired(true);
+            realm.setEnabled(true);
+            realm.addRequiredResourceCredential(UserCredentialModel.PASSWORD);
+            realm.addRequiredOAuthClientCredential(UserCredentialModel.PASSWORD);
+            realm.addRequiredCredential(UserCredentialModel.PASSWORD);
+            final RoleModel realmRole1 = realm.addRole("REALM_ROLE_1");
+            final RoleModel realmRole2 = realm.addRole("REALM_ROLE_2");
+            final RoleModel realmRole3 = realm.addRole("REALM_ROLE_3");
+            final RoleModel realmComposite1 = realm.addRole("REALM_COMPOSITE_1");
+            realmComposite1.setComposite(true);
+            realmComposite1.addCompositeRole(realmRole1);
+
+            final UserModel realmComposite1User = realm.addUser("REALM_COMPOSITE_1_USER");
+            realmComposite1User.setEnabled(true);
+            realm.updateCredential(realmComposite1User, UserCredentialModel.password("password"));
+            realm.grantRole(realmComposite1User, realmComposite1);
+
+            final ApplicationModel realmComposite1Application = new ApplicationManager(manager).createApplication(realm, "REALM_COMPOSITE_1_APPLICATION");
+            realmComposite1Application.setEnabled(true);
+            realmComposite1Application.addScope(realmComposite1);
+            realmComposite1Application.setBaseUrl("http://localhost:8081/app");
+            realmComposite1Application.setManagementUrl("http://localhost:8081/app/logout");
+            realm.updateCredential(realmComposite1Application.getApplicationUser(), UserCredentialModel.password("password"));
+
+            final ApplicationModel realmRole1Application = new ApplicationManager(manager).createApplication(realm, "REALM_ROLE_1_APPLICATION");
+            realmRole1Application.setEnabled(true);
+            realmRole1Application.addScope(realmRole1);
+            realmRole1Application.setBaseUrl("http://localhost:8081/app");
+            realmRole1Application.setManagementUrl("http://localhost:8081/app/logout");
+            realm.updateCredential(realmRole1Application.getApplicationUser(), UserCredentialModel.password("password"));
+
+
+
+            deployServlet("app", "/app", ApplicationServlet.class);
+
+        }
+    };
+
+    @Rule
+    public WebRule webRule = new WebRule(this);
+
+    @WebResource
+    protected WebDriver driver;
+
+    @WebResource
+    protected OAuthClient oauth;
+
+    @WebResource
+    protected LoginPage loginPage;
+
+    @Test
+    public void testRealmOnlyCompositeWithUserCompositeAppComposite() throws Exception {
+        oauth.realm("Test");
+        oauth.realmPublicKey(realmPublicKey);
+        oauth.clientId("REALM_COMPOSITE_1_APPLICATION");
+        oauth.doLogin("REALM_COMPOSITE_1_USER", "password");
+
+        String code = oauth.getCurrentQuery().get("code");
+        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+
+        Assert.assertEquals(200, response.getStatusCode());
+
+        Assert.assertEquals("bearer", response.getTokenType());
+
+        SkeletonKeyToken token = oauth.verifyToken(response.getAccessToken());
+
+        Assert.assertEquals("REALM_COMPOSITE_1_USER", token.getSubject());
+
+        Assert.assertEquals(2, token.getRealmAccess().getRoles().size());
+        Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_COMPOSITE_1"));
+        Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
+    }
+
+    @Test
+    public void testRealmOnlyCompositeWithUserCompositeAppRole() throws Exception {
+        oauth.realm("Test");
+        oauth.realmPublicKey(realmPublicKey);
+        oauth.clientId("REALM_ROLE_1_APPLICATION");
+        oauth.doLogin("REALM_COMPOSITE_1_USER", "password");
+
+        String code = oauth.getCurrentQuery().get("code");
+        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+
+        Assert.assertEquals(200, response.getStatusCode());
+
+        Assert.assertEquals("bearer", response.getTokenType());
+
+        SkeletonKeyToken token = oauth.verifyToken(response.getAccessToken());
+
+        Assert.assertEquals("REALM_COMPOSITE_1_USER", token.getSubject());
+
+        Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
+        Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
+    }
+
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AccountTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AccountTest.java
index 3a06d44..1d6262f 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AccountTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AccountTest.java
@@ -58,7 +58,7 @@ public class AccountTest {
             UserModel user2 = appRealm.addUser("test-user-no-access@localhost");
             user2.setEnabled(true);
             for (String r : accountApp.getDefaultRoles()) {
-                accountApp.deleteRoleMapping(user2, accountApp.getRole(r));
+                appRealm.deleteRoleMapping(user2, accountApp.getRole(r));
             }
             UserCredentialModel creds = new UserCredentialModel();
             creds.setType(CredentialRepresentation.PASSWORD);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
index 49acb71..7dbf997 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
@@ -226,6 +226,10 @@ public class OAuthClient {
         this.realm = realm;
         return this;
     }
+    public OAuthClient realmPublicKey(PublicKey key) {
+        this.realmPublicKey = key;
+        return this;
+    }
 
     public OAuthClient clientId(String clientId) {
         this.clientId = clientId;
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
new file mode 100755
index 0000000..caf6c58
--- /dev/null
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
@@ -0,0 +1,84 @@
+package org.keycloak.testsuite.rule;
+
+import io.undertow.servlet.api.DeploymentInfo;
+import io.undertow.servlet.api.ServletInfo;
+import org.junit.rules.ExternalResource;
+import org.keycloak.models.Constants;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testutils.KeycloakServer;
+import org.keycloak.util.JsonSerialization;
+
+import javax.servlet.Servlet;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractKeycloakRule extends ExternalResource {
+    protected KeycloakServer server;
+
+    protected void before() throws Throwable {
+        server = new KeycloakServer();
+        server.start();
+
+
+        setupKeycloak();
+    }
+
+    protected void setupKeycloak() {
+        KeycloakSession session = server.getKeycloakSessionFactory().createSession();
+        session.getTransaction().begin();
+
+        try {
+            RealmManager manager = new RealmManager(session);
+
+            RealmModel adminstrationRealm = manager.getRealm(Constants.ADMIN_REALM);
+
+            configure(manager, adminstrationRealm);
+
+            session.getTransaction().commit();
+        } finally {
+            session.close();
+        }
+
+    }
+
+    protected void configure(RealmManager manager, RealmModel adminRealm) {
+
+    }
+
+    public void deployServlet(String name, String contextPath, Class<? extends Servlet> servletClass) {
+        DeploymentInfo deploymentInfo = new DeploymentInfo();
+        deploymentInfo.setClassLoader(getClass().getClassLoader());
+        deploymentInfo.setDeploymentName(name);
+        deploymentInfo.setContextPath(contextPath);
+
+        ServletInfo servlet = new ServletInfo(servletClass.getSimpleName(), servletClass);
+        servlet.addMapping("/*");
+
+        deploymentInfo.addServlet(servlet);
+        server.getServer().deploy(deploymentInfo);
+    }
+
+    @Override
+    protected void after() {
+        server.stop();
+    }
+
+    public RealmRepresentation loadJson(String path) throws IOException {
+        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        int c;
+        while ((c = is.read()) != -1) {
+            os.write(c);
+        }
+        byte[] bytes = os.toByteArray();
+        return JsonSerialization.readValue(bytes, RealmRepresentation.class);
+    }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java
index 4668761..dd5c033 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java
@@ -41,9 +41,7 @@ import java.io.InputStream;
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
-public class KeycloakRule extends ExternalResource {
-
-    private KeycloakServer server;
+public class KeycloakRule extends AbstractKeycloakRule {
 
     private KeycloakSetup setup;
 
@@ -54,11 +52,9 @@ public class KeycloakRule extends ExternalResource {
         this.setup = setup;
     }
 
-    protected void before() throws Throwable {
-        server = new KeycloakServer();
-        server.start();
-
-        server.importRealm(getClass().getResourceAsStream("/testrealm.json"));
+    @Override
+    protected void setupKeycloak() {
+        importRealm();
 
         if (setup != null) {
             configure(setup);
@@ -67,33 +63,8 @@ public class KeycloakRule extends ExternalResource {
         deployServlet("app", "/app", ApplicationServlet.class);
     }
 
-    public void deployServlet(String name, String contextPath, Class<? extends Servlet> servletClass) {
-        DeploymentInfo deploymentInfo = new DeploymentInfo();
-        deploymentInfo.setClassLoader(getClass().getClassLoader());
-        deploymentInfo.setDeploymentName(name);
-        deploymentInfo.setContextPath(contextPath);
-
-        ServletInfo servlet = new ServletInfo(servletClass.getSimpleName(), servletClass);
-        servlet.addMapping("/*");
-
-        deploymentInfo.addServlet(servlet);
-        server.getServer().deploy(deploymentInfo);
-    }
-
-    @Override
-    protected void after() {
-        server.stop();
-    }
-
-    public RealmRepresentation loadJson(String path) throws IOException {
-        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
-        ByteArrayOutputStream os = new ByteArrayOutputStream();
-        int c;
-        while ((c = is.read()) != -1) {
-            os.write(c);
-        }
-        byte[] bytes = os.toByteArray();
-        return JsonSerialization.readValue(bytes, RealmRepresentation.class);
+    protected void importRealm() {
+        server.importRealm(getClass().getResourceAsStream("/testrealm.json"));
     }
 
     public void configure(KeycloakSetup configurer) {
@@ -106,7 +77,7 @@ public class KeycloakRule extends ExternalResource {
             RealmModel adminstrationRealm = manager.getRealm(Constants.ADMIN_REALM);
             RealmModel appRealm = manager.getRealm("test");
 
-            configurer.config(manager, null, appRealm);
+            configurer.config(manager, adminstrationRealm, appRealm);
 
             session.getTransaction().commit();
         } finally {
diff --git a/testsuite/performance/src/test/resources/META-INF/persistence.xml b/testsuite/performance/src/test/resources/META-INF/persistence.xml
index 8083104..2f67fde 100755
--- a/testsuite/performance/src/test/resources/META-INF/persistence.xml
+++ b/testsuite/performance/src/test/resources/META-INF/persistence.xml
@@ -2,6 +2,7 @@
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
              version="1.0">
+    <!--
     <persistence-unit name="picketlink-keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
         <provider>org.hibernate.ejb.HibernatePersistence</provider>
 
@@ -35,22 +36,21 @@
             <property name="hibernate.format_sql" value="true" />
         </properties>
     </persistence-unit>
+        -->
     <persistence-unit name="jpa-keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
         <provider>org.hibernate.ejb.HibernatePersistence</provider>
 
         <class>org.keycloak.models.jpa.entities.ApplicationEntity</class>
-        <class>org.keycloak.models.jpa.entities.ApplicationScopeMappingEntity</class>
-        <class>org.keycloak.models.jpa.entities.ApplicationUserRoleMappingEntity</class>
         <class>org.keycloak.models.jpa.entities.CredentialEntity</class>
         <class>org.keycloak.models.jpa.entities.OAuthClientEntity</class>
         <class>org.keycloak.models.jpa.entities.RealmEntity</class>
-        <class>org.keycloak.models.jpa.entities.RealmScopeMappingEntity</class>
-        <class>org.keycloak.models.jpa.entities.RealmUserRoleMappingEntity</class>
         <class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
-        <class>org.keycloak.models.jpa.entities.RoleEntity</class>
+        <class>org.keycloak.models.jpa.entities.ApplicationRoleEntity</class>
+        <class>org.keycloak.models.jpa.entities.RealmRoleEntity</class>
         <class>org.keycloak.models.jpa.entities.SocialLinkEntity</class>
         <class>org.keycloak.models.jpa.entities.UserEntity</class>
         <class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
+        <class>org.keycloak.models.jpa.entities.UserScopeMappingEntity</class>
 
         <exclude-unlisted-classes>true</exclude-unlisted-classes>