keycloak-uncached

Changes

admin-ui/src/main/resources/META-INF/resources/admin/partials/application-menu.html 23(+0 -23)

examples/as7-eap-dev/customer-app/pom.xml 73(+0 -73)

examples/as7-eap-dev/customer-app/src/main/webapp/admin/admin.jsp 11(+0 -11)

examples/as7-eap-dev/customer-app/src/main/webapp/customers/cors-test.html 38(+0 -38)

examples/as7-eap-dev/customer-app/src/main/webapp/customers/view.jsp 27(+0 -27)

examples/as7-eap-dev/customer-app/src/main/webapp/index.html 14(+0 -14)

examples/as7-eap-dev/customer-app/src/main/webapp/WEB-INF/jboss-deployment-structure.xml 11(+0 -11)

examples/as7-eap-dev/customer-app/src/main/webapp/WEB-INF/jboss-web.xml 5(+0 -5)

examples/as7-eap-dev/customer-app/src/main/webapp/WEB-INF/keycloak.json 12(+0 -12)

examples/as7-eap-dev/customer-app/src/main/webapp/WEB-INF/web.xml 49(+0 -49)

examples/as7-eap-dev/database-service/pom.xml 62(+0 -62)

examples/as7-eap-dev/database-service/src/main/java/org/jboss/resteasy/example/oauth/CustomerService.java 26(+0 -26)

examples/as7-eap-dev/database-service/src/main/java/org/jboss/resteasy/example/oauth/DataApplication.java 13(+0 -13)

examples/as7-eap-dev/database-service/src/main/java/org/jboss/resteasy/example/oauth/ProductService.java 26(+0 -26)

examples/as7-eap-dev/database-service/src/main/webapp/WEB-INF/jboss-deployment-structure.xml 9(+0 -9)

examples/as7-eap-dev/database-service/src/main/webapp/WEB-INF/jboss-web.xml 5(+0 -5)

examples/as7-eap-dev/database-service/src/main/webapp/WEB-INF/keycloak.json 7(+0 -7)

examples/as7-eap-dev/database-service/src/main/webapp/WEB-INF/web.xml 29(+0 -29)

examples/as7-eap-dev/pom.xml 44(+0 -44)

examples/as7-eap-dev/README.md 79(+0 -79)

examples/as7-eap-dev/server/link-server.bat 20(+0 -20)

examples/as7-eap-dev/server/link-server.sh 16(+0 -16)

examples/as7-eap-dev/server/pom.xml 133(+0 -133)

examples/as7-eap-dev/server/src/main/java/org/keycloak/example/demo/DemoApplication.java 60(+0 -60)

examples/as7-eap-dev/server/src/main/resources/META-INF/persistence.xml 32(+0 -32)

examples/as7-eap-dev/server/src/main/resources/META-INF/testrealm.json 88(+0 -88)

examples/as7-eap-dev/server/src/main/webapp/saas/css/base.css 35(+0 -35)

examples/as7-eap-dev/server/src/main/webapp/saas/css/ejs-styles.css 321(+0 -321)

examples/as7-eap-dev/server/src/main/webapp/saas/css/ejs-styles.less 393(+0 -393)

examples/as7-eap-dev/server/src/main/webapp/saas/css/forms.css 61(+0 -61)

examples/as7-eap-dev/server/src/main/webapp/saas/css/forms.less 66(+0 -66)

examples/as7-eap-dev/server/src/main/webapp/saas/css/img/btn-social-fb.svg 8(+0 -8)

examples/as7-eap-dev/server/src/main/webapp/saas/css/img/customer-login-screen-bg.jpg 0(+0 -0)

examples/as7-eap-dev/server/src/main/webapp/saas/css/img/customer-login-screen-bg.svg 164(+0 -164)

examples/as7-eap-dev/server/src/main/webapp/saas/css/img/customer-login-screen-bg2.jpg 0(+0 -0)

examples/as7-eap-dev/server/src/main/webapp/saas/css/img/login-register-separator.svg 7(+0 -7)

examples/as7-eap-dev/server/src/main/webapp/saas/css/img/login-register-separators.png 0(+0 -0)

examples/as7-eap-dev/server/src/main/webapp/saas/css/img/login-register-social-separators.png 0(+0 -0)

examples/as7-eap-dev/server/src/main/webapp/saas/css/img/login-register-social-separators.svg 19(+0 -19)

examples/as7-eap-dev/server/src/main/webapp/saas/css/img/login-screen-background.jpg 0(+0 -0)

examples/as7-eap-dev/server/src/main/webapp/saas/css/img/register-login-bg.png 0(+0 -0)

examples/as7-eap-dev/server/src/main/webapp/saas/css/login-screen.css 268(+0 -268)

examples/as7-eap-dev/server/src/main/webapp/saas/css/login-screen.less 302(+0 -302)

examples/as7-eap-dev/server/src/main/webapp/saas/css/reset.css 71(+0 -71)

examples/as7-eap-dev/server/src/main/webapp/saas/css/zocial/zocial.css 473(+0 -473)

examples/as7-eap-dev/server/src/main/webapp/saas/css/zocial/zocial.less 281(+0 -281)

examples/as7-eap-dev/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.eot 0(+0 -0)

examples/as7-eap-dev/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.svg 151(+0 -151)

examples/as7-eap-dev/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.ttf 0(+0 -0)

examples/as7-eap-dev/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.woff 0(+0 -0)

examples/as7-eap-dev/server/src/main/webapp/saas/oauthGrantForm.jsp 87(+0 -87)

examples/as7-eap-dev/server/src/main/webapp/saas/securityFailure.jsp 23(+0 -23)

examples/as7-eap-dev/server/src/main/webapp/WEB-INF/jboss-deployment-structure.xml 10(+0 -10)

examples/as7-eap-dev/server/src/main/webapp/WEB-INF/jboss-web.xml 3(+0 -3)

examples/as7-eap-dev/server/src/main/webapp/WEB-INF/web.xml 49(+0 -49)

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

Details

diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/index.html b/admin-ui/src/main/resources/META-INF/resources/admin/index.html
index 5a1e6fc..188074d 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/index.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/index.html
@@ -43,6 +43,7 @@
     <script src="js/app.js"></script>
     <script src="js/controllers/realm.js"></script>
     <script src="js/controllers/applications.js"></script>
+    <script src="js/controllers/oauth-clients.js"></script>
     <script src="js/controllers/users.js"></script>
     <script src="js/loaders.js"></script>
     <script src="js/services.js"></script>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
index 3b1d433..f0e6ddd 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
@@ -307,6 +307,77 @@ module.config([ '$routeProvider', function($routeProvider) {
             },
             controller : 'ApplicationListCtrl'
         })
+
+        // OAUTH Client
+
+        .when('/realms/:realm/oauth-clients/:oauth/credentials', {
+            templateUrl : 'partials/oauth-client-credentials.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                application : function(OAuthClientLoader) {
+                    return OAuthClientLoader();
+                }
+            },
+            controller : 'OAuthClientCredentialsCtrl'
+        })
+        .when('/realms/:realm/oauth-clients/:oauth/scope-mappings', {
+            templateUrl : 'partials/oauth-client-scope-mappings.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                oauth : function(OAuthClientLoader) {
+                    return OAuthClientLoader();
+                },
+                applications : function(ApplicationListLoader) {
+                    return ApplicationListLoader();
+                },
+                roles : function(RoleListLoader) {
+                    return RoleListLoader();
+                }
+            },
+            controller : 'OAuthClientScopeMappingCtrl'
+        })
+
+        .when('/create/oauth-client/:realm', {
+            templateUrl : 'partials/oauth-client-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                oauth : function() {
+                    return {};
+                }
+            },
+            controller : 'OAuthClientDetailCtrl'
+        })
+        .when('/realms/:realm/oauth-clients/:oauth', {
+            templateUrl : 'partials/oauth-client-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                oauth : function(OAuthClientLoader) {
+                    return OAuthClientLoader();
+                }
+            },
+            controller : 'OAuthClientDetailCtrl'
+        })
+        .when('/realms/:realm/oauth-clients', {
+            templateUrl : 'partials/oauth-client-list.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                oauthClients : function(OAuthClientListLoader) {
+                    return OAuthClientListLoader();
+                }
+            },
+            controller : 'OAuthClientListCtrl'
+        })
+
         .when('/', {
             templateUrl : 'partials/home.html',
             controller : 'HomeCtrl'
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/applications.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/applications.js
index 790e53d..ed435ee 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/applications.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/applications.js
@@ -194,6 +194,8 @@ module.controller('ApplicationDetailCtrl', function($scope, realm, application, 
         $scope.application= angular.copy(application);
     } else {
         $scope.application = {};
+        $scope.application.webOrigins = [];
+        $scope.application.redirectUris = [];
     }
 
     $scope.$watch(function() {
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/oauth-clients.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/oauth-clients.js
new file mode 100755
index 0000000..a0a8cd9
--- /dev/null
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/oauth-clients.js
@@ -0,0 +1,296 @@
+module.controller('OAuthClientCredentialsCtrl', function($scope, $location, realm, oauth, OAuthClientCredentials, Notifications) {
+    $scope.realm = realm;
+    $scope.oauth = oauth;
+
+    var required = realm.requiredOAuthClientCredentials;
+
+    for (var i = 0; i < required.length; i++) {
+        if (required[i] == 'password') {
+            $scope.passwordRequired = true;
+        } else if (required[i] == 'totp') {
+            $scope.totpRequired = true;
+        } else if (required[i] == 'cert') {
+            $scope.certRequired = true;
+        }
+    }
+
+    function randomString(len) {
+        var charSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+        var randomString = '';
+        for (var i = 0; i < len; i++) {
+            var randomPoz = Math.floor(Math.random() * charSet.length);
+            randomString += charSet.substring(randomPoz,randomPoz+1);
+        }
+        return randomString;
+    }
+
+    $scope.generateTotp = function() {
+        $scope.totp = randomString(5) + '-' + randomString(5) + '-' + randomString(5);
+    }
+
+    $scope.changePassword = function() {
+        if ($scope.password != $scope.confirmPassword) {
+            Notifications.error("Password and confirmation does not match.");
+            $scope.password = "";
+            $scope.confirmPassword = "";
+            return;
+        }
+        var creds = [
+            {
+                type : "password",
+                value : $scope.password
+            }
+        ];
+
+        OAuthClientCredentials.update({ realm : realm.id, oauth : oauth.id }, creds,
+            function() {
+                Notifications.success('The password has been changed.');
+                $scope.password = null;
+                $scope.confirmPassword = null;
+            },
+            function() {
+                Notifications.error("The password was not changed due to a problem.");
+                $scope.password = null;
+                $scope.confirmPassword = null;
+            }
+        );
+    };
+
+    $scope.changeTotp = function() {
+        var creds = [
+            {
+                type : "totp",
+                value : $scope.totp
+            }
+        ];
+
+        OAuthClientCredentials.update({ realm : realm.id, oauth : oauth.id }, creds,
+            function() {
+                Notifications.success('The totp was changed.');
+                $scope.totp = null;
+            },
+            function() {
+                Notifications.error("The totp was not changed due to a problem.");
+                $scope.totp = null;
+            }
+        );
+    };
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+});
+
+module.controller('OAuthClientListCtrl', function($scope, realm, oauthClients, OAuthClient, $location) {
+    $scope.realm = realm;
+    $scope.oauthClients = oauthClients;
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+});
+
+module.controller('OAuthClientDetailCtrl', function($scope, realm, oauth, OAuthClient, $location, Dialog, Notifications) {
+    $scope.realm = realm;
+    $scope.create = !oauth.id;
+    if (!$scope.create) {
+        $scope.oauth= angular.copy(oauth);
+    } else {
+        $scope.oauth = {};
+        $scope.oauth.webOrigins = [];
+        $scope.oauth.redirectUris = [];
+    }
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+
+    $scope.$watch('oauth', function() {
+        if (!angular.equals($scope.oauth, oauth)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.deleteWebOrigin = function(index) {
+        $scope.oauth.webOrigins.splice(index, 1);
+    }
+    $scope.addWebOrigin = function() {
+        $scope.oauth.webOrigins.push($scope.newWebOrigin);
+        $scope.newWebOrigin = "";
+    }
+    $scope.deleteRedirectUri = function(index) {
+        $scope.oauth.redirectUris.splice(index, 1);
+    }
+    $scope.addRedirectUri = function() {
+        $scope.oauth.redirectUris.push($scope.newRedirectUri);
+        $scope.newRedirectUri = "";
+    }
+
+    $scope.save = function() {
+        if ($scope.create) {
+            OAuthClient.save({
+                realm: realm.id
+            }, $scope.oauth, function (data, headers) {
+                $scope.changed = false;
+                var l = headers().location;
+                var id = l.substring(l.lastIndexOf("/") + 1);
+                $location.url("/realms/" + realm.id + "/oauth-clients/" + id);
+                Notifications.success("The oauth client has been created.");
+            });
+        } else {
+            OAuthClient.update({
+                realm : realm.id,
+                id : oauth.id
+            }, $scope.oauth, function() {
+                $scope.changed = false;
+                oauth = angular.copy($scope.oauth);
+                Notifications.success("Your changes have been saved to the oauth client.");
+            });
+        }
+    };
+
+    $scope.reset = function() {
+        $scope.oauth = angular.copy(oauth);
+        $scope.changed = false;
+    };
+
+    $scope.cancel = function() {
+        $location.url("/realms/" + realm.id + "/oauth-clients");
+    };
+
+    $scope.remove = function() {
+        Dialog.confirmDelete($scope.oauth.name, 'oauth', function() {
+            $scope.oauth.$remove({
+                realm : realm.id,
+                id : $scope.oauth.id
+            }, function() {
+                $location.url("/realms/" + realm.id + "/oauth-clients");
+                Notifications.success("The oauth client has been deleted.");
+            });
+        });
+    };
+
+
+});
+
+module.controller('OAuthClientScopeMappingCtrl', function($scope, $http, realm, oauth, roles, applications, OAuthClientRealmScopeMapping, OAuthClientApplicationScopeMapping, ApplicationRole) {
+    $scope.realm = realm;
+    $scope.oauth = oauth;
+    $scope.realmRoles = angular.copy(roles);
+    $scope.selectedRealmRoles = [];
+    $scope.selectedRealmMappings = [];
+    $scope.realmMappings = [];
+    $scope.applications = applications;
+    $scope.applicationRoles = [];
+    $scope.selectedApplicationRoles = [];
+    $scope.selectedApplicationMappings = [];
+    $scope.applicationMappings = [];
+
+
+
+    $scope.realmMappings = OAuthClientRealmScopeMapping.query({realm : realm.id, oauth : oauth.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 + '/oauth-clients/' + oauth.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 + '/oauth-clients/' + oauth.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 + '/oauth-clients/' + oauth.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 + '/oauth-clients/' + oauth.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 = OAuthClientApplicationScopeMapping.query({realm : realm.id, oauth : oauth.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/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js
index 41d74a6..7b72c48 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js
@@ -134,4 +134,21 @@ module.factory('RoleMappingLoader', function(Loader, RoleMapping, $route, $q) {
 			role : $route.current.params.role
 		}
 	});
-});
\ No newline at end of file
+});
+
+module.factory('OAuthClientLoader', function(Loader, OAuthClient, $route, $q) {
+    return Loader.get(OAuthClient, function() {
+        return {
+            realm : $route.current.params.realm,
+            id : $route.current.params.oauth
+        }
+    });
+});
+
+module.factory('OAuthClientListLoader', function(Loader, OAuthClient, $route, $q) {
+    return Loader.query(OAuthClient, function() {
+        return {
+            realm : $route.current.params.realm
+        }
+    });
+});
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js
index b666617..88d4ec3 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js
@@ -249,6 +249,45 @@ module.factory('ApplicationOrigins', function($resource) {
     });
 });
 
+module.factory('OAuthClient', function($resource) {
+    return $resource('/auth-server/rest/saas/admin/realms/:realm/oauth-clients/:id', {
+        realm : '@realm',
+        id : '@id'
+    },  {
+        update : {
+            method : 'PUT'
+        }
+    });
+});
+
+module.factory('OAuthClientCredentials', function($resource) {
+    return $resource('/auth-server/rest/saas/admin/realms/:realm/oauth-clients/:oauth/credentials', {
+        realm : '@realm',
+        oauth : '@oauth'
+    },  {
+        update : {
+            method : 'PUT',
+            isArray : true
+        }
+    });
+});
+
+module.factory('OAuthClientRealmScopeMapping', function($resource) {
+    return $resource('/auth-server/rest/saas/admin/realms/:realm/oauth-clients/:oauth/scope-mappings/realm', {
+        realm : '@realm',
+        oauth : '@oauth'
+    });
+});
+
+module.factory('OAuthClientApplicationScopeMapping', function($resource) {
+    return $resource('/auth-server/rest/saas/admin/realms/:realm/oauth-clients/:oauth/scope-mappings/applications/:targetApp', {
+        realm : '@realm',
+        oauth : '@oauth',
+        targetApp : '@targetApp'
+    });
+});
+
+
 module.factory('Current', function(Realm, $route) {
     var current = {};
 
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-detail.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-detail.html
index 6d1ffa1..2a21202 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-detail.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-detail.html
@@ -47,14 +47,6 @@
                             <input ng-model="application.enabled" name="enabled" id="enabled" onoffswitch />
                         </div>
                         <div class="form-group">
-                            <label for="baseUrl" class="control-label">Base URL</label>
-
-                            <div class="controls">
-                                <input class="input-small" type="text" name="baseUrl" id="baseUrl"
-                                       data-ng-model="application.baseUrl">
-                            </div>
-                        </div>
-                        <div class="form-group">
                             <label for="adminUrl" class="control-label">Admin URL</label>
 
                             <div class="controls">
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-list.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-list.html
index 16a1697..d472c61 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-list.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-list.html
@@ -36,12 +36,11 @@
                     <tr data-ng-show="applications.length > 0">
                         <th>Application Name</th>
                         <th>Enabled</th>
-                        <th>Base URL</th>
                     </tr>
                     </thead>
                     <tfoot data-ng-show="applications && applications.length > 5"> <!-- todo -->
                     <tr>
-                        <td colspan="3">
+                        <td colspan="2">
                             <div class="table-nav">
                                 <a href="#" class="first disabled">First page</a><a href="#" class="prev disabled">Previous
                                 page</a><span><strong>1-8</strong> of <strong>10</strong></span><a href="#"
@@ -55,7 +54,6 @@
                     <tr ng-repeat="app in applications">
                         <td><a href="#/realms/{{realm.id}}/applications/{{app.id}}">{{app.name}}</a></td>
                         <td>{{app.enabled}}</td>
-                        <td ng-class="{'text-muted': !app.baseUrl}">{{app.baseUrl || "Not defined"}}</td>
                     </tr>
                     </tbody>
                 </table>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-credentials.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-credentials.html
new file mode 100755
index 0000000..01d63c5
--- /dev/null
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-credentials.html
@@ -0,0 +1,64 @@
+<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="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}">Settings</a></li>
+                    <li class="active"><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
+                </ul>
+            </div>
+            <div id="content">
+                <ol class="breadcrumb" data-ng-hide="create">
+                    <li><a href="#/realms/{{realm.id}}">{{realm.realm}}</a></li>
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients">OAuth Clients</a></li>
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}">{{oauth.name}}</a></li>
+                    <li class="active">Credentials</li>
+                </ol>
+                <h2 data-ng-hide="create"><span>{{oauth.name}}</span> Credentials</h2>
+                <form name="credentialForm" novalidate >
+                    <fieldset data-ng-show="passwordRequired">
+                        <legend uncollapsed><span class="text">Change Password</span></legend>
+                        <div class="form-group">
+                            <label for="password">New Password</label>
+                            <div class="controls">
+                            <input type="password" id="password" name="password" data-ng-model="password" autofocus
+                                   required>
+                            </div>
+                        </div>
+                        <div class="form-group">
+                            <label class="two-lines" for="password">New Password Confirmation</label>
+                            <div class="controls">
+                                <input type="password" id="confirmPassword" name="confirmPassword" data-ng-model="confirmPassword"
+                                       required>
+                            </div>
+                        </div>
+                        <div class="form-actions">
+                            <button type="submit" data-ng-click="changePassword()" class="primary" ng-show="password != null">Save
+                            </button>
+                        </div>
+                    </fieldset>
+                    <fieldset data-ng-show="totpRequired">
+                        <legend uncollapsed><span class="text">Change TOTP Key</span></legend>
+                        <div class="form-group">
+                            <label for="totp">New Key</label>
+                            <div class="controls">
+                                <input type="text" id="totp" name="totp" data-ng-model="totp" autofocus
+                                       required>
+                                <button type="submit" data-ng-click="generateTotp()">Generate
+                                </button>
+                            </div>
+                        </div>
+                        <div class="form-actions">
+                            <label></label>
+                            <button type="submit" data-ng-click="changeTotp()" class="primary" ng-show="totp != null">Save
+                            </button>
+                        </div>
+                    </fieldset>
+                </form>
+            </div>
+        </div>
+        <div id="container-right-bg"></div>
+    </div>
+</div>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-detail.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-detail.html
new file mode 100755
index 0000000..22427f3
--- /dev/null
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-detail.html
@@ -0,0 +1,99 @@
+<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" data-ng-show="!create">
+                <ul class="rcue-tabs">
+                    <li class="active"><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}">Settings</a></li>
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
+                </ul>
+            </div>
+            <div class="top-nav" data-ng-show="create">
+                <ul class="rcue-tabs">
+                    <li></li>
+                </ul>
+            </div>
+            <div id="content">
+                <ol class="breadcrumb" data-ng-show="create">
+                    <li><a href="#/realms/{{realm.id}}">{{realm.realm}}</a></li>
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients">OAuth Clients</a></li>
+                    <li class="active">Add OAuth Client</li>
+                </ol>
+                <h2 class="pull-left" data-ng-show="create"><span>{{realm.realm}}</span> Add OAuth Client</h2>
+                <p class="subtitle" data-ng-show="create"><span class="required">*</span> Required fields</p>
+                <ol class="breadcrumb" data-ng-hide="create">
+                    <li><a href="#/realms/{{realm.id}}">{{realm.realm}}</a></li>
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients">OAuth Clients</a></li>
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}">{{oauth.name}}</a></li>
+                    <li class="active">Settings</li>
+                </ol>
+                <h2 data-ng-hide="create"><span>{{oauth.name}}</span> Settings</h2>
+                <form name="oauthForm" novalidate>
+                    <fieldset class="border-top">
+                        <div class="form-group">
+                            <label for="name">Name <span class="required" data-ng-show="create">*</span></label>
+                            <div class="controls">
+                            <input type="text" id="name" name="name" data-ng-model="oauth.name" autofocus
+                                   required>
+                            </div>
+                        </div>
+
+                        <div class="form-group clearfix block">
+                            <label for="enabled" class="control-label">Enabled</label>
+                            <input ng-model="oauth.enabled" name="enabled" id="enabled" onoffswitch />
+                        </div>
+                        <div class="form-group">
+                            <label for="newWebOrigin" class="control-label">Web Origin</label>
+                            <div class="controls">
+                                <div ng-repeat="webOrigin in oauth.webOrigins" class="item-deletable">
+                                    <input  class="input-small" type="text" data-ng-class="{'input-below':!$first}"
+                                            name="webOrigin" id="webOrigin" data-ng-model="webOrigin" readonly />
+                                    <button type="button" data-ng-click="deleteWebOrigin($index)" class="btn-delete">
+                                        Delete</button>
+                                </div>
+                                <input class="input-small" type="text" name="newWebOrigin" id="newWebOrigin"
+                                       placeholder="New Web Origin..." data-ng-model="newWebOrigin"
+                                       data-ng-class="{'input-below':oauth.webOrigins.length}" />
+                                <button data-ng-click="addWebOrigin()" ng-show="newWebOrigin.length > 0">Add</button>
+                            </div>
+                        </div>
+                        <div class="form-group">
+                            <label for="newRedirectUri" class="control-label">Redirect URI</label>
+                            <div class="controls">
+                                <div ng-repeat="redirectUri in oauth.redirectUris" class="item-deletable">
+                                    <input  class="input-small" type="text" data-ng-class="{'input-below':!$first}"
+                                            name="redirectUri" id="redirectUri" data-ng-model="redirectUri" readonly />
+                                    <button type="button" data-ng-click="deleteRedirectUri($index)" class="btn-delete">
+                                        Delete</button>
+                                </div>
+                                <input class="input-small" type="text" name="newRedirectUri" id="newRedirectUri"
+                                       placeholder="New Redirect URI..." data-ng-model="newRedirectUri"
+                                       data-ng-class="{'input-below':oauth.redirectUris.length}" />
+                                <button data-ng-click="addRedirectUri()" ng-show="newRedirectUri.length > 0">Add</button>
+                            </div>
+                        </div>
+                    </fieldset>
+                    <div class="form-actions" data-ng-show="create">
+                        <button type="submit" kc-save data-ng-show="changed" class="primary">Save
+                        </button>
+                        <button type="submit" data-ng-click="cancel()">Cancel
+                        </button>
+                    </div>
+
+                    <div class="form-actions" data-ng-show="!create">
+                        <button type="submit" kc-save class="primary" data-ng-show="changed">Save
+                        </button>
+                        <button type="submit" kc-reset data-ng-show="changed">Clear changes
+                        </button>
+                        <button type="submit" data-ng-click="remove()" class="destructive" data-ng-hide="changed">
+                            Delete
+                        </button>
+                    </div>
+
+                </form>
+            </div>
+        </div>
+        <div id="container-right-bg"></div>
+    </div>
+</div>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-list.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-list.html
new file mode 100755
index 0000000..e7bb3c6
--- /dev/null
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-list.html
@@ -0,0 +1,67 @@
+<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></li>
+                </ul>
+            </div>
+            <div id="content">
+                <ol class="breadcrumb">
+                    <li><a href="#/realms/{{realm.id}}">{{realm.realm}}</a></li>
+                    <li class="active">OAuth Clients</li>
+                </ol>
+                <h2><span>{{realm.realm}}</span> OAuth Clients</h2>
+                <div class="feedback info inline" data-ng-show="!oauthClients || oauthClients.length == 0">
+                    <p><strong>You have not configured oauth clients.</strong> <a class="button" href="#/create/oauth-client/{{realm.id}}">Add OAuth Client</a></p>
+                </div>
+                <table data-ng-hide="oauthClients.length == 0">
+                    <thead>
+                    <tr>
+                        <th class="rcue-table-actions" colspan="3">
+                            <div class="search-comp clearfix">
+                                <input type="text" placeholder="Search..." class="search"
+                                       onkeyup="if(event.keyCode == 13){$(this).next('button').click();}">
+                                <button class="icon-search" tooltip-placement="right"
+                                        tooltip="Search by oauth client name.">
+                                    Icon: search
+                                </button>
+                            </div>
+                            <div class="actions">
+                                <a class="button" href="#/create/oauth-client/{{realm.id}}">Add OAuth Client</a>
+                            </div>
+                        </th>
+                    </tr>
+                    <tr data-ng-show="oauthClients.length > 0">
+                        <th>OAuth Client Name</th>
+                        <th>Enabled</th>
+                    </tr>
+                    </thead>
+                    <tfoot data-ng-show="oauthClients && oauthClients.length > 5"> <!-- todo -->
+                    <tr>
+                        <td colspan="2">
+                            <div class="table-nav">
+                                <a href="#" class="first disabled">First page</a><a href="#" class="prev disabled">Previous
+                                page</a><span><strong>1-8</strong> of <strong>10</strong></span><a href="#"
+                                                                                                   class="next">Next
+                                page</a><a href="#" class="last">Last page</a>
+                            </div>
+                        </td>
+                    </tr>
+                    </tfoot>
+                    <tbody>
+                    <tr ng-repeat="client in oauthClients">
+                        <td><a href="#/realms/{{realm.id}}/oauth-clients/{{client.id}}">{{client.name}}</a></td>
+                        <td>{{client.enabled}}</td>
+                    </tr>
+                    </tbody>
+                </table>
+                <div class="feedback warning inline" data-ng-show="search && oauthClients.length == 0">
+                    <p><strong>Your search returned no results.</strong><br>Try modifying the query and try again.</p>
+                </div>
+            </div>
+        </div>
+        <div id="container-right-bg"></div>
+    </div>
+</div>
\ No newline at end of file
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-scope-mappings.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-scope-mappings.html
new file mode 100755
index 0000000..c2d0308
--- /dev/null
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-scope-mappings.html
@@ -0,0 +1,92 @@
+<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="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}">Settings</a></li>
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
+                    <li class="active"><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
+                </ul>
+            </div>
+            <div id="content">
+                <ol class="breadcrumb" data-ng-hide="create">
+                    <li><a href="#/realms/{{realm.id}}">{{realm.realm}}</a></li>
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients">OAuth Clients</a></li>
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}">{{oauth.name}}</a></li>
+                    <li class="active">Scope</li>
+                </ol>
+                <h2 class="pull-left"><span>{{oauth.name}}</span> Scope Mappings</h2>
+                <p class="subtitle"></p>
+                <form name="realmForm" novalidate>
+                    <fieldset>
+                        <legend uncollapsed><span class="text">Realm Roles</span></legend>
+                        <div class="form-group">
+                            <div class="controls changing-selectors">
+                                <div class="select-title">
+                                    <label for="available">Available Roles</label>
+                                    <select id="available" class="form-control" multiple size="5"
+                                            ng-multiple="true"
+                                            ng-model="selectedRealmRoles"
+                                            ng-options="r.name for r in realmRoles">
+                                    </select>
+                                </div>
+                                <div class="middle-buttons">
+                                    <button type="submit" ng-click="addRealmRole()" tooltip="Move right" tooltip-placement="right"><span class="icon-arrow-right">Move right</span></button>
+                                    <button type="submit" ng-click="deleteRealmRole()" tooltip="Move left" tooltip-placement="right"><span class="icon-arrow-left">Move left</span></button>
+                                </div>
+                                <div class="select-title">
+                                    <label for="assigned">Assigned Roles</label>
+                                    <select id="assigned" class="form-control" multiple size=5
+                                            ng-multiple="true"
+                                            ng-model="selectedRealmMappings"
+                                            ng-options="r.name for r in realmMappings">
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </fieldset>
+
+                    <fieldset ng-show="applications.length > 0">
+                        <legend collapsed><span class="text">Application Roles</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)">
+                                        <option value="" selected> Select an Application </option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="form-group" ng-show="targetApp">
+                            <div class="controls changing-selectors application">
+                                <div class="select-title">
+                                    <label for="app-available">Available Roles</label>
+                                    <select id="app-available" class="form-control" multiple size="5"
+                                            ng-multiple="true"
+                                            ng-model="selectedApplicationRoles"
+                                            ng-options="r.name for r in applicationRoles">
+                                    </select>
+                                </div>
+                                <div class="middle-buttons">
+                                    <button type="submit" ng-click="addApplicationRole()" tooltip="Move right" tooltip-placement="right"><span class="icon-arrow-right">Move right</span></button>
+                                    <button type="submit" ng-click="deleteApplicationRole()" tooltip="Move left" tooltip-placement="right"><span class="icon-arrow-left">Move left</span></button>
+                                </div>
+                                <div class="select-title">
+                                    <label for="app-assigned">Assigned Roles</label>
+                                    <select id="app-assigned" class="form-control" multiple size=5
+                                            ng-multiple="true"
+                                            ng-model="selectedApplicationMappings"
+                                            ng-options="r.name for r in applicationMappings">
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </fieldset>
+                </form>
+            </div>
+        </div>
+        <div id="container-right-bg"></div>
+    </div>
+</div>
\ No newline at end of file
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-menu.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-menu.html
index 87e0ed1..40739e8 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-menu.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-menu.html
@@ -3,5 +3,6 @@
     <li data-ng-class="(path[2] == 'users' || path[1] == 'user') && 'active'"><a href="#/realms/{{realm.id}}/users">Users</a>
     </li>
     <li data-ng-class="(path[2] == 'applications' || path[1] == 'application') && 'active'"><a href="#/realms/{{realm.id}}/applications">Applications</a></li>
+    <li data-ng-class="(path[2] == 'oauth-clients' || path[1] == 'oauth-client') && 'active'"><a href="#/realms/{{realm.id}}/oauth-clients">OAuth Clients</a></li>
 </ul>
 
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 bab05a0..dee8ae5 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
@@ -12,7 +12,6 @@ public class ApplicationRepresentation {
     protected String id;
     protected String name;
     protected String adminUrl;
-    protected String baseUrl;
     protected boolean surrogateAuthRequired;
     protected boolean enabled;
     protected List<CredentialRepresentation> credentials;
@@ -116,14 +115,6 @@ public class ApplicationRepresentation {
         this.adminUrl = adminUrl;
     }
 
-    public String getBaseUrl() {
-        return baseUrl;
-    }
-
-    public void setBaseUrl(String baseUrl) {
-        this.baseUrl = baseUrl;
-    }
-
     public List<CredentialRepresentation> getCredentials() {
         return credentials;
     }
diff --git a/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java
index 9f1b821..cf46b1e 100755
--- a/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java
@@ -10,9 +10,10 @@ import java.util.List;
 public class OAuthClientRepresentation {
     protected String id;
     protected String name;
-    protected String baseUrl;
+    protected List<String> redirectUris;
+    protected List<String> webOrigins;
     protected boolean enabled;
-    protected List<ScopeMappingRepresentation> scopeMappings;
+    protected List<CredentialRepresentation> credentials;
 
     public String getId() {
         return id;
@@ -38,23 +39,27 @@ public class OAuthClientRepresentation {
         this.enabled = enabled;
     }
 
-    public List<ScopeMappingRepresentation> getScopeMappings() {
-        return scopeMappings;
+    public List<String> getRedirectUris() {
+        return redirectUris;
     }
 
-    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 void setRedirectUris(List<String> redirectUris) {
+        this.redirectUris = redirectUris;
     }
 
-    public String getBaseUrl() {
-        return baseUrl;
+    public List<String> getWebOrigins() {
+        return webOrigins;
     }
 
-    public void setBaseUrl(String baseUrl) {
-        this.baseUrl = baseUrl;
+    public void setWebOrigins(List<String> webOrigins) {
+        this.webOrigins = webOrigins;
+    }
+
+    public List<CredentialRepresentation> getCredentials() {
+        return credentials;
+    }
+
+    public void setCredentials(List<CredentialRepresentation> credentials) {
+        this.credentials = credentials;
     }
 }
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 3b9b4d1..7ae7dd2 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
@@ -33,11 +33,11 @@ public class RealmRepresentation {
     protected Set<String> requiredApplicationCredentials;
     protected Set<String> requiredOAuthClientCredentials;
     protected List<UserRepresentation> users;
-    protected List<UserRepresentation> clients;
     protected List<UserRoleMappingRepresentation> roleMappings;
     protected List<ScopeMappingRepresentation> scopeMappings;
     protected List<SocialMappingRepresentation> socialMappings;
     protected List<ApplicationRepresentation> applications;
+    protected List<OAuthClientRepresentation> oauthClients;
     protected Map<String, String> socialProviders;
     protected Map<String, String> smtpServer;
 
@@ -69,10 +69,6 @@ public class RealmRepresentation {
         return users;
     }
 
-    public List<UserRepresentation> getClients() {
-        return clients;
-    }
-
     public List<ApplicationRepresentation> getApplications() {
         return applications;
     }
@@ -89,10 +85,6 @@ public class RealmRepresentation {
         this.users = users;
     }
 
-    public void setClients(List<UserRepresentation> clients) {
-        this.clients = clients;
-    }
-
     public UserRepresentation user(String username) {
         UserRepresentation user = new UserRepresentation();
         user.setUsername(username);
@@ -308,4 +300,12 @@ public class RealmRepresentation {
     public void setSmtpServer(Map<String, String> smtpServer) {
         this.smtpServer = smtpServer;
     }
+
+    public List<OAuthClientRepresentation> getOauthClients() {
+        return oauthClients;
+    }
+
+    public void setOauthClients(List<OAuthClientRepresentation> oauthClients) {
+        this.oauthClients = oauthClients;
+    }
 }
diff --git a/examples/as7-eap-demo/product-app/src/main/java/org/jboss/resteasy/example/oauth/ProductDatabaseClient.java b/examples/as7-eap-demo/product-app/src/main/java/org/jboss/resteasy/example/oauth/ProductDatabaseClient.java
new file mode 100755
index 0000000..dc98ec7
--- /dev/null
+++ b/examples/as7-eap-demo/product-app/src/main/java/org/jboss/resteasy/example/oauth/ProductDatabaseClient.java
@@ -0,0 +1,36 @@
+package org.jboss.resteasy.example.oauth;
+
+import org.jboss.resteasy.client.jaxrs.ResteasyClient;
+import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
+import org.keycloak.SkeletonKeySession;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ProductDatabaseClient
+{
+    public static List<String> getProducts(HttpServletRequest request)
+    {
+        SkeletonKeySession session = (SkeletonKeySession)request.getAttribute(SkeletonKeySession.class.getName());
+        ResteasyClient client = new ResteasyClientBuilder()
+                .trustStore(session.getMetadata().getTruststore())
+                .hostnameVerification(ResteasyClientBuilder.HostnameVerificationPolicy.ANY).build();
+        try
+        {
+            Response response = client.target("http://localhost:8080/database/products").request()
+                    .header(HttpHeaders.AUTHORIZATION, "Bearer " + session.getTokenString()).get();
+            return response.readEntity(new GenericType<List<String>>(){});
+        }
+        finally
+        {
+            client.close();
+        }
+    }
+}
diff --git a/examples/as7-eap-demo/server/pom.xml b/examples/as7-eap-demo/server/pom.xml
index 8b82f4b..94bff30 100755
--- a/examples/as7-eap-demo/server/pom.xml
+++ b/examples/as7-eap-demo/server/pom.xml
@@ -37,6 +37,11 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-jpa</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
             <artifactId>keycloak-social-core</artifactId>
             <version>${project.version}</version>
         </dependency>
diff --git a/examples/as7-eap-demo/server/src/main/resources/META-INF/testrealm.json b/examples/as7-eap-demo/server/src/main/resources/META-INF/testrealm.json
index cc267ee..21b5f99 100755
--- a/examples/as7-eap-demo/server/src/main/resources/META-INF/testrealm.json
+++ b/examples/as7-eap-demo/server/src/main/resources/META-INF/testrealm.json
@@ -28,16 +28,6 @@
             ]
         }
     ],
-    "clients" : [
-        {
-            "username" : "third-party",
-            "enabled": true,
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ]
-        }
-    ],
     "roles": [
         {
             "name": "user",
@@ -58,7 +48,16 @@
         {
             "username": "third-party",
             "roles": ["user"]
+        },
+        {
+            "username": "customer-portal",
+            "roles": ["user"]
+        },
+        {
+            "username": "product-portal",
+            "roles": ["user"]
         }
+
     ],
     "applications": [
         {
@@ -83,5 +82,18 @@
                 }
             ]
         }
+    ],
+    "oauthClients": [
+        {
+            "name": "third-party",
+            "enabled": true,
+            "credentials": [
+                {
+                    "type": "password",
+                    "value": "password"
+                }
+            ]
+        }
     ]
+
 }

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

diff --git a/examples/pom.xml b/examples/pom.xml
index 664977a..d491f21 100755
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -35,6 +35,5 @@
     </build>
     <modules>
         <module>as7-eap-demo</module>
-        <module>as7-eap-dev</module>
     </modules>
 </project>
diff --git a/model/api/src/main/java/org/keycloak/models/ApplicationModel.java b/model/api/src/main/java/org/keycloak/models/ApplicationModel.java
index e5374b8..9039f4f 100755
--- a/model/api/src/main/java/org/keycloak/models/ApplicationModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ApplicationModel.java
@@ -29,10 +29,6 @@ public interface ApplicationModel extends RoleContainerModel, RoleMapperModel, S
 
     void setManagementUrl(String url);
 
-    String getBaseUrl();
-
-    void setBaseUrl(String url);
-
     List<String> getDefaultRoles();
 
     void addDefaultRole(String name);
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 57ec2ae..d4af49f 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -140,6 +140,8 @@ public interface RealmModel extends RoleContainerModel, RoleMapperModel, ScopeMa
     OAuthClientModel addOAuthClient(String name);
 
     OAuthClientModel getOAuthClient(String name);
+    OAuthClientModel getOAuthClientById(String id);
+    boolean removeOAuthClient(String id);
 
     List<OAuthClientModel> getOAuthClients();
 
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 1ca34b6..ad5f9e1 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
@@ -83,15 +83,6 @@ public class ApplicationAdapter implements ApplicationModel {
     }
 
     @Override
-    public String getBaseUrl() {
-        return null;
-    }
-
-    @Override
-    public void setBaseUrl(String url) {
-    }
-
-    @Override
     public RoleModel getRole(String name) {
         Collection<RoleEntity> roles = application.getRoles();
         if (roles == null) return null;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index 96e539a..7a47448 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -575,9 +575,13 @@ public class RealmAdapter implements RealmModel {
             return false;
         }
         realm.getApplications().remove(application);
-        removeUser(application.getApplicationUser());
         em.createQuery("delete from " + ApplicationScopeMappingEntity.class.getSimpleName() + " where application = :application").setParameter("application", application).executeUpdate();
         em.createQuery("delete from " + ApplicationUserRoleMappingEntity.class.getSimpleName() + " where application = :application").setParameter("application", application).executeUpdate();
+        em.createQuery("delete from " + ApplicationScopeMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", application.getApplicationUser()).executeUpdate();
+        em.createQuery("delete from " + RealmScopeMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", application.getApplicationUser()).executeUpdate();
+        em.createQuery("delete from " + ApplicationUserRoleMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", application.getApplicationUser()).executeUpdate();
+        em.createQuery("delete from " + RealmUserRoleMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", application.getApplicationUser()).executeUpdate();
+        removeUser(application.getApplicationUser());
         em.remove(application);
         return true;
     }
@@ -724,6 +728,19 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
+    public boolean removeOAuthClient(String id) {
+        OAuthClientEntity client = em.find(OAuthClientEntity.class, id);
+        em.createQuery("delete from " + ApplicationScopeMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", client.getAgent()).executeUpdate();
+        em.createQuery("delete from " + RealmScopeMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", client.getAgent()).executeUpdate();
+        em.createQuery("delete from " + ApplicationUserRoleMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", client.getAgent()).executeUpdate();
+        em.createQuery("delete from " + RealmUserRoleMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", client.getAgent()).executeUpdate();
+        removeUser(client.getAgent());
+        em.remove(client);
+        return true;
+    }
+
+
+    @Override
     public OAuthClientModel getOAuthClient(String name) {
         TypedQuery<OAuthClientEntity> query = em.createNamedQuery("findOAuthClientByUser", OAuthClientEntity.class);
         query.setParameter("name", name);
@@ -731,7 +748,15 @@ public class RealmAdapter implements RealmModel {
         List<OAuthClientEntity> entities = query.getResultList();
         if (entities.size() == 0) return null;
         return new OAuthClientAdapter(entities.get(0));
-     }
+    }
+
+    @Override
+    public OAuthClientModel getOAuthClientById(String id) {
+        OAuthClientEntity client = em.find(OAuthClientEntity.class, id);
+        if (client == null) return null;
+        return new OAuthClientAdapter(client);
+    }
+
 
     @Override
     public List<OAuthClientModel> getOAuthClients() {
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 98a510a..e6fe85b 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
@@ -106,17 +106,6 @@ public class ApplicationAdapter implements ApplicationModel {
     }
 
     @Override
-    public String getBaseUrl() {
-        return applicationData.getBaseUrl();
-    }
-
-    @Override
-    public void setBaseUrl(String url) {
-        applicationData.setBaseUrl(url);
-        updateApplication();
-    }
-
-    @Override
     public RoleAdapter getRole(String name) {
         Role role = SampleModel.getRole(getIdm(), name);
         if (role == null) return null;
diff --git a/model/picketlink/src/main/java/org/keycloak/models/picketlink/mappings/ApplicationData.java b/model/picketlink/src/main/java/org/keycloak/models/picketlink/mappings/ApplicationData.java
index 5ce4aca..3adb8f3 100755
--- a/model/picketlink/src/main/java/org/keycloak/models/picketlink/mappings/ApplicationData.java
+++ b/model/picketlink/src/main/java/org/keycloak/models/picketlink/mappings/ApplicationData.java
@@ -13,7 +13,6 @@ public class ApplicationData extends AbstractPartition {
     private boolean enabled;
     private boolean surrogateAuthRequired;
     private String managementUrl;
-    private String baseUrl;
     private User resourceUser;
     private String[] defaultRoles;
 
@@ -69,15 +68,6 @@ public class ApplicationData extends AbstractPartition {
     }
 
     @AttributeProperty
-    public String getBaseUrl() {
-        return baseUrl;
-    }
-
-    public void setBaseUrl(String baseUrl) {
-        this.baseUrl = baseUrl;
-    }
-
-    @AttributeProperty
     public String[] getDefaultRoles() {
         return defaultRoles;
     }
diff --git a/model/picketlink/src/main/java/org/keycloak/models/picketlink/mappings/ApplicationEntity.java b/model/picketlink/src/main/java/org/keycloak/models/picketlink/mappings/ApplicationEntity.java
index 0e8d23b..88af1a6 100755
--- a/model/picketlink/src/main/java/org/keycloak/models/picketlink/mappings/ApplicationEntity.java
+++ b/model/picketlink/src/main/java/org/keycloak/models/picketlink/mappings/ApplicationEntity.java
@@ -31,8 +31,6 @@ public class ApplicationEntity implements Serializable {
     private boolean surrogateAuthRequired;
     @AttributeValue
     private String managementUrl;
-    @AttributeValue
-    private String baseUrl;
 
     @AttributeValue
     private String[] defaultRoles;
@@ -82,14 +80,6 @@ public class ApplicationEntity implements Serializable {
         this.managementUrl = managementUrl;
     }
 
-    public String getBaseUrl() {
-        return baseUrl;
-    }
-
-    public void setBaseUrl(String baseUrl) {
-        this.baseUrl = baseUrl;
-    }
-
     public AccountTypeEntity getResourceUser() {
         return resourceUser;
     }
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 3f6631c..1300b53 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
@@ -747,6 +747,19 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
+    public boolean removeOAuthClient(String id) {
+        RelationshipQuery<OAuthClientRelationship> query = getRelationshipManager().createRelationshipQuery(OAuthClientRelationship.class);
+        query.setParameter(OAuthClientRelationship.REALM, realm.getName());
+        query.setParameter(OAuthClientRelationship.ID, id);
+        List<OAuthClientRelationship> results = query.getResultList();
+        if (results.size() == 0) return false;
+        OAuthClientRelationship relationship = results.get(0);
+        getRelationshipManager().remove(relationship);
+        return true;
+    }
+
+
+    @Override
     public OAuthClientModel getOAuthClient(String name) {
         User user = findPicketlinkUser(name);
         if (user == null) return null;
@@ -758,6 +771,17 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
+    public OAuthClientModel getOAuthClientById(String id) {
+        RelationshipQuery<OAuthClientRelationship> query = getRelationshipManager().createRelationshipQuery(OAuthClientRelationship.class);
+        query.setParameter(OAuthClientRelationship.REALM, realm.getName());
+        query.setParameter(OAuthClientRelationship.ID, id);
+        List<OAuthClientRelationship> results = query.getResultList();
+        if (results.size() == 0) return null;
+        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());
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 51c5e53..8081979 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
@@ -36,13 +36,20 @@ public class ApplicationManager {
         this.realmManager = realmManager;
     }
 
+    /**
+     * Does not create scope or role mappings!
+     *
+     * @param realm
+     * @param loginRole
+     * @param resourceRep
+     * @return
+     */
     public ApplicationModel createApplication(RealmModel realm, RoleModel loginRole, ApplicationRepresentation resourceRep) {
         logger.debug("************ CREATE APPLICATION: {0}" + resourceRep.getName());
         ApplicationModel applicationModel = realm.addApplication(resourceRep.getName());
         applicationModel.setEnabled(resourceRep.isEnabled());
         applicationModel.setManagementUrl(resourceRep.getAdminUrl());
         applicationModel.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
-        applicationModel.setBaseUrl(resourceRep.getBaseUrl());
         applicationModel.updateApplication();
 
         UserModel resourceUser = applicationModel.getApplicationUser();
@@ -80,6 +87,10 @@ public class ApplicationManager {
             applicationModel.updateDefaultRoles(resourceRep.getDefaultRoles());
         }
 
+        return applicationModel;
+    }
+
+    public void createMappings(RealmModel realm, ApplicationRepresentation resourceRep, ApplicationModel applicationModel) {
         if (resourceRep.getRoleMappings() != null) {
             for (UserRoleMappingRepresentation mapping : resourceRep.getRoleMappings()) {
                 UserModel user = realm.getUser(mapping.getUsername());
@@ -107,7 +118,6 @@ public class ApplicationManager {
                 }
             }
         }
-        return applicationModel;
     }
 
     public ApplicationModel createApplication(RealmModel realm, ApplicationRepresentation resourceRep) {
@@ -119,7 +129,6 @@ public class ApplicationManager {
         resource.setName(rep.getName());
         resource.setEnabled(rep.isEnabled());
         resource.setManagementUrl(rep.getAdminUrl());
-        resource.setBaseUrl(rep.getBaseUrl());
         resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired());
         resource.updateApplication();
 
@@ -145,7 +154,6 @@ public class ApplicationManager {
         rep.setEnabled(applicationModel.isEnabled());
         rep.setAdminUrl(applicationModel.getManagementUrl());
         rep.setSurrogateAuthRequired(applicationModel.isSurrogateAuthRequired());
-        rep.setBaseUrl(applicationModel.getBaseUrl());
 
         Set<String> redirectUris = applicationModel.getApplicationUser().getRedirectUris();
         if (redirectUris != null) {
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 7840566..651db2f 100755
--- a/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java
@@ -4,8 +4,16 @@ import org.keycloak.models.Constants;
 import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.representations.idm.OAuthClientRepresentation;
 
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
@@ -26,11 +34,30 @@ public class OAuthClientManager {
 
     public OAuthClientModel create(OAuthClientRepresentation rep) {
         OAuthClientModel model = create(rep.getName());
-        model.getOAuthAgent().setEnabled(rep.isEnabled());
+        update(rep, model);
+        UserModel resourceUser = model.getOAuthAgent();
+        if (rep.getCredentials() != null) {
+            for (CredentialRepresentation cred : rep.getCredentials()) {
+                UserCredentialModel credential = new UserCredentialModel();
+                credential.setType(cred.getType());
+                credential.setValue(cred.getValue());
+                realm.updateCredential(resourceUser, credential);
+            }
+        }
         return model;
     }
 
     public void update(OAuthClientRepresentation rep, OAuthClientModel model) {
+        model.getOAuthAgent().setEnabled(rep.isEnabled());
+        List<String> redirectUris = rep.getRedirectUris();
+        if (redirectUris != null) {
+            model.getOAuthAgent().setRedirectUris(new HashSet<String>(redirectUris));
+        }
+
+        List<String> webOrigins = rep.getWebOrigins();
+        if (webOrigins != null) {
+            model.getOAuthAgent().setWebOrigins(new HashSet<String>(webOrigins));
+        }
     }
 
     public static OAuthClientRepresentation toRepresentation(OAuthClientModel model) {
@@ -38,6 +65,15 @@ public class OAuthClientManager {
         rep.setId(model.getId());
         rep.setName(model.getOAuthAgent().getLoginName());
         rep.setEnabled(model.getOAuthAgent().isEnabled());
+        Set<String> redirectUris = model.getOAuthAgent().getRedirectUris();
+        if (redirectUris != null) {
+            rep.setRedirectUris(new LinkedList<String>(redirectUris));
+        }
+
+        Set<String> webOrigins = model.getOAuthAgent().getWebOrigins();
+        if (webOrigins != null) {
+            rep.setWebOrigins(new LinkedList<String>(webOrigins));
+        }
         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 347aca8..07bf34a 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -4,6 +4,7 @@ import org.jboss.resteasy.logging.Logger;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RequiredCredentialModel;
 import org.keycloak.models.RoleModel;
@@ -13,6 +14,7 @@ import org.keycloak.models.UserModel;
 import org.keycloak.models.UserModel.RequiredAction;
 import org.keycloak.representations.idm.ApplicationRepresentation;
 import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.representations.idm.OAuthClientRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.RoleRepresentation;
 import org.keycloak.representations.idm.ScopeMappingRepresentation;
@@ -227,14 +229,6 @@ public class RealmManager {
             }
         }
 
-        if (rep.getClients() != null) {
-            for (UserRepresentation clientRep : rep.getClients()) {
-                UserModel client = createUser(newRealm, clientRep);
-                newRealm.grantRole(client, newRealm.getRole(Constants.IDENTITY_REQUESTER_ROLE));
-                userMap.put(client.getLoginName(), client);
-            }
-        }
-
         if (rep.getRoles() != null) {
             for (RoleRepresentation roleRep : rep.getRoles()) {
                 createRole(newRealm, roleRep);
@@ -247,13 +241,34 @@ public class RealmManager {
             }
         }
 
+        Map<String, ApplicationModel> appMap = null;
         if (rep.getApplications() != null) {
-            Map<String, ApplicationModel> appMap = createApplications(rep, newRealm);
+            appMap = createApplications(rep, newRealm);
             for (ApplicationModel app : appMap.values()) {
                 userMap.put(app.getApplicationUser().getLoginName(), app.getApplicationUser());
             }
         }
 
+        if (rep.getOauthClients() != null) {
+            Map<String, OAuthClientModel> oauthMap = createOAuthClients(rep, newRealm);
+            for (OAuthClientModel app : oauthMap.values()) {
+                userMap.put(app.getOAuthAgent().getLoginName(), app.getOAuthAgent());
+            }
+
+        }
+
+        // Now that all possible users are created (users, apps, and oauth clients), do role mappings and scope mappings
+
+        if (rep.getApplications() != null) {
+            ApplicationManager manager = new ApplicationManager(this);
+            for (ApplicationRepresentation appRep : rep.getApplications()) {
+                ApplicationModel model = appMap.get(appRep.getName());
+                manager.createMappings(newRealm, appRep, model);
+
+            }
+        }
+
+
         if (rep.getRoleMappings() != null) {
             for (UserRoleMappingRepresentation mapping : rep.getRoleMappings()) {
                 UserModel user = userMap.get(mapping.getUsername());
@@ -381,6 +396,17 @@ public class RealmManager {
         return appMap;
     }
 
+    protected Map<String, OAuthClientModel> createOAuthClients(RealmRepresentation realmRep, RealmModel realm) {
+        Map<String, OAuthClientModel> appMap = new HashMap<String, OAuthClientModel>();
+        OAuthClientManager manager = new OAuthClientManager(realm);
+        for (OAuthClientRepresentation rep : realmRep.getOauthClients()) {
+            OAuthClientModel app = manager.create(rep);
+            appMap.put(app.getOAuthAgent().getLoginName(), app);
+        }
+        return appMap;
+    }
+
+
     public static UserRepresentation toRepresentation(UserModel user) {
         UserRepresentation rep = new UserRepresentation();
         rep.setUsername(user.getLoginName());
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
index f7a2286..138bc3a 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java
@@ -12,6 +12,7 @@ import org.keycloak.services.managers.OAuthClientManager;
 import org.keycloak.services.managers.RealmManager;
 
 import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
@@ -46,11 +47,16 @@ public class OAuthClientResource  {
     @GET
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
-    public OAuthClientRepresentation getApplication() {
-        OAuthClientManager manager = new OAuthClientManager(realm);
+    public OAuthClientRepresentation getOAuthClient() {
         return OAuthClientManager.toRepresentation(oauthClient);
     }
 
+    @DELETE
+    @NoCache
+    public void deleteOAuthClient() {
+        realm.removeOAuthClient(oauthClient.getId());
+    }
+
     @Path("credentials")
     @PUT
     @Consumes("application/json")
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
index 408a48f..6e4101b 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java
@@ -54,12 +54,12 @@ public class OAuthClientsResource {
     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();
+        return Response.created(uriInfo.getAbsolutePathBuilder().path(oauth.getId()).build()).build();
     }
 
     @Path("{id}")
     public OAuthClientResource getOAuthClient(final @PathParam("id") String id) {
-        OAuthClientModel oauth = realm.getOAuthClient(id);
+        OAuthClientModel oauth = realm.getOAuthClientById(id);
         if (oauth == null) {
             throw new NotFoundException();
         }
diff --git a/services/src/test/java/org/keycloak/test/ApplicationModelTest.java b/services/src/test/java/org/keycloak/test/ApplicationModelTest.java
index e322481..f96e089 100755
--- a/services/src/test/java/org/keycloak/test/ApplicationModelTest.java
+++ b/services/src/test/java/org/keycloak/test/ApplicationModelTest.java
@@ -40,7 +40,6 @@ public class ApplicationModelTest extends AbstractKeycloakServerTest {
 
         realm = manager.createRealm("original");
         application = realm.addApplication("application");
-        application.setBaseUrl("http://base");
         application.setManagementUrl("http://management");
         application.setName("app-name");
         application.addRole("role-1");
@@ -83,7 +82,6 @@ public class ApplicationModelTest extends AbstractKeycloakServerTest {
 
     public static void assertEquals(ApplicationModel expected, ApplicationModel actual) {
         Assert.assertEquals(expected.getName(), actual.getName());
-        Assert.assertEquals(expected.getBaseUrl(), actual.getBaseUrl());
         Assert.assertEquals(expected.getManagementUrl(), actual.getManagementUrl());
         Assert.assertEquals(expected.getDefaultRoles(), actual.getDefaultRoles());
 
diff --git a/services/src/test/resources/testrealm-demo.json b/services/src/test/resources/testrealm-demo.json
index 9e96d21..295c70e 100755
--- a/services/src/test/resources/testrealm-demo.json
+++ b/services/src/test/resources/testrealm-demo.json
@@ -25,9 +25,9 @@
             ]
         }
     ],
-    "clients" : [
+    "oauthClients" : [
         {
-            "username" : "third-party",
+            "name" : "third-party",
             "enabled": true,
             "credentials" : [
                 { "type" : "Password",
diff --git a/testsuite/integration/src/test/resources/testrealm.json b/testsuite/integration/src/test/resources/testrealm.json
index 819e313..66809f5 100755
--- a/testsuite/integration/src/test/resources/testrealm.json
+++ b/testsuite/integration/src/test/resources/testrealm.json
@@ -32,9 +32,9 @@
             ]
         }
     ],
-    "clients" : [
+    "oauthClients" : [
         {
-            "username" : "third-party",
+            "name" : "third-party",
             "enabled": true,
             "credentials" : [
                 { "type" : "password",