keycloak-memoizeit

scope mapping, oauth client

10/9/2013 6:27:45 PM

Changes

core/src/main/java/org/keycloak/representations/idm/RealmRoleMappingsRepresentation.java 47(+0 -47)

Details

diff --git a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
index 6689e1d..ab12aae 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
@@ -18,7 +18,7 @@ public class ApplicationRepresentation {
     protected boolean enabled;
     protected List<CredentialRepresentation> credentials;
     protected List<RoleRepresentation> roles;
-    protected List<RoleMappingRepresentation> roleMappings;
+    protected List<UserRoleMappingRepresentation> roleMappings;
     protected List<ScopeMappingRepresentation> scopeMappings;
 
     public String getSelf() {
@@ -82,14 +82,14 @@ public class ApplicationRepresentation {
         return this;
     }
 
-    public List<RoleMappingRepresentation> getRoleMappings() {
+    public List<UserRoleMappingRepresentation> getRoleMappings() {
         return roleMappings;
     }
 
-    public RoleMappingRepresentation roleMapping(String username) {
-        RoleMappingRepresentation mapping = new RoleMappingRepresentation();
+    public UserRoleMappingRepresentation roleMapping(String username) {
+        UserRoleMappingRepresentation mapping = new UserRoleMappingRepresentation();
         mapping.setUsername(username);
-        if (roleMappings == null) roleMappings = new ArrayList<RoleMappingRepresentation>();
+        if (roleMappings == null) roleMappings = new ArrayList<UserRoleMappingRepresentation>();
         roleMappings.add(mapping);
         return mapping;
     }
diff --git a/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java
new file mode 100755
index 0000000..9f1b821
--- /dev/null
+++ b/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java
@@ -0,0 +1,60 @@
+package org.keycloak.representations.idm;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class OAuthClientRepresentation {
+    protected String id;
+    protected String name;
+    protected String baseUrl;
+    protected boolean enabled;
+    protected List<ScopeMappingRepresentation> scopeMappings;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public List<ScopeMappingRepresentation> getScopeMappings() {
+        return scopeMappings;
+    }
+
+    public ScopeMappingRepresentation scopeMapping(String username) {
+        ScopeMappingRepresentation mapping = new ScopeMappingRepresentation();
+        mapping.setUsername(username);
+        if (scopeMappings == null) scopeMappings = new ArrayList<ScopeMappingRepresentation>();
+        scopeMappings.add(mapping);
+        return mapping;
+    }
+
+    public String getBaseUrl() {
+        return baseUrl;
+    }
+
+    public void setBaseUrl(String baseUrl) {
+        this.baseUrl = baseUrl;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
index 36d8b33..14d7d50 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
@@ -31,7 +31,7 @@ public class RealmRepresentation {
     protected Set<String> requiredApplicationCredentials;
     protected Set<String> requiredOAuthClientCredentials;
     protected List<UserRepresentation> users;
-    protected List<RoleMappingRepresentation> roleMappings;
+    protected List<UserRoleMappingRepresentation> roleMappings;
     protected List<ScopeMappingRepresentation> scopeMappings;
     protected List<SocialMappingRepresentation> socialMappings;
     protected List<ApplicationRepresentation> applications;
@@ -125,14 +125,14 @@ public class RealmRepresentation {
         this.tokenLifespan = tokenLifespan;
     }
 
-    public List<RoleMappingRepresentation> getRoleMappings() {
+    public List<UserRoleMappingRepresentation> getRoleMappings() {
         return roleMappings;
     }
 
-    public RoleMappingRepresentation roleMapping(String username) {
-        RoleMappingRepresentation mapping = new RoleMappingRepresentation();
+    public UserRoleMappingRepresentation roleMapping(String username) {
+        UserRoleMappingRepresentation mapping = new UserRoleMappingRepresentation();
         mapping.setUsername(username);
-        if (roleMappings == null) roleMappings = new ArrayList<RoleMappingRepresentation>();
+        if (roleMappings == null) roleMappings = new ArrayList<UserRoleMappingRepresentation>();
         roleMappings.add(mapping);
         return mapping;
     }
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js
index cd96e48..675cc48 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js
@@ -181,6 +181,23 @@ module.config([ '$routeProvider', function($routeProvider) {
                 }
             },
             controller : 'ApplicationRoleListCtrl'
+        }).when('/realms/:realm/applications/:application/scope-mappings', {
+            templateUrl : 'partials/application-scope-mappings.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                application : function(ApplicationLoader) {
+                    return ApplicationLoader();
+                },
+                applications : function(ApplicationListLoader) {
+                    return ApplicationListLoader();
+                },
+                roles : function(RoleListLoader) {
+                    return RoleListLoader();
+                }
+            },
+            controller : 'ApplicationScopeMappingCtrl'
         })
 
 
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js
index 9bb6e9b..ced7268 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js
@@ -2,9 +2,6 @@
 
 var module = angular.module('keycloak.controllers', [ 'keycloak.services' ]);
 
-var realmslist = {};
-
-
 module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location, Notifications) {
 	$scope.addMessage = function() {
 		Notifications.success("test");
@@ -463,6 +460,74 @@ module.controller('RoleListCtrl', function($scope, $location, realm, roles) {
     });
 });
 
+module.controller('RoleDetailCtrl', function($scope, realm, role, Role, $location, Dialog, Notifications) {
+    $scope.realm = realm;
+    $scope.role = angular.copy(role);
+    $scope.create = !role.name;
+
+    $scope.changed = $scope.create;
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+
+    $scope.$watch('role', function() {
+        if (!angular.equals($scope.role, role)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        if ($scope.create) {
+            Role.save({
+                realm: realm.id
+            }, $scope.role, function (data, headers) {
+                $scope.changed = false;
+                role = angular.copy($scope.role);
+
+                var l = headers().location;
+                var id = l.substring(l.lastIndexOf("/") + 1);
+                $location.url("/realms/" + realm.id + "/roles/" + id);
+                Notifications.success("Created role");
+
+            });
+        } else {
+            Role.update({
+                realm : realm.id,
+                roleId : role.id
+            }, $scope.role, function() {
+                $scope.changed = false;
+                role = angular.copy($scope.role);
+                Notifications.success("Saved changes to role");
+            });
+        }
+    };
+
+    $scope.reset = function() {
+        $scope.role = angular.copy(role);
+        $scope.changed = false;
+        $scope.roleForm.showErrors = false;
+    };
+
+    $scope.cancel = function() {
+        $location.url("/realms/" + realm.id + "/roles");
+    };
+
+    $scope.remove = function() {
+        Dialog.confirmDelete($scope.role.name, 'role', function() {
+            $scope.role.$remove({
+                realm : realm.id,
+                role : $scope.role.name
+            }, function() {
+                $location.url("/realms/" + realm.id + "/roles");
+                Notifications.success("Deleted role");
+            });
+        });
+    };
+});
+
 module.controller('ApplicationRoleListCtrl', function($scope, $location, realm, application, roles) {
     $scope.realm = realm;
     $scope.roles = roles;
@@ -775,3 +840,121 @@ module.controller('RoleMappingCtrl', function($scope, realm, User, users, role, 
 		}
 	}
 });
+
+module.controller('ApplicationScopeMappingCtrl', function($scope, $http, realm, application, roles, applications, ApplicationRealmScopeMapping, ApplicationApplicationScopeMapping, ApplicationRole) {
+    $scope.realm = realm;
+    $scope.application = application;
+    $scope.realmRoles = angular.copy(roles);
+    $scope.selectedRealmRoles = [];
+    $scope.selectedRealmMappings = [];
+    $scope.realmMappings = [];
+    $scope.applications = applications;
+    $scope.applicationRoles = [];
+    $scope.selectedApplicationRoles = [];
+    $scope.selectedApplicationMappings = [];
+    $scope.applicationMappings = [];
+
+
+
+    $scope.realmMappings = ApplicationRealmScopeMapping.query({realm : realm.id, application : application.id}, function(){
+        for (var i = 0; i < $scope.realmMappings.length; i++) {
+            var role = $scope.realmMappings[i];
+            for (var j = 0; j < $scope.realmRoles.length; j++) {
+                var realmRole = $scope.realmRoles[j];
+                if (realmRole.id == role.id) {
+                    var idx = $scope.realmRoles.indexOf(realmRole);
+                    if (idx != -1) {
+                        $scope.realmRoles.splice(idx, 1);
+                        break;
+                    }
+                }
+            }
+        }
+    });
+
+    $scope.addRealmRole = function() {
+        $http.post('/auth-server/rest/saas/admin/realms/' + realm.id + '/applications/' + application.id + '/scope-mappings/realm',
+                $scope.selectedRealmRoles).success(function() {
+                for (var i = 0; i < $scope.selectedRealmRoles.length; i++) {
+                    var role = $scope.selectedRealmRoles[i];
+                    var idx = $scope.realmRoles.indexOf($scope.selectedRealmRoles[i]);
+                    if (idx != -1) {
+                        $scope.realmRoles.splice(idx, 1);
+                        $scope.realmMappings.push(role);
+                    }
+                }
+                $scope.selectRealmRoles = [];
+            });
+    };
+
+    $scope.deleteRealmRole = function() {
+        $http.delete('/auth-server/rest/saas/admin/realms/' + realm.id + '/applications/' + application.id +  '/scope-mappings/realm',
+            {data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(function() {
+                for (var i = 0; i < $scope.selectedRealmMappings.length; i++) {
+                    var role = $scope.selectedRealmMappings[i];
+                    var idx = $scope.realmMappings.indexOf($scope.selectedRealmMappings[i]);
+                    if (idx != -1) {
+                        $scope.realmMappings.splice(idx, 1);
+                        $scope.realmRoles.push(role);
+                    }
+                }
+                $scope.selectedRealmMappings = [];
+            });
+    };
+
+    $scope.addApplicationRole = function() {
+        $http.post('/auth-server/rest/saas/admin/realms/' + realm.id + '/applications/' + application.id +  '/scope-mappings/applications/' + $scope.targetApp.id,
+                $scope.selectedApplicationRoles).success(function() {
+                for (var i = 0; i < $scope.selectedApplicationRoles.length; i++) {
+                    var role = $scope.selectedApplicationRoles[i];
+                    var idx = $scope.applicationRoles.indexOf($scope.selectedApplicationRoles[i]);
+                    if (idx != -1) {
+                        $scope.applicationRoles.splice(idx, 1);
+                        $scope.applicationMappings.push(role);
+                    }
+                }
+                $scope.selectedApplicationRoles = [];
+            });
+    };
+
+    $scope.deleteApplicationRole = function() {
+        $http.delete('/auth-server/rest/saas/admin/realms/' + realm.id + '/applications/' + application.id +  '/scope-mappings/applications/' + $scope.targetApp.id,
+            {data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function() {
+                for (var i = 0; i < $scope.selectedApplicationMappings.length; i++) {
+                    var role = $scope.selectedApplicationMappings[i];
+                    var idx = $scope.applicationMappings.indexOf($scope.selectedApplicationMappings[i]);
+                    if (idx != -1) {
+                        $scope.applicationMappings.splice(idx, 1);
+                        $scope.applicationRoles.push(role);
+                    }
+                }
+                $scope.selectedApplicationMappings = [];
+            });
+    };
+
+
+    $scope.changeApplication = function() {
+        $scope.applicationRoles = ApplicationRole.query({realm : realm.id, application : $scope.targetApp.id}, function() {
+                $scope.applicationMappings = ApplicationApplicationScopeMapping.query({realm : realm.id, application : application.id, targetApp : $scope.targetApp.id}, function(){
+                    for (var i = 0; i < $scope.applicationMappings.length; i++) {
+                        var role = $scope.applicationMappings[i];
+                        for (var j = 0; j < $scope.applicationRoles.length; j++) {
+                            var realmRole = $scope.applicationRoles[j];
+                            if (realmRole.id == role.id) {
+                                var idx = $scope.applicationRoles.indexOf(realmRole);
+                                if (idx != -1) {
+                                    $scope.applicationRoles.splice(idx, 1);
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                });
+
+            }
+        );
+    };
+
+
+
+});
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js
index 4614635..b5d900f 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js
@@ -111,8 +111,6 @@ module.factory('RealmRoleMapping', function($resource) {
     });
 });
 
-
-
 module.factory('ApplicationRoleMapping', function($resource) {
     return $resource('/auth-server/rest/saas/admin/realms/:realm/users/:userId/role-mappings/applications/:application', {
         realm : '@realm',
@@ -121,6 +119,21 @@ module.factory('ApplicationRoleMapping', function($resource) {
     });
 });
 
+module.factory('ApplicationRealmScopeMapping', function($resource) {
+    return $resource('/auth-server/rest/saas/admin/realms/:realm/applications/:application/scope-mappings/realm', {
+        realm : '@realm',
+        application : '@application'
+    });
+});
+
+module.factory('ApplicationApplicationScopeMapping', function($resource) {
+    return $resource('/auth-server/rest/saas/admin/realms/:realm/applications/:application/scope-mappings/applications/:targetApp', {
+        realm : '@realm',
+        application : '@application',
+        targetApp : '@targetApp'
+    });
+});
+
 
 
 module.factory('RealmRoles', function($resource) {
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-credentials.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-credentials.html
index 6be1cb0..506cc43 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-credentials.html
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-credentials.html
@@ -10,7 +10,7 @@
                     <li class="active"><a href="#/realms/{{realm.id}}/applications/{{application.id}}/credentials">Credentials</a></li>
                     <li><a href="#">Installation</a></li>
                     <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/roles">Roles</a></li>
-                    <li><a href="#">Scope</a></li>
+                    <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/scope-mappings">Scope</a></li>
                     <li><a href="#">Sessions</a></li>
                 </ul>
             </div>
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-detail.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-detail.html
index a1035f3..bc23ca3 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-detail.html
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-detail.html
@@ -10,7 +10,7 @@
                     <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/credentials">Credentials</a></li>
                     <li><a href="#">Installation</a></li>
                     <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/roles">Roles</a></li>
-                    <li><a href="#">Scope</a></li>
+                    <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/scope-mappings">Scope</a></li>
                     <li><a href="#">Sessions</a></li>
                 </ul>
             </div>
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-scope-mappings.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-scope-mappings.html
new file mode 100755
index 0000000..f8638cf
--- /dev/null
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-scope-mappings.html
@@ -0,0 +1,73 @@
+<div id="wrapper" class="container">
+    <div class="row">
+        <div class="bs-sidebar col-md-3 clearfix" data-ng-include data-src="'partials/realm-menu.html'"></div>
+        <div id="content-area" class="col-md-9" role="main">
+            <div class="top-nav">
+                <ul class="rcue-tabs">
+                    <li><a href="#/create/application/{{realm.id}}">New Application</a></li>
+                    <li><a href="#/realms/{{realm.id}}/applications">Applications</a></li>
+                    <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}">Settings</a></li>
+                    <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/credentials">Credentials</a></li>
+                    <li><a href="#">Installation</a></li>
+                    <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/roles">Roles</a></li>
+                    <li class="active"><a href="#/realms/{{realm.id}}/applications/{{application.id}}/scope-mappings">Scope</a></li>
+                    <li><a href="#">Sessions</a></li>
+                </ul>
+            </div>
+            <div id="content">
+                <h2 class="pull-left">Application Scope Mappings for <span>{{application.name}}</span></h2>
+                <p class="subtitle"></p>
+                <form name="realmForm" novalidate>
+                    <fieldset>
+                        <legend uncollapsed><span class="text">Realm Scope</span> </legend>
+                        <div class="form-group">
+                            <div class="controls">
+                                <select multiple size="5"
+                                        ng-multiple="true"
+                                        ng-model="selectedRealmRoles"
+                                        ng-options="r.name for r in realmRoles">
+                                </select>
+                                <button type="submit" ng-click="addRealmRole()">---&gt;</button>
+                                <button type="submit" ng-click="deleteRealmRole()">&lt;---</button>
+                                <select multiple size=5
+                                        ng-multiple="true"
+                                        ng-model="selectedRealmMappings"
+                                        ng-options="r.name for r in realmMappings">
+                                </select>
+                            </div>
+                        </div>
+                    </fieldset>
+                    <fieldset ng-show="applications.length > 0">
+                        <legend collapsed><span class="text">Application Scope</span> </legend>
+                        <div class="form-group input-select">
+                            <label for="applications">Application: </label>
+                            <div class="input-group">
+                                <div class="select-rcue">
+                                    <select id="applications" name="applications" ng-change="changeApplication()" ng-model="targetApp" ng-options="a.name for a in applications">
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="form-group" ng-show="application">
+                            <div class="controls">
+                                <select multiple size="5"
+                                        ng-multiple="true"
+                                        ng-model="selectedApplicationRoles"
+                                        ng-options="r.name for r in applicationRoles">
+                                </select>
+                                <button type="submit" ng-click="addApplicationRole()">---&gt;</button>
+                                <button type="submit" ng-click="deleteApplicationRole()">&lt;---</button>
+                                <select multiple size=5
+                                        ng-multiple="true"
+                                        ng-model="selectedApplicationMappings"
+                                        ng-options="r.name for r in applicationMappings">
+                                </select>
+                            </div>
+                        </div>
+                    </fieldset>
+                </form>
+            </div>
+        </div>
+        <div id="container-right-bg"></div>
+    </div>
+</div>
\ No newline at end of file
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 9dd08d3..05dedaf 100755
--- a/model/api/src/main/java/org/keycloak/models/ApplicationModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ApplicationModel.java
@@ -7,7 +7,7 @@ import java.util.Set;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public interface ApplicationModel {
+public interface ApplicationModel extends RoleContainerModel, RoleMapperModel, ScopeMapperModel {
     void updateApplication();
 
     UserModel getApplicationUser();
@@ -34,25 +34,4 @@ public interface ApplicationModel {
 
     void setBaseUrl(String url);
 
-    RoleModel getRole(String name);
-
-    RoleModel addRole(String name);
-
-    List<RoleModel> getRoles();
-
-    Set<String> getRoleMappingValues(UserModel user);
-
-    void addScopeMapping(UserModel agent, String roleName);
-
-    void addScopeMapping(UserModel agent, RoleModel role);
-
-    Set<String> getScopeMapping(UserModel agent);
-
-    List<RoleModel> getRoleMappings(UserModel user);
-
-    void deleteRoleMapping(UserModel user, RoleModel role);
-
-    RoleModel getRoleById(String id);
-
-    void grantRole(UserModel user, 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 d6d0a1a..d308660 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -10,7 +10,7 @@ import java.util.Set;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public interface RealmModel {
+public interface RealmModel extends RoleContainerModel, RoleMapperModel, ScopeMapperModel {
     String DEFAULT_REALM = "default";
 
     String getId();
@@ -85,12 +85,6 @@ public interface RealmModel {
 
     UserModel addUser(String username);
 
-    RoleModel getRole(String name);
-
-    RoleModel addRole(String name);
-
-    List<RoleModel> getRoles();
-    
     List<RoleModel> getDefaultRoles();
     
     void addDefaultRole(String name);
@@ -103,30 +97,16 @@ public interface RealmModel {
 
     ApplicationModel addApplication(String name);
 
-    boolean hasRole(UserModel user, RoleModel role);
-
-    void grantRole(UserModel user, RoleModel role);
-
-    Set<String> getRoleMappingValues(UserModel user);
-
-    void addScopeMapping(UserModel agent, String roleName);
-
-    Set<String> getScopeMapping(UserModel agent);
-
     boolean isRealmAdmin(UserModel agent);
 
     void addRealmAdmin(UserModel agent);
 
-    RoleModel getRoleById(String id);
-
 
     List<RequiredCredentialModel> getRequiredApplicationCredentials();
 
 
     List<RequiredCredentialModel> getRequiredOAuthClientCredentials();
 
-    boolean hasRole(UserModel user, String role);
-
     ApplicationModel getApplicationById(String id);
 
     void addRequiredOAuthClientCredential(String type);
@@ -157,11 +137,9 @@ public interface RealmModel {
 
     List<UserModel> searchForUserByAttributes(Map<String, String> attributes);
 
-    List<RoleModel> getRoleMappings(UserModel user);
-
-    void deleteRoleMapping(UserModel user, RoleModel role);
-
     OAuthClientModel addOAuthClient(String name);
 
     OAuthClientModel getOAuthClient(String name);
+
+    List<OAuthClientModel> getOAuthClients();
 }
diff --git a/model/api/src/main/java/org/keycloak/models/RoleContainerModel.java b/model/api/src/main/java/org/keycloak/models/RoleContainerModel.java
new file mode 100755
index 0000000..4442359
--- /dev/null
+++ b/model/api/src/main/java/org/keycloak/models/RoleContainerModel.java
@@ -0,0 +1,17 @@
+package org.keycloak.models;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface RoleContainerModel {
+    RoleModel getRole(String name);
+
+    RoleModel addRole(String name);
+
+    List<RoleModel> getRoles();
+
+    RoleModel getRoleById(String id);
+}
diff --git a/model/api/src/main/java/org/keycloak/models/RoleMapperModel.java b/model/api/src/main/java/org/keycloak/models/RoleMapperModel.java
new file mode 100755
index 0000000..a9a9938
--- /dev/null
+++ b/model/api/src/main/java/org/keycloak/models/RoleMapperModel.java
@@ -0,0 +1,22 @@
+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 RoleMapperModel {
+    boolean hasRole(UserModel user, RoleModel role);
+
+    void grantRole(UserModel user, RoleModel role);
+
+    Set<String> getRoleMappingValues(UserModel user);
+
+    List<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/ScopeMapperModel.java b/model/api/src/main/java/org/keycloak/models/ScopeMapperModel.java
new file mode 100755
index 0000000..a94ac8d
--- /dev/null
+++ b/model/api/src/main/java/org/keycloak/models/ScopeMapperModel.java
@@ -0,0 +1,20 @@
+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 ScopeMapperModel {
+    void addScopeMapping(UserModel agent, String roleName);
+
+    Set<String> getScopeMappingValues(UserModel agent);
+
+    List<RoleModel> getScopeMappings(UserModel agent);
+
+    void addScopeMapping(UserModel agent, RoleModel role);
+
+    void deleteScopeMapping(UserModel user, RoleModel role);
+}
diff --git a/model/picketlink/src/main/java/org/keycloak/models/picketlink/ApplicationAdapter.java b/model/picketlink/src/main/java/org/keycloak/models/picketlink/ApplicationAdapter.java
index f5a413c..184feb3 100755
--- a/model/picketlink/src/main/java/org/keycloak/models/picketlink/ApplicationAdapter.java
+++ b/model/picketlink/src/main/java/org/keycloak/models/picketlink/ApplicationAdapter.java
@@ -134,7 +134,16 @@ public class ApplicationAdapter implements ApplicationModel {
         SampleModel.grantRole(getRelationshipManager(), ((UserAdapter) user).getUser(), ((RoleAdapter) role).getRole());
     }
 
+    @Override
+    public boolean hasRole(UserModel user, RoleModel role) {
+        return SampleModel.hasRole(getRelationshipManager(), ((UserAdapter) user).getUser(), ((RoleAdapter) role).getRole());
+    }
 
+    @Override
+    public boolean hasRole(UserModel user, String role) {
+        RoleModel roleModel = getRole(role);
+        return hasRole(user, roleModel);
+    }
 
     @Override
     public RoleAdapter addRole(String name) {
@@ -190,9 +199,6 @@ public class ApplicationAdapter implements ApplicationModel {
         }
     }
 
-
-
-
     @Override
     public void addScopeMapping(UserModel agent, String roleName) {
         IdentityManager idm = getIdm();
@@ -211,7 +217,19 @@ public class ApplicationAdapter implements ApplicationModel {
     }
 
     @Override
-    public Set<String> getScopeMapping(UserModel agent) {
+    public void deleteScopeMapping(UserModel user, RoleModel role) {
+        RelationshipQuery<ScopeRelationship> query = getRelationshipManager().createRelationshipQuery(ScopeRelationship.class);
+        query.setParameter(ScopeRelationship.CLIENT, ((UserAdapter)user).getUser());
+        query.setParameter(ScopeRelationship.SCOPE, ((RoleAdapter)role).getRole());
+        List<ScopeRelationship> grants = query.getResultList();
+        for (ScopeRelationship grant : grants) {
+            getRelationshipManager().remove(grant);
+        }
+    }
+
+
+    @Override
+    public Set<String> getScopeMappingValues(UserModel agent) {
         RelationshipQuery<ScopeRelationship> query = getRelationshipManager().createRelationshipQuery(ScopeRelationship.class);
         query.setParameter(ScopeRelationship.CLIENT, ((UserAdapter)agent).getUser());
         List<ScopeRelationship> scope = query.getResultList();
@@ -221,4 +239,17 @@ public class ApplicationAdapter implements ApplicationModel {
         }
         return set;
     }
+
+    @Override
+    public List<RoleModel> getScopeMappings(UserModel agent) {
+        RelationshipQuery<ScopeRelationship> query = getRelationshipManager().createRelationshipQuery(ScopeRelationship.class);
+        query.setParameter(ScopeRelationship.CLIENT, ((UserAdapter)agent).getUser());
+        List<ScopeRelationship> scope = query.getResultList();
+        List<RoleModel> roles = new ArrayList<RoleModel>();
+        for (ScopeRelationship rel : scope) {
+            if (rel.getScope().getPartition().getId().equals(applicationData.getId())) roles.add(new RoleAdapter(rel.getScope(), getIdm()));
+        }
+        return roles;
+    }
+
 }
diff --git a/model/picketlink/src/main/java/org/keycloak/models/picketlink/RealmAdapter.java b/model/picketlink/src/main/java/org/keycloak/models/picketlink/RealmAdapter.java
index 5746908..6c62007 100755
--- a/model/picketlink/src/main/java/org/keycloak/models/picketlink/RealmAdapter.java
+++ b/model/picketlink/src/main/java/org/keycloak/models/picketlink/RealmAdapter.java
@@ -665,7 +665,6 @@ public class RealmAdapter implements RealmModel {
         return set;
     }
 
-
     @Override
     public void addScopeMapping(UserModel agent, String roleName) {
         IdentityManager idm = getIdm();
@@ -678,6 +677,25 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
+    public void addScopeMapping(UserModel agent, RoleModel role) {
+        ScopeRelationship scope = new ScopeRelationship();
+        scope.setClient(((UserAdapter)agent).getUser());
+        scope.setScope(((RoleAdapter)role).getRole());
+        getRelationshipManager().add(scope);
+    }
+
+    @Override
+    public void deleteScopeMapping(UserModel user, RoleModel role) {
+        RelationshipQuery<ScopeRelationship> query = getRelationshipManager().createRelationshipQuery(ScopeRelationship.class);
+        query.setParameter(ScopeRelationship.CLIENT, ((UserAdapter)user).getUser());
+        query.setParameter(ScopeRelationship.SCOPE, ((RoleAdapter)role).getRole());
+        List<ScopeRelationship> grants = query.getResultList();
+        for (ScopeRelationship grant : grants) {
+            getRelationshipManager().remove(grant);
+        }
+    }
+
+    @Override
     public OAuthClientModel addOAuthClient(String name) {
         User client = new User(name);
         getIdm().add(client);
@@ -699,9 +717,32 @@ public class RealmAdapter implements RealmModel {
         return new OAuthClientAdapter(results.get(0), getIdm(), getRelationshipManager());
     }
 
+    @Override
+    public List<OAuthClientModel> getOAuthClients() {
+        RelationshipQuery<OAuthClientRelationship> query = getRelationshipManager().createRelationshipQuery(OAuthClientRelationship.class);
+        query.setParameter(OAuthClientRelationship.REALM, realm.getName());
+        List<OAuthClientRelationship> results = query.getResultList();
+        List<OAuthClientModel> list = new ArrayList<OAuthClientModel>();
+        for (OAuthClientRelationship rel : results) {
+            list.add(new OAuthClientAdapter(rel, getIdm(), getRelationshipManager()));
+        }
+        return list;
+    }
+
+    @Override
+    public List<RoleModel> getScopeMappings(UserModel agent) {
+        RelationshipQuery<ScopeRelationship> query = getRelationshipManager().createRelationshipQuery(ScopeRelationship.class);
+        query.setParameter(ScopeRelationship.CLIENT, ((UserAdapter)agent).getUser());
+        List<ScopeRelationship> scope = query.getResultList();
+        List<RoleModel> roles = new ArrayList<RoleModel>();
+        for (ScopeRelationship rel : scope) {
+            if (rel.getScope().getPartition().getId().equals(realm.getId())) roles.add(new RoleAdapter(rel.getScope(), getIdm()));
+        }
+        return roles;
+    }
 
     @Override
-    public Set<String> getScopeMapping(UserModel agent) {
+    public Set<String> getScopeMappingValues(UserModel agent) {
         RelationshipQuery<ScopeRelationship> query = getRelationshipManager().createRelationshipQuery(ScopeRelationship.class);
         query.setParameter(ScopeRelationship.CLIENT, ((UserAdapter)agent).getUser());
         List<ScopeRelationship> scope = query.getResultList();
diff --git a/model/picketlink/src/main/java/org/keycloak/models/picketlink/relationships/ScopeRelationship.java b/model/picketlink/src/main/java/org/keycloak/models/picketlink/relationships/ScopeRelationship.java
index 96ed96e..65a1c7a 100755
--- a/model/picketlink/src/main/java/org/keycloak/models/picketlink/relationships/ScopeRelationship.java
+++ b/model/picketlink/src/main/java/org/keycloak/models/picketlink/relationships/ScopeRelationship.java
@@ -21,6 +21,15 @@ public class ScopeRelationship extends AbstractAttributedType implements Relatio
         }
     };
 
+    public static final RelationshipQueryParameter SCOPE = new RelationshipQueryParameter() {
+
+        @Override
+        public String getName() {
+            return "scope";
+        }
+    };
+
+
     protected User client;
     protected Role scope;
 
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 f7dd7c3..46d3b6c 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
@@ -42,7 +42,7 @@ public class ApplicationManager {
             }
         }
         if (resourceRep.getRoleMappings() != null) {
-            for (RoleMappingRepresentation mapping : resourceRep.getRoleMappings()) {
+            for (UserRoleMappingRepresentation mapping : resourceRep.getRoleMappings()) {
                 UserModel user = realm.getUser(mapping.getUsername());
                 for (String roleString : mapping.getRoles()) {
                     RoleModel role = applicationModel.getRole(roleString.trim());
diff --git a/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java b/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java
index 0efd2a9..22ef50e 100755
--- a/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java
@@ -3,6 +3,7 @@ package org.keycloak.services.managers;
 import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
+import org.keycloak.representations.idm.OAuthClientRepresentation;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -15,10 +16,30 @@ public class OAuthClientManager {
         this.realm = realm;
     }
 
-    public OAuthClientModel createOAuthClient(String name) {
+    public OAuthClientModel create(String name) {
         OAuthClientModel model = realm.addOAuthClient(name);
         RoleModel role = realm.getRole(RealmManager.IDENTITY_REQUESTER_ROLE);
         realm.grantRole(model.getOAuthAgent(), role);
         return model;
     }
+
+    public OAuthClientModel create(OAuthClientRepresentation rep) {
+        OAuthClientModel model = create(rep.getName());
+        model.setBaseUrl(rep.getBaseUrl());
+        model.getOAuthAgent().setEnabled(rep.isEnabled());
+        return model;
+    }
+
+    public void update(OAuthClientRepresentation rep, OAuthClientModel model) {
+        model.setBaseUrl(rep.getBaseUrl());
+    }
+
+    public static OAuthClientRepresentation toRepresentation(OAuthClientModel model) {
+        OAuthClientRepresentation rep = new OAuthClientRepresentation();
+        rep.setId(model.getId());
+        rep.setBaseUrl(model.getBaseUrl());
+        rep.setName(model.getOAuthAgent().getLoginName());
+        rep.setEnabled(model.getOAuthAgent().isEnabled());
+        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 cb66e43..c683290 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -183,7 +183,7 @@ public class RealmManager {
         }
 
         if (rep.getRoleMappings() != null) {
-            for (RoleMappingRepresentation mapping : rep.getRoleMappings()) {
+            for (UserRoleMappingRepresentation mapping : rep.getRoleMappings()) {
                 UserModel user = userMap.get(mapping.getUsername());
                 for (String roleString : mapping.getRoles()) {
                     RoleModel role = newRealm.getRole(roleString.trim());
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 2d04d8a..19da5e3 100755
--- a/services/src/main/java/org/keycloak/services/managers/TokenManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/TokenManager.java
@@ -50,7 +50,7 @@ public class TokenManager {
         Set<String> realmMapping = realm.getRoleMappingValues(user);
 
         if (realmMapping != null && realmMapping.size() > 0 && (scopeMap == null || scopeMap.containsKey("realm"))) {
-            Set<String> scope = realm.getScopeMapping(client);
+            Set<String> scope = realm.getScopeMappingValues(client);
             if (scope.size() > 0) {
                 Set<String> scopeRequest = null;
                 if (scopeMap != null) {
@@ -69,7 +69,7 @@ public class TokenManager {
         for (ApplicationModel resource : realm.getApplications()) {
             Set<String> mapping = resource.getRoleMappingValues(user);
             if (mapping != null && mapping.size() > 0 && (scopeMap == null || scopeMap.containsKey(resource.getName()))) {
-                Set<String> scope = resource.getScopeMapping(client);
+                Set<String> scope = resource.getScopeMappingValues(client);
                 if (scope.size() > 0) {
                     Set<String> scopeRequest = null;
                     if (scopeMap != null) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java
index 2117cb2..242d479 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java
@@ -3,9 +3,7 @@ package org.keycloak.services.resources.admin;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.logging.Logger;
 import org.keycloak.models.*;
-import org.keycloak.representations.idm.ApplicationRepresentation;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.*;
 import org.keycloak.services.managers.ApplicationManager;
 import org.keycloak.services.managers.RealmManager;
 
@@ -15,25 +13,25 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class ApplicationResource {
+public class ApplicationResource extends RoleContainerResource {
     protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
-    protected UserModel admin;
     protected RealmModel realm;
     protected ApplicationModel application;
-
-    @Context
     protected KeycloakSession session;
 
-    public ApplicationResource(UserModel admin, RealmModel realm, ApplicationModel applicationModel) {
-        this.admin = admin;
+    public ApplicationResource(RealmModel realm, ApplicationModel applicationModel, KeycloakSession session) {
+        super(applicationModel);
         this.realm = realm;
         this.application = applicationModel;
+        this.session = session;
     }
 
     @PUT
@@ -52,59 +50,6 @@ public class ApplicationResource {
         return applicationManager.toRepresentation(application);
     }
 
-    @Path("roles")
-    @GET
-    @NoCache
-    @Produces("application/json")
-    public List<RoleRepresentation> getRoles() {
-        List<RoleModel> roleModels = application.getRoles();
-        List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
-        for (RoleModel roleModel : roleModels) {
-            roles.add(RealmManager.toRepresentation(roleModel));
-        }
-        return roles;
-    }
-
-    @Path("roles/{id}")
-    @GET
-    @NoCache
-    @Produces("application/json")
-    public RoleRepresentation getRole(final @PathParam("id") String id) {
-        RoleModel roleModel = application.getRoleById(id);
-        if (roleModel == null) {
-            throw new NotFoundException();
-        }
-        return RealmManager.toRepresentation(roleModel);
-    }
-
-
-    @Path("roles/{id}")
-    @PUT
-    @Consumes("application/json")
-    public void updateRole(final @PathParam("id") String id, final RoleRepresentation rep) {
-        RoleModel role = application.getRoleById(id);
-        if (role == null) {
-            throw new NotFoundException();
-        }
-        role.setName(rep.getName());
-        role.setDescription(rep.getDescription());
-    }
-
-    @Path("roles")
-    @POST
-    @Consumes("application/json")
-    public Response createRole(final @Context UriInfo uriInfo, final RoleRepresentation rep) {
-        if (application.getRole(rep.getName()) != null) { // no duplicates
-            throw new InternalServerErrorException(); // todo appropriate status here.
-        }
-        RoleModel role = application.addRole(rep.getName());
-        if (role == null) {
-            throw new NotFoundException();
-        }
-        role.setDescription(rep.getDescription());
-        return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getId()).build()).build();
-    }
-
     @Path("credentials")
     @PUT
     @Consumes("application/json")
@@ -116,7 +61,12 @@ public class ApplicationResource {
             UserCredentialModel cred = RealmManager.fromRepresentation(rep);
             realm.updateCredential(application.getApplicationUser(), cred);
         }
+    }
 
+    @Path("scope-mappings")
+    public ScopeMappedResource getScopeMappedResource() {
+        return new ScopeMappedResource(realm, application.getApplicationUser(), session);
     }
 
+
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java
index 1f5138e..40e3ca7 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java
@@ -25,7 +25,6 @@ import java.util.List;
  */
 public class ApplicationsResource {
     protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
-    protected UserModel admin;
     protected RealmModel realm;
 
     @Context
@@ -34,15 +33,14 @@ public class ApplicationsResource {
     @Context
     protected KeycloakSession session;
 
-    public ApplicationsResource(UserModel admin, RealmModel realm) {
-        this.admin = admin;
+    public ApplicationsResource(RealmModel realm) {
         this.realm = realm;
     }
 
     @GET
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
-    public List<ApplicationRepresentation> getResources() {
+    public List<ApplicationRepresentation> getApplications() {
         List<ApplicationRepresentation> rep = new ArrayList<ApplicationRepresentation>();
         List<ApplicationModel> applicationModels = realm.getApplications();
         ApplicationManager resourceManager = new ApplicationManager(new RealmManager(session));
@@ -54,19 +52,19 @@ public class ApplicationsResource {
 
     @POST
     @Consumes(MediaType.APPLICATION_JSON)
-    public Response createResource(final @Context UriInfo uriInfo, final ApplicationRepresentation rep) {
+    public Response createApplication(final @Context UriInfo uriInfo, final ApplicationRepresentation rep) {
         ApplicationManager resourceManager = new ApplicationManager(new RealmManager(session));
         ApplicationModel applicationModel = resourceManager.createApplication(realm, rep);
         return Response.created(uriInfo.getAbsolutePathBuilder().path(applicationModel.getId()).build()).build();
     }
 
     @Path("{id}")
-    public ApplicationResource getResource(final @PathParam("id") String id) {
+    public ApplicationResource getApplication(final @PathParam("id") String id) {
         ApplicationModel applicationModel = realm.getApplicationById(id);
         if (applicationModel == null) {
             throw new NotFoundException();
         }
-        ApplicationResource applicationResource = new ApplicationResource(admin, realm, applicationModel);
+        ApplicationResource applicationResource = new ApplicationResource(realm, applicationModel, session);
         resourceContext.initResource(applicationResource);
         return applicationResource;
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java
new file mode 100755
index 0000000..fc04fbc
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java
@@ -0,0 +1,68 @@
+package org.keycloak.services.resources.admin;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.jboss.resteasy.logging.Logger;
+import org.keycloak.models.*;
+import org.keycloak.representations.idm.ApplicationRepresentation;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.representations.idm.OAuthClientRepresentation;
+import org.keycloak.services.managers.ApplicationManager;
+import org.keycloak.services.managers.OAuthClientManager;
+import org.keycloak.services.managers.RealmManager;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class OAuthClientResource  {
+    protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
+    protected RealmModel realm;
+    protected OAuthClientModel oauthClient;
+    protected KeycloakSession session;
+
+    public OAuthClientResource(RealmModel realm, OAuthClientModel oauthClient, KeycloakSession session) {
+        this.realm = realm;
+        this.oauthClient = oauthClient;
+        this.session = session;
+    }
+
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void update(final OAuthClientRepresentation rep) {
+        OAuthClientManager manager = new OAuthClientManager(realm);
+        manager.update(rep, oauthClient);
+    }
+
+
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public OAuthClientRepresentation getApplication() {
+        OAuthClientManager manager = new OAuthClientManager(realm);
+        return OAuthClientManager.toRepresentation(oauthClient);
+    }
+
+    @Path("credentials")
+    @PUT
+    @Consumes("application/json")
+    public void updateCredentials(List<CredentialRepresentation> credentials) {
+        logger.info("updateCredentials");
+        if (credentials == null) return;
+
+        for (CredentialRepresentation rep : credentials) {
+            UserCredentialModel cred = RealmManager.fromRepresentation(rep);
+            realm.updateCredential(oauthClient.getOAuthAgent(), cred);
+        }
+    }
+
+    @Path("scope-mappings")
+    public ScopeMappedResource getScopeMappedResource() {
+        return new ScopeMappedResource(realm, oauthClient.getOAuthAgent(), session);
+    }
+
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java
new file mode 100755
index 0000000..2873767
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java
@@ -0,0 +1,69 @@
+package org.keycloak.services.resources.admin;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.jboss.resteasy.logging.Logger;
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.OAuthClientModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.representations.idm.ApplicationRepresentation;
+import org.keycloak.representations.idm.OAuthClientRepresentation;
+import org.keycloak.services.managers.ApplicationManager;
+import org.keycloak.services.managers.OAuthClientManager;
+import org.keycloak.services.managers.RealmManager;
+
+import javax.ws.rs.*;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class OAuthClientsResource {
+    protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
+    protected RealmModel realm;
+
+    protected KeycloakSession session;
+
+    public OAuthClientsResource(RealmModel realm, KeycloakSession session) {
+        this.realm = realm;
+        this.session = session;
+    }
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public List<OAuthClientRepresentation> getOAuthClients() {
+        List<OAuthClientRepresentation> rep = new ArrayList<OAuthClientRepresentation>();
+        List<OAuthClientModel> oauthModels = realm.getOAuthClients();
+        for (OAuthClientModel oauth : oauthModels) {
+            rep.add(OAuthClientManager.toRepresentation(oauth));
+        }
+        return rep;
+    }
+
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response createOAuthClient(final @Context UriInfo uriInfo, final OAuthClientRepresentation rep) {
+        OAuthClientManager resourceManager = new OAuthClientManager(realm);
+        OAuthClientModel oauth = resourceManager.create(rep);
+        return Response.created(uriInfo.getAbsolutePathBuilder().path(oauth.getOAuthAgent().getLoginName()).build()).build();
+    }
+
+    @Path("{id}")
+    public OAuthClientResource getOAuthClient(final @PathParam("id") String id) {
+        OAuthClientModel oauth = realm.getOAuthClient(id);
+        if (oauth == null) {
+            throw new NotFoundException();
+        }
+        OAuthClientResource oAuthClientResource = new OAuthClientResource(realm, oauth, session);
+        return oAuthClientResource;
+    }
+
+}
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 97249dd..e092b91 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
@@ -2,13 +2,10 @@ package org.keycloak.services.resources.admin;
 
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.logging.Logger;
+import org.keycloak.models.*;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.RoleRepresentation;
 import org.keycloak.services.managers.RealmManager;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
 
 import javax.ws.rs.*;
 import javax.ws.rs.container.ResourceContext;
@@ -22,7 +19,7 @@ import java.util.List;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class RealmAdminResource {
+public class RealmAdminResource extends RoleContainerResource {
     protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
     protected UserModel admin;
     protected RealmModel realm;
@@ -34,22 +31,29 @@ public class RealmAdminResource {
     protected KeycloakSession session;
 
     public RealmAdminResource(UserModel admin, RealmModel realm) {
+        super(realm);
         this.admin = admin;
         this.realm = realm;
     }
 
     @Path("applications")
-    public ApplicationsResource getResources() {
-        ApplicationsResource applicationsResource = new ApplicationsResource(admin, realm);
+    public ApplicationsResource getApplications() {
+        ApplicationsResource applicationsResource = new ApplicationsResource(realm);
         resourceContext.initResource(applicationsResource);
         return applicationsResource;
     }
 
+    @Path("oauth-clients")
+    public OAuthClientsResource getOAuthClients() {
+        OAuthClientsResource oauth = new OAuthClientsResource(realm, session);
+        return oauth;
+    }
+
     @GET
     @NoCache
     @Produces("application/json")
     public RealmRepresentation getRealm() {
-        return new RealmManager(session).toRepresentation(realm);
+        return RealmManager.toRepresentation(realm);
     }
 
 
@@ -60,62 +64,6 @@ public class RealmAdminResource {
         new RealmManager(session).updateRealm(rep, realm);
     }
 
-    @Path("roles")
-    @GET
-    @NoCache
-    @Produces("application/json")
-    public List<RoleRepresentation> getRoles() {
-        List<RoleModel> roleModels = realm.getRoles();
-        List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
-        for (RoleModel roleModel : roleModels) {
-            RoleRepresentation role = new RoleRepresentation(roleModel.getName(), roleModel.getDescription());
-            role.setId(roleModel.getId());
-            roles.add(role);
-        }
-        return roles;
-    }
-
-    @Path("roles/{id}")
-    @GET
-    @NoCache
-    @Produces("application/json")
-    public RoleRepresentation getRole(final @PathParam("id") String id) {
-        RoleModel roleModel = realm.getRoleById(id);
-        if (roleModel == null) {
-            throw new NotFoundException();
-        }
-        RoleRepresentation rep = new RoleRepresentation(roleModel.getName(), roleModel.getDescription());
-        rep.setId(roleModel.getId());
-        return rep;
-    }
-
-
-    @Path("roles/{id}")
-    @PUT
-    @Consumes("application/json")
-    public void updateRole(final @PathParam("id") String id, final RoleRepresentation rep) {
-        RoleModel role = realm.getRoleById(id);
-        if (role == null) {
-            throw new NotFoundException();
-        }
-        role.setName(rep.getName());
-        role.setDescription(rep.getDescription());
-    }
-
-    @Path("roles")
-    @POST
-    @Consumes("application/json")
-    public Response createRole(final @Context UriInfo uriInfo, final RoleRepresentation rep) {
-        if (realm.getRole(rep.getName()) != null) {
-            throw new InternalServerErrorException(); // todo appropriate status here.
-        }
-        RoleModel role = realm.addRole(rep.getName());
-        if (role == null) {
-            throw new NotFoundException();
-        }
-        role.setDescription(rep.getDescription());
-        return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getId()).build()).build();
-    }
 
     @Path("users")
     public UsersResource users() {
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
new file mode 100755
index 0000000..0c02a78
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
@@ -0,0 +1,81 @@
+package org.keycloak.services.resources.admin;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.keycloak.models.RoleContainerModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.representations.idm.RoleRepresentation;
+
+import javax.ws.rs.*;
+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.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RoleContainerResource {
+    protected RoleContainerModel roleContainer;
+
+    public RoleContainerResource(RoleContainerModel roleContainer) {
+        this.roleContainer = roleContainer;
+    }
+
+    @Path("roles")
+    @GET
+    @NoCache
+    @Produces("application/json")
+    public List<RoleRepresentation> getRoles() {
+        List<RoleModel> roleModels = roleContainer.getRoles();
+        List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
+        for (RoleModel roleModel : roleModels) {
+            RoleRepresentation role = new RoleRepresentation(roleModel.getName(), roleModel.getDescription());
+            role.setId(roleModel.getId());
+            roles.add(role);
+        }
+        return roles;
+    }
+
+    @Path("roles/{id}")
+    @GET
+    @NoCache
+    @Produces("application/json")
+    public RoleRepresentation getRole(final @PathParam("id") String id) {
+        RoleModel roleModel = roleContainer.getRoleById(id);
+        if (roleModel == null) {
+            throw new NotFoundException();
+        }
+        RoleRepresentation rep = new RoleRepresentation(roleModel.getName(), roleModel.getDescription());
+        rep.setId(roleModel.getId());
+        return rep;
+    }
+
+    @Path("roles/{id}")
+    @PUT
+    @Consumes("application/json")
+    public void updateRole(final @PathParam("id") String id, final RoleRepresentation rep) {
+        RoleModel role = roleContainer.getRoleById(id);
+        if (role == null) {
+            throw new NotFoundException();
+        }
+        role.setName(rep.getName());
+        role.setDescription(rep.getDescription());
+    }
+
+    @Path("roles")
+    @POST
+    @Consumes("application/json")
+    public Response createRole(final @Context UriInfo uriInfo, final RoleRepresentation rep) {
+        if (roleContainer.getRole(rep.getName()) != null) {
+            throw new InternalServerErrorException(); // todo appropriate status here.
+        }
+        RoleModel role = roleContainer.addRole(rep.getName());
+        if (role == null) {
+            throw new NotFoundException();
+        }
+        role.setDescription(rep.getDescription());
+        return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getId()).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
new file mode 100755
index 0000000..d093e16
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java
@@ -0,0 +1,182 @@
+package org.keycloak.services.resources.admin;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.keycloak.models.*;
+import org.keycloak.representations.idm.ApplicationMappingsRepresentation;
+import org.keycloak.representations.idm.MappingsRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.services.managers.RealmManager;
+
+import javax.ws.rs.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ScopeMappedResource {
+    protected RealmModel realm;
+    protected UserModel agent;
+    protected KeycloakSession session;
+
+    public ScopeMappedResource(RealmModel realm, UserModel account, KeycloakSession session) {
+        this.realm = realm;
+        this.agent = account;
+        this.session = session;
+    }
+
+    @GET
+    @Produces("application/json")
+    @NoCache
+    public MappingsRepresentation getScopeMappings() {
+        MappingsRepresentation all = new MappingsRepresentation();
+        List<RoleModel> realmMappings = realm.getScopeMappings(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));
+            }
+            all.setRealmMappings(realmRep);
+        }
+
+        List<ApplicationModel> applications = realm.getApplications();
+        if (applications.size() > 0) {
+            Map<String, ApplicationMappingsRepresentation> appMappings = new HashMap<String, ApplicationMappingsRepresentation>();
+            for (ApplicationModel app : applications) {
+                List<RoleModel> roleMappings = app.getScopeMappings(agent);
+                if (roleMappings.size() > 0) {
+                    ApplicationMappingsRepresentation mappings = new ApplicationMappingsRepresentation();
+                    mappings.setApplicationId(app.getId());
+                    mappings.setApplication(app.getName());
+                    List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
+                    mappings.setMappings(roles);
+                    for (RoleModel role : roleMappings) {
+                        roles.add(manager.toRepresentation(role));
+                    }
+                    appMappings.put(app.getName(), mappings);
+                    all.setApplicationMappings(appMappings);
+                }
+            }
+        }
+        return all;
+    }
+
+    @Path("realm")
+    @GET
+    @Produces("application/json")
+    @NoCache
+    public List<RoleRepresentation> getRealmScopeMappings() {
+        List<RoleModel> realmMappings = realm.getScopeMappings(agent);
+        List<RoleRepresentation> realmMappingsRep = new ArrayList<RoleRepresentation>();
+        RealmManager manager = new RealmManager(session);
+        for (RoleModel roleModel : realmMappings) {
+            realmMappingsRep.add(manager.toRepresentation(roleModel));
+        }
+        return realmMappingsRep;
+    }
+
+    @Path("realm")
+    @POST
+    @Consumes("application/json")
+    public void addRealmScopeMappings(List<RoleRepresentation> roles) {
+        for (RoleRepresentation role : roles) {
+            RoleModel roleModel = realm.getRoleById(role.getId());
+            if (roleModel == null) {
+                throw new NotFoundException();
+            }
+            realm.addScopeMapping(agent, roleModel);
+        }
+
+
+    }
+
+    @Path("realm")
+    @DELETE
+    @Consumes("application/json")
+    public void deleteRealmScopeMappings(List<RoleRepresentation> roles) {
+        if (roles == null) {
+            List<RoleModel> roleModels = realm.getScopeMappings(agent);
+            for (RoleModel roleModel : roleModels) {
+                realm.deleteScopeMapping(agent, roleModel);
+            }
+
+        } else {
+            for (RoleRepresentation role : roles) {
+                RoleModel roleModel = realm.getRoleById(role.getId());
+                if (roleModel == null) {
+                    throw new NotFoundException();
+                }
+                realm.deleteScopeMapping(agent, roleModel);
+            }
+        }
+    }
+
+    @Path("applications/{appId}")
+    @GET
+    @Produces("application/json")
+    @NoCache
+    public List<RoleRepresentation> getApplicationScopeMappings(@PathParam("appId") String appId) {
+        ApplicationModel app = realm.getApplicationById(appId);
+
+        if (app == null) {
+            throw new NotFoundException();
+        }
+
+        List<RoleModel> mappings = app.getScopeMappings(agent);
+        List<RoleRepresentation> mapRep = new ArrayList<RoleRepresentation>();
+        for (RoleModel roleModel : mappings) {
+            mapRep.add(RealmManager.toRepresentation(roleModel));
+        }
+        return mapRep;
+    }
+
+    @Path("applications/{appId}")
+    @POST
+    @Consumes("application/json")
+    public void addApplicationScopeMapping(@PathParam("appId") String appId, List<RoleRepresentation> roles) {
+        ApplicationModel app = realm.getApplicationById(appId);
+
+        if (app == null) {
+            throw new NotFoundException();
+        }
+
+        for (RoleRepresentation role : roles) {
+            RoleModel roleModel = app.getRoleById(role.getId());
+            if (roleModel == null) {
+                throw new NotFoundException();
+            }
+            app.addScopeMapping(agent, roleModel);
+        }
+
+    }
+
+    @Path("applications/{appId}")
+    @DELETE
+    @Consumes("application/json")
+    public void deleteApplicationRoleMapping(@PathParam("appId") String appId, List<RoleRepresentation> roles) {
+        ApplicationModel app = realm.getApplicationById(appId);
+
+        if (app == null) {
+            throw new NotFoundException();
+        }
+
+        if (roles == null) {
+            List<RoleModel> roleModels = app.getScopeMappings(agent);
+            for (RoleModel roleModel : roleModels) {
+                app.deleteScopeMapping(agent, roleModel);
+            }
+
+        } else {
+            for (RoleRepresentation role : roles) {
+                RoleModel roleModel = app.getRoleById(role.getId());
+                if (roleModel == null) {
+                    throw new NotFoundException();
+                }
+                app.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 3008b92..cc9feea 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
@@ -127,16 +127,13 @@ public class UsersResource {
     @GET
     @Produces("application/json")
     @NoCache
-    public AllRoleMappingsRepresentation getRoleMappings(@PathParam("username") String username) {
+    public MappingsRepresentation getRoleMappings(@PathParam("username") String username) {
         UserModel user = realm.getUser(username);
         if (user == null) {
             throw new NotFoundException();
         }
 
-        AllRoleMappingsRepresentation all = new AllRoleMappingsRepresentation();
-        all.setRealmId(realm.getId());
-        all.setRealmName(realm.getName());
-        all.setUsername(username);
+        MappingsRepresentation all = new MappingsRepresentation();
         List<RoleModel> realmMappings = realm.getRoleMappings(user);
         RealmManager manager = new RealmManager(session);
         if (realmMappings.size() > 0) {
@@ -149,12 +146,11 @@ public class UsersResource {
 
         List<ApplicationModel> applications = realm.getApplications();
         if (applications.size() > 0) {
-            Map<String, ApplicationRoleMappingsRepresentation> appMappings = new HashMap<String, ApplicationRoleMappingsRepresentation>();
+            Map<String, ApplicationMappingsRepresentation> appMappings = new HashMap<String, ApplicationMappingsRepresentation>();
             for (ApplicationModel application : applications) {
                 List<RoleModel> roleMappings = application.getRoleMappings(user);
                 if (roleMappings.size() > 0) {
-                    ApplicationRoleMappingsRepresentation mappings = new ApplicationRoleMappingsRepresentation();
-                    mappings.setUsername(user.getLoginName());
+                    ApplicationMappingsRepresentation mappings = new ApplicationMappingsRepresentation();
                     mappings.setApplicationId(application.getId());
                     mappings.setApplication(application.getName());
                     List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
@@ -180,7 +176,6 @@ public class UsersResource {
             throw new NotFoundException();
         }
 
-        RealmRoleMappingsRepresentation rep = new RealmRoleMappingsRepresentation();
         List<RoleModel> realmMappings = realm.getRoleMappings(user);
         List<RoleRepresentation> realmMappingsRep = new ArrayList<RoleRepresentation>();
         RealmManager manager = new RealmManager(session);
diff --git a/services/src/test/java/org/keycloak/test/AdapterTest.java b/services/src/test/java/org/keycloak/test/AdapterTest.java
index aa2767a..1bdaa82 100755
--- a/services/src/test/java/org/keycloak/test/AdapterTest.java
+++ b/services/src/test/java/org/keycloak/test/AdapterTest.java
@@ -134,7 +134,7 @@ public class AdapterTest {
     public void testOAuthClient() throws Exception {
         test1CreateRealm();
 
-        OAuthClientModel oauth = new OAuthClientManager(realmModel).createOAuthClient("oauth-client");
+        OAuthClientModel oauth = new OAuthClientManager(realmModel).create("oauth-client");
         oauth.setBaseUrl("/foo/bar");
         oauth = realmModel.getOAuthClient("oauth-client");
         Assert.assertEquals("/foo/bar", oauth.getBaseUrl());
diff --git a/services/src/test/java/org/keycloak/test/ImportTest.java b/services/src/test/java/org/keycloak/test/ImportTest.java
index 30c8190..d426d4e 100755
--- a/services/src/test/java/org/keycloak/test/ImportTest.java
+++ b/services/src/test/java/org/keycloak/test/ImportTest.java
@@ -86,7 +86,7 @@ public class ImportTest {
 
         UserModel user = realm.getUser("loginclient");
         Assert.assertNotNull(user);
-        Set<String> scopes = realm.getScopeMapping(user);
+        Set<String> scopes = realm.getScopeMappingValues(user);
         System.out.println("Scopes size: " + scopes.size());
         Assert.assertTrue(scopes.contains("*"));
         Assert.assertEquals(0, realm.getSocialLinks(user).size());
@@ -101,7 +101,7 @@ public class ImportTest {
         UserModel oauthClient = realm.getUser("oauthclient");
         Assert.assertNotNull(application);
         Assert.assertNotNull(oauthClient);
-        Set<String> appScopes = application.getScopeMapping(oauthClient);
+        Set<String> appScopes = application.getScopeMappingValues(oauthClient);
         Assert.assertTrue(appScopes.contains("user"));
 
         // Test social linking