keycloak-aplcache

Merge pull request #191 from patriot1burke/master composite

2/4/2014 3:03:15 PM

Details

core/pom.xml 1(+1 -0)

diff --git a/core/pom.xml b/core/pom.xml
index 49d2275..011fa2a 100755
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -21,6 +21,7 @@
         <dependency>
             <groupId>net.iharder</groupId>
             <artifactId>base64</artifactId>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.codehaus.jackson</groupId>
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 14b4d5c..e98eaa6 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java
@@ -84,4 +84,9 @@ public class RoleRepresentation {
     public void setComposites(Composites composites) {
         this.composites = composites;
     }
+
+    @Override
+    public String toString() {
+        return name;
+    }
 }
diff --git a/distribution/modules/build.xml b/distribution/modules/build.xml
index 9ec84de..4b273e8 100755
--- a/distribution/modules/build.xml
+++ b/distribution/modules/build.xml
@@ -43,6 +43,10 @@
           ~ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
           -->
 
+        <module-def name="net.iharder.base64">
+            <maven-resource group="net.iharder" artifact="base64"/>
+        </module-def>
+
         <module-def name="org.bouncycastle">
             <maven-resource group="org.bouncycastle" artifact="bcprov-jdk16"/>
         </module-def>
diff --git a/distribution/modules/src/main/resources/modules/net/iharder/base64/main/module.xml b/distribution/modules/src/main/resources/modules/net/iharder/base64/main/module.xml
new file mode 100755
index 0000000..5f39dcf
--- /dev/null
+++ b/distribution/modules/src/main/resources/modules/net/iharder/base64/main/module.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ JBoss, Home of Professional Open Source.
+  ~ Copyright 2010, 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.
+  -->
+
+<module xmlns="urn:jboss:module:1.1" name="net.iharder.base64">
+    <resources>
+        <!-- Insert resources here -->
+    </resources>
+    <dependencies>
+        <module name="javax.api"/>
+    </dependencies>
+
+</module>
diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-core/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-core/main/module.xml
index a58f092..095e419 100755
--- a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-core/main/module.xml
+++ b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-core/main/module.xml
@@ -31,6 +31,7 @@
         <module name="org.codehaus.jackson.jackson-mapper-asl"/>
         <module name="org.codehaus.jackson.jackson-xc"/>
         <module name="org.bouncycastle"/>
+        <module name="net.iharder.base64"/>
         <module name="javax.api"/>
     </dependencies>
 
diff --git a/integration/as7-eap6/adapter/pom.xml b/integration/as7-eap6/adapter/pom.xml
index 35423e3..f4421de 100755
--- a/integration/as7-eap6/adapter/pom.xml
+++ b/integration/as7-eap6/adapter/pom.xml
@@ -29,6 +29,10 @@
             <version>${keycloak.apache.httpcomponents.version}</version>
         </dependency>
         <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.bouncycastle</groupId>
             <artifactId>bcprov-jdk16</artifactId>
         </dependency>
diff --git a/integration/servlet-oauth-client/pom.xml b/integration/servlet-oauth-client/pom.xml
index 9311ed2..67163af 100755
--- a/integration/servlet-oauth-client/pom.xml
+++ b/integration/servlet-oauth-client/pom.xml
@@ -41,6 +41,10 @@
             <artifactId>jackson-mapper-asl</artifactId>
         </dependency>
         <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.jboss.spec.javax.servlet</groupId>
             <artifactId>jboss-servlet-api_3.0_spec</artifactId>
             <scope>provided</scope>
diff --git a/integration/undertow/pom.xml b/integration/undertow/pom.xml
index 1781ef3..8012c35 100755
--- a/integration/undertow/pom.xml
+++ b/integration/undertow/pom.xml
@@ -35,6 +35,10 @@
             <version>${keycloak.apache.httpcomponents.version}</version>
         </dependency>
         <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.bouncycastle</groupId>
             <artifactId>bcprov-jdk16</artifactId>
         </dependency>
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 8f650c6..4703da9 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
@@ -269,4 +269,8 @@ public class ApplicationAdapter implements ApplicationModel {
         ApplicationAdapter app = (ApplicationAdapter)o;
         return app.getId().equals(getId());
     }
+
+    public String toString() {
+        return getName();
+    }
 }

server/pom.xml 4(+4 -0)

diff --git a/server/pom.xml b/server/pom.xml
index f07ec2a..3293918 100755
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -20,6 +20,10 @@
             <artifactId>bcprov-jdk16</artifactId>
         </dependency>
         <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.keycloak</groupId>
             <artifactId>keycloak-core</artifactId>
             <version>${project.version}</version>
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 0789941..9afb3ea 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -245,12 +245,6 @@ public class RealmManager {
             }
         }
 
-        if (rep.getRoles() != null && rep.getRoles().getRealm() != null) {
-            for (RoleRepresentation roleRep : rep.getRoles().getRealm()) {
-                createRole(newRealm, roleRep);
-            }
-        }
-
         if (rep.getRoles() != null) {
             if (rep.getRoles().getRealm() != null) { // realm roles
                 for (RoleRepresentation roleRep : rep.getRoles().getRealm()) {
@@ -270,10 +264,11 @@ public class RealmManager {
                     }
                 }
             }
-            // now that all roles are created, re-interate and set up composites
+            // now that all roles are created, re-iterate and set up composites
             if (rep.getRoles().getRealm() != null) { // realm roles
                 for (RoleRepresentation roleRep : rep.getRoles().getRealm()) {
-                    createRole(newRealm, roleRep);
+                    RoleModel role = newRealm.getRole(roleRep.getName());
+                    addComposites(role, roleRep, newRealm);
                 }
             }
             if (rep.getRoles().getApplication() != null) {
@@ -283,9 +278,8 @@ public class RealmManager {
                         throw new RuntimeException("App doesn't exist in role definitions: " + entry.getKey());
                     }
                     for (RoleRepresentation roleRep : entry.getValue()) {
-                        RoleModel role = app.addRole(roleRep.getName());
-                        role.setDescription(roleRep.getDescription());
-                        role.setComposite(roleRep.isComposite());
+                        RoleModel role = app.getRole(roleRep.getName());
+                        addComposites(role, roleRep, newRealm);
                     }
                 }
             }
@@ -298,27 +292,6 @@ public class RealmManager {
             }
         }
 
-        if (rep.getRoles() != null) {
-            if (rep.getRoles().getRealm() != null) { // realm roles
-                for (RoleRepresentation roleRep : rep.getRoles().getRealm()) {
-                    RoleModel role = newRealm.getRole(roleRep.getName());
-                    addComposites(role, roleRep, newRealm);
-                }
-            }
-            if (rep.getRoles().getApplication() != null) {
-                for (Map.Entry<String, List<RoleRepresentation>> entry : rep.getRoles().getApplication().entrySet()) {
-                    ApplicationModel app = newRealm.getApplicationByName(entry.getKey());
-                    if (app == null) {
-                        throw new RuntimeException("App doesn't exist in role definitions: " + entry.getKey());
-                    }
-                    for (RoleRepresentation roleRep : entry.getValue()) {
-                        RoleModel role = app.getRole(roleRep.getName());
-                        addComposites(role, roleRep, newRealm);
-                    }
-                }
-            }
-        }
-
         if (rep.getOauthClients() != null) {
             Map<String, OAuthClientModel> oauthMap = createOAuthClients(rep, newRealm);
             for (OAuthClientModel app : oauthMap.values()) {
@@ -431,6 +404,7 @@ public class RealmManager {
     public void createRole(RealmModel newRealm, RoleRepresentation roleRep) {
         RoleModel role = newRealm.addRole(roleRep.getName());
         if (roleRep.getDescription() != null) role.setDescription(roleRep.getDescription());
+        role.setComposite(roleRep.isComposite());
     }
 
     public void createRole(RealmModel newRealm, ApplicationModel app, RoleRepresentation roleRep) {
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 e447ab1..87d4025 100755
--- a/services/src/main/java/org/keycloak/services/managers/TokenManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/TokenManager.java
@@ -3,7 +3,6 @@ package org.keycloak.services.managers;
 import org.jboss.resteasy.logging.Logger;
 import org.keycloak.jose.jws.JWSBuilder;
 import org.keycloak.models.ApplicationModel;
-import org.keycloak.models.Constants;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
@@ -15,7 +14,6 @@ import org.keycloak.util.JsonSerialization;
 import javax.ws.rs.core.MultivaluedMap;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -62,7 +60,7 @@ public class TokenManager {
         return scope == null || scope.isEmpty();
     }
 
-    public static void addScopes(RoleModel role, RoleModel scope, Set<RoleModel> visited, Set<RoleModel> requested) {
+    public static void applyScope(RoleModel role, RoleModel scope, Set<RoleModel> visited, Set<RoleModel> requested) {
         if (visited.contains(scope)) return;
         visited.add(scope);
         if (role.hasRole(scope)) {
@@ -72,7 +70,7 @@ public class TokenManager {
         if (!scope.isComposite()) return;
 
         for (RoleModel contained : scope.getComposites()) {
-            addScopes(role, contained, visited, requested);
+            applyScope(role, contained, visited, requested);
         }
     }
 
@@ -98,7 +96,7 @@ public class TokenManager {
             if (clientApp != null && role.getContainer().equals(clientApp)) requestedRoles.add(role);
             for (RoleModel desiredRole : scopeMappings) {
                 Set<RoleModel> visited = new HashSet<RoleModel>();
-                addScopes(role, desiredRole, visited, requestedRoles);
+                applyScope(role, desiredRole, visited, requestedRoles);
             }
         }
 
@@ -114,35 +112,6 @@ public class TokenManager {
             }
         }
 
-
-
-
-        Set<RoleModel> realmRoleMappings = realm.getRealmRoleMappings(user);
-
-        for (RoleModel role : realmRoleMappings) {
-            if (!desiresScope(scopeMap, "realm", role.getName())) continue;
-            for (RoleModel desiredRole : scopeMappings) {
-                if (desiredRole.hasRole(role)) {
-                    realmRolesRequested.add(role);
-                } else if (role.hasRole(desiredRole)) {
-                    realmRolesRequested.add(desiredRole);
-                }
-            }
-        }
-
-        for (ApplicationModel application : realm.getApplications()) {
-            if (!desiresScopeGroup(scopeMap, application.getName())) continue;
-            Set<RoleModel> appRoleMappings = application.getApplicationRoleMappings(user);
-            for (RoleModel role : appRoleMappings) {
-                if (!desiresScope(scopeMap, application.getName(), role.getName())) continue;
-                for (RoleModel desiredRole : scopeMappings) {
-                    if (!application.getApplicationUser().getLoginName().equals(client.getLoginName())
-                          && !desiredRole.hasRole(role)) continue;
-                    resourceRolesRequested.add(application.getName(), role);
-                }
-            }
-        }
-
         createToken(code, realm, client, user);
         code.setRealm(realm);
         code.setExpiration((System.currentTimeMillis() / 1000) + realm.getAccessCodeLifespan());
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeImportRoleTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeImportRoleTest.java
new file mode 100755
index 0000000..ddd15ed
--- /dev/null
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeImportRoleTest.java
@@ -0,0 +1,200 @@
+/*
+ * 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.representations.idm.RealmRepresentation;
+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 CompositeImportRoleTest {
+
+    public static PublicKey realmPublicKey;
+    @ClassRule
+    public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule(){
+        @Override
+        protected void configure(RealmManager manager, RealmModel adminRealm) {
+            server.importRealm(getClass().getResourceAsStream("/testcomposite.json"));
+            RealmModel realm = manager.getRealmByName("Test");
+            realmPublicKey = realm.getPublicKey();
+
+
+
+            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 testAppCompositeUser() throws Exception {
+        oauth.realm("Test");
+        oauth.realmPublicKey(realmPublicKey);
+        oauth.clientId("APP_COMPOSITE_APPLICATION");
+        oauth.doLogin("APP_COMPOSITE_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("APP_COMPOSITE_USER", token.getSubject());
+
+        Assert.assertEquals(1, token.getResourceAccess("APP_ROLE_APPLICATION").getRoles().size());
+        Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
+        Assert.assertTrue(token.getResourceAccess("APP_ROLE_APPLICATION").isUserInRole("APP_ROLE_1"));
+        Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
+    }
+
+
+    @Test
+    public void testRealmAppCompositeUser() throws Exception {
+        oauth.realm("Test");
+        oauth.realmPublicKey(realmPublicKey);
+        oauth.clientId("APP_ROLE_APPLICATION");
+        oauth.doLogin("REALM_APP_COMPOSITE_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_APP_COMPOSITE_USER", token.getSubject());
+
+        Assert.assertEquals(1, token.getResourceAccess("APP_ROLE_APPLICATION").getRoles().size());
+        Assert.assertTrue(token.getResourceAccess("APP_ROLE_APPLICATION").isUserInRole("APP_ROLE_1"));
+    }
+
+
+
+    @Test
+    public void testRealmOnlyWithUserCompositeAppComposite() 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 testRealmOnlyWithUserCompositeAppRole() 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"));
+    }
+
+    @Test
+    public void testRealmOnlyWithUserRoleAppComposite() throws Exception {
+        oauth.realm("Test");
+        oauth.realmPublicKey(realmPublicKey);
+        oauth.clientId("REALM_COMPOSITE_1_APPLICATION");
+        oauth.doLogin("REALM_ROLE_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_ROLE_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/resources/testcomposite.json b/testsuite/integration/src/test/resources/testcomposite.json
new file mode 100755
index 0000000..2b6a48a
--- /dev/null
+++ b/testsuite/integration/src/test/resources/testcomposite.json
@@ -0,0 +1,234 @@
+{
+    "id": "Test",
+    "realm": "Test",
+    "enabled": true,
+    "tokenLifespan": 600,
+    "accessCodeLifespan": 600,
+    "accessCodeLifespanUserAction": 600,
+    "sslNotRequired": true,
+    "registrationAllowed": true,
+    "resetPasswordAllowed": true,
+    "requiredCredentials": [ "password" ],
+    "requiredApplicationCredentials": [ "password" ],
+    "requiredOAuthClientCredentials": [ "password" ],
+    "smtpServer": {
+        "from": "auto@keycloak.org",
+        "host": "localhost",
+        "port":"3025"
+    },
+    "users" : [
+        {
+            "username" : "REALM_COMPOSITE_1_USER",
+            "enabled": true,
+            "email" : "test-user@localhost",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ]
+        },
+        {
+            "username" : "REALM_ROLE_1_USER",
+            "enabled": true,
+            "email" : "test-user@localhost",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ]
+        },
+        {
+            "username" : "REALM_APP_COMPOSITE_USER",
+            "enabled": true,
+            "email" : "test-user@localhost",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ]
+        },
+        {
+            "username" : "REALM_APP_ROLE_USER",
+            "enabled": true,
+            "email" : "test-user@localhost",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ]
+        },
+        {
+            "username" : "APP_COMPOSITE_USER",
+            "enabled": true,
+            "email" : "test-user@localhost",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ]
+        }
+    ],
+    "oauthClients" : [
+        {
+            "name" : "third-party",
+            "enabled": true,
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ]
+        }
+    ],
+    "roleMappings": [
+        {
+            "username": "REALM_COMPOSITE_1_USER",
+            "roles": ["REALM_COMPOSITE_1"]
+        },
+        {
+            "username": "REALM_ROLE_1_USER",
+            "roles": ["REALM_ROLE_1"]
+        },
+        {
+            "username": "REALM_APP_COMPOSITE_USER",
+            "roles": ["REALM_APP_COMPOSITE_ROLE"]
+        },
+        {
+            "username": "APP_COMPOSITE_USER",
+            "roles": ["REALM_APP_COMPOSITE_ROLE", "REALM_COMPOSITE_1"]
+        }
+    ],
+    "scopeMappings": [
+        {
+            "username": "REALM_COMPOSITE_1_APPLICATION",
+            "roles": ["REALM_COMPOSITE_1"]
+        },
+        {
+            "username": "REALM_ROLE_1_APPLICATION",
+            "roles": ["REALM_ROLE_1"]
+        }
+    ],
+    "applications": [
+        {
+            "name": "REALM_COMPOSITE_1_APPLICATION",
+            "enabled": true,
+            "baseUrl": "http://localhost:8081/app",
+            "adminUrl": "http://localhost:8081/app/logout",
+            "credentials": [
+                {
+                    "type": "password",
+                    "value": "password"
+                }
+            ]
+         },
+        {
+            "name": "REALM_ROLE_1_APPLICATION",
+            "enabled": true,
+            "baseUrl": "http://localhost:8081/app",
+            "adminUrl": "http://localhost:8081/app/logout",
+            "credentials": [
+                {
+                    "type": "password",
+                    "value": "password"
+                }
+            ]
+        },
+        {
+            "name": "APP_ROLE_APPLICATION",
+            "enabled": true,
+            "baseUrl": "http://localhost:8081/app",
+            "adminUrl": "http://localhost:8081/app/logout",
+            "credentials": [
+                {
+                    "type": "password",
+                    "value": "password"
+                }
+            ]
+        },
+        {
+            "name": "APP_COMPOSITE_APPLICATION",
+            "enabled": true,
+            "baseUrl": "http://localhost:8081/app",
+            "adminUrl": "http://localhost:8081/app/logout",
+            "credentials": [
+                {
+                    "type": "password",
+                    "value": "password"
+                }
+            ]
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "REALM_ROLE_1"
+            },
+            {
+                "name": "REALM_ROLE_2"
+            },
+            {
+                "name": "REALM_ROLE_3"
+            },
+            {
+                "name": "REALM_COMPOSITE_1",
+                "composite": true,
+                "composites": {
+                    "realm": ["REALM_ROLE_1"]
+                }
+            },
+            {
+                "name": "REALM_APP_COMPOSITE_ROLE",
+                "composite": true,
+                "composites": {
+                    "application": {
+                        "APP_ROLE_APPLICATION" :[
+                            "APP_ROLE_1"
+                        ]
+                    }
+                }
+            }
+        ],
+        "application" : {
+            "APP_ROLE_APPLICATION" : [
+                {
+                    "name": "APP_ROLE_1"
+                },
+                {
+                    "name": "APP_ROLE_2"
+                }
+            ],
+            "APP_COMPOSITE_APPLICATION" : [
+                {
+                    "name": "APP_COMPOSITE_ROLE",
+                    "composite": true,
+                    "composites": {
+                        "realm" : [
+                            "REALM_ROLE_1",
+                            "REALM_ROLE_2",
+                            "REALM_ROLE_3"
+                        ],
+                        "application": {
+                            "APP_ROLE_APPLICATION" :[
+                                "APP_ROLE_1"
+                            ]
+                        }
+                    }
+                },
+                {
+                    "name": "APP_ROLE_2"
+                }
+            ]
+        }
+
+    },
+
+    "applicationRoleMappings": {
+        "APP_ROLE_APPLICATION": [
+            {
+                "username": "REALM_APP_ROLE_USER",
+                "roles": ["APP_ROLE_2"]
+            }
+        ]
+    },
+    "applicationScopeMappings": {
+        "APP_ROLE_APPLICATION": [
+            {
+                "username": "APP_COMPOSITE_APPLICATION",
+                "roles": ["APP_ROLE_2"]
+            }
+        ]
+    }
+}
\ No newline at end of file