keycloak-uncached

Changes

Details

diff --git a/examples/cors/angular-product-app/src/main/webapp/index.html b/examples/cors/angular-product-app/src/main/webapp/index.html
index ebd3968..2e05d7f 100755
--- a/examples/cors/angular-product-app/src/main/webapp/index.html
+++ b/examples/cors/angular-product-app/src/main/webapp/index.html
@@ -34,6 +34,24 @@
             </tbody>
         </table>
     </div>
+    <div>
+        <h2><span>Realm Roles</span></h2>
+        <button type="submit" data-ng-click="loadRoles()">load Roles</button>
+        <button type="submit" data-ng-click="addRole()">Add Role</button>
+        <button type="submit" data-ng-click="deleteRole()">Delete Role</button>
+        <table class="table" data-ng-show="roles.length > 0">
+            <thead>
+            <tr>
+                <th>Role Listing</th>
+            </tr>
+            </thead>
+            <tbody>
+            <tr data-ng-repeat="r in roles">
+                <td>{{r.name}}</a></td>
+            </tr>
+            </tbody>
+        </table>
+    </div>
 </div>
 </body>
 </html>
diff --git a/examples/cors/angular-product-app/src/main/webapp/js/app.js b/examples/cors/angular-product-app/src/main/webapp/js/app.js
index a9d879e..50b68bc 100755
--- a/examples/cors/angular-product-app/src/main/webapp/js/app.js
+++ b/examples/cors/angular-product-app/src/main/webapp/js/app.js
@@ -29,6 +29,7 @@ angular.element(document).ready(function ($http) {
 
 module.controller('GlobalCtrl', function($scope, $http) {
     $scope.products = [];
+    $scope.roles = [];
     $scope.reloadData = function() {
         $http.get("http://localhost-db:8080/database/products").success(function(data) {
             $scope.products = angular.fromJson(data);
@@ -36,6 +37,25 @@ module.controller('GlobalCtrl', function($scope, $http) {
         });
 
     };
+    $scope.loadRoles = function() {
+        $http.query("http://localhost-auth:8080/auth/admin/realms/" + keycloakAuth.realm + "/roles").success(function(data) {
+            $scope.roles = angular.fromJson(data);
+
+        });
+
+    };
+    $scope.addRole = function() {
+        $http.post("http://localhost-auth:8080/auth/admin/realms/" + keycloakAuth.realm + "/roles", {name: 'stuff'}).success(function() {
+            $scope.loadRoles();
+        });
+
+    };
+    $scope.deleteRole = function() {
+        $http.delete("http://localhost-auth:8080/auth/admin/realms/" + keycloakAuth.realm + "/roles/stuff").success(function() {
+            $scope.loadRoles();
+        });
+
+    };
     $scope.logout = logout;
 });
 
diff --git a/examples/cors/angular-product-app/src/main/webapp/keycloak.json b/examples/cors/angular-product-app/src/main/webapp/keycloak.json
index 7ea2954..6b94b27 100755
--- a/examples/cors/angular-product-app/src/main/webapp/keycloak.json
+++ b/examples/cors/angular-product-app/src/main/webapp/keycloak.json
@@ -1,5 +1,5 @@
 {
-  "realm" : "cors-realm",
+  "realm" : "cors",
   "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url" : "http://localhost-auth:8080/auth",
   "ssl-not-required" : true,
diff --git a/examples/cors/cors-realm.json b/examples/cors/cors-realm.json
index 32705aa..9b3da42 100755
--- a/examples/cors/cors-realm.json
+++ b/examples/cors/cors-realm.json
@@ -1,5 +1,5 @@
 {
-    "realm": "cors-realm",
+    "realm": "cors",
     "enabled": true,
     "accessTokenLifespan": 3000,
     "accessCodeLifespan": 10,
@@ -57,5 +57,22 @@
                 "http://localhost:8080"
             ]
         }
-    ]
+    ],
+    "applicationRoleMappings": {
+        "realm-management": [
+            {
+                "username": "bburke@redhat.com",
+                "roles": ["realm-admin"]
+            }
+        ]
+    },
+    "applicationScopeMappings": {
+        "realm-management": [
+            {
+                "client": "angular-product",
+                "roles": ["realm-admin"]
+            }
+        ]
+    }
+
 }
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/realm.js b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/realm.js
index d1fdc39..a3e61c3 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/realm.js
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/realm.js
@@ -7,69 +7,69 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, WhoAmI, Current, $
     $scope.logout = logout;
 
     $scope.auth = Auth;
+    WhoAmI.get(function(data) {
+        Auth.user = data;
+        Auth.loggedIn = true;
 
-    WhoAmI.get(function(user) {
-        Auth.user = user;
-    });
-
-    function getAccess(role) {
-        if (!Current.realm) {
-            return false;
-        }
+        function getAccess(role) {
+            if (!Current.realm) {
+                return false;
+            }
 
-        var realmAccess = Auth.user && Auth.user['realm_access'];
-        if (realmAccess) {
-            realmAccess = realmAccess[Current.realm.realm];
+            var realmAccess = Auth.user['realm_access'];
             if (realmAccess) {
-                return realmAccess.indexOf(role) >= 0;
+                realmAccess = realmAccess[Current.realm.realm];
+                if (realmAccess) {
+                    return realmAccess.indexOf(role) >= 0;
+                }
             }
+            return false;
         }
-        return false;
-    }
 
-    $scope.access = {
-        createRealm: Auth.user && Auth.user.createRealm,
+        $scope.access = {
+            createRealm: data.createRealm,
 
-        get viewRealm() {
-            return getAccess('view-realm') || this.manageRealm;
-        },
+            get viewRealm() {
+                return getAccess('view-realm') || this.manageRealm;
+            },
 
-        get viewApplications() {
-            return getAccess('view-applications') || this.manageApplications;
-        },
+            get viewApplications() {
+                return getAccess('view-applications') || this.manageApplications;
+            },
 
-        get viewClients() {
-            return getAccess('view-clients') || this.manageClients;
-        },
+            get viewClients() {
+                return getAccess('view-clients') || this.manageClients;
+            },
 
-        get viewUsers() {
-            return getAccess('view-users') || this.manageClients;
-        },
+            get viewUsers() {
+                return getAccess('view-users') || this.manageClients;
+            },
 
-        get viewAudit() {
-            return getAccess('view-audit') || this.manageClients;
-        },
+            get viewAudit() {
+                return getAccess('view-audit') || this.manageClients;
+            },
 
-        get manageRealm() {
-            return getAccess('manage-realm');
-        },
+            get manageRealm() {
+                return getAccess('manage-realm');
+            },
 
-        get manageApplications() {
-            return getAccess('manage-applications');
-        },
+            get manageApplications() {
+                return getAccess('manage-applications');
+            },
 
-        get manageClients() {
-            return getAccess('manage-clients');
-        },
+            get manageClients() {
+                return getAccess('manage-clients');
+            },
 
-        get manageUsers() {
-            return getAccess('manage-users');
-        },
+            get manageUsers() {
+                return getAccess('manage-users');
+            },
 
-        get manageAudit() {
-            return getAccess('manage-audit');
+            get manageAudit() {
+                return getAccess('manage-audit');
+            }
         }
-    }
+    });
 
     $scope.$watch(function() {
         return $location.path();
@@ -114,7 +114,7 @@ module.controller('RealmDropdownCtrl', function($scope, Realm, Current, Auth, $l
 
     $scope.showNav = function() {
         var show = Current.realms.length > 0;
-        return Auth.user && show;
+        return Auth.loggedIn && show;
     }
     $scope.refresh = function() {
          Current.refresh();
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/application-detail.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/application-detail.html
index f8380ed..9496bf3 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/application-detail.html
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/application-detail.html
@@ -76,21 +76,21 @@
                         </div>
                     </div>
                 </div>
-                <div class="form-group" data-ng-show="!application.bearerOnly">
+                <div class="form-group" data-ng-show="!application.bearerOnly && !create">
                     <label class="col-sm-2 control-label" for="baseUrl">Base URL</label>
                     <div class="col-sm-4">
                         <input class="form-control" type="text" name="baseUrl" id="baseUrl"
                                data-ng-model="application.baseUrl">
                     </div>
                 </div>
-                <div class="form-group">
+                <div class="form-group" data-ng-hide="create">
                     <label class="col-sm-2 control-label" for="adminUrl">Admin URL</label>
                     <div class="col-sm-4">
                         <input class="form-control" type="text" name="adminUrl" id="adminUrl"
                                data-ng-model="application.adminUrl">
                     </div>
                 </div>
-                <div class="form-group" data-ng-show="!application.bearerOnly">
+                <div class="form-group" data-ng-show="!application.bearerOnly && !create">
                     <label class="col-sm-2 control-label" for="newWebOrigin">Web Origin</label>
                     <div class="col-sm-4 multiple" ng-repeat="webOrigin in application.webOrigins">
                         <div class="input-group kc-item-deletable">
diff --git a/services/src/main/java/org/keycloak/services/managers/AppAuthManager.java b/services/src/main/java/org/keycloak/services/managers/AppAuthManager.java
index 2b2aa08..64adc30 100755
--- a/services/src/main/java/org/keycloak/services/managers/AppAuthManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AppAuthManager.java
@@ -3,7 +3,6 @@ package org.keycloak.services.managers;
 import org.jboss.logging.Logger;
 import org.jboss.resteasy.spi.UnauthorizedException;
 import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
 import org.keycloak.provider.ProviderSession;
 
 import javax.ws.rs.core.Cookie;
@@ -21,18 +20,16 @@ public class AppAuthManager extends AuthenticationManager {
         super(providerSession);
     }
 
-    public AuthResult authenticateRequest(RealmModel realm, UriInfo uriInfo, HttpHeaders headers) {
-        AuthResult authResult = authenticateIdentityCookie(realm, uriInfo, headers);
-        if (authResult != null) {
-            Cookie remember = headers.getCookies().get(AuthenticationManager.KEYCLOAK_REMEMBER_ME);
-            boolean rememberMe = remember != null;
-            // refresh the cookies!
-            createLoginCookie(realm, authResult.getUser(), authResult.getSession(), uriInfo, rememberMe);
-            if (rememberMe) createRememberMeCookie(realm, uriInfo);
-            return authResult;
-        } else {
-            return authenticateBearerToken(realm, uriInfo, headers);
-        }
+    @Override
+    public AuthResult authenticateIdentityCookie(RealmModel realm, UriInfo uriInfo, HttpHeaders headers) {
+        AuthResult authResult = super.authenticateIdentityCookie(realm, uriInfo, headers);
+        if (authResult == null) return null;
+        Cookie remember = headers.getCookies().get(AuthenticationManager.KEYCLOAK_REMEMBER_ME);
+        boolean rememberMe = remember != null;
+        // refresh the cookies!
+        createLoginCookie(realm, authResult.getUser(), authResult.getSession(), uriInfo, rememberMe);
+        if (rememberMe) createRememberMeCookie(realm, uriInfo);
+        return authResult;
     }
 
     public String extractAuthorizationHeaderToken(HttpHeaders headers) {
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 1bb7e52..ae760e8 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
@@ -80,6 +80,26 @@ public class ApplicationManager {
                 logger.debugv("Application: {0} webOrigin: {1}", resourceRep.getName(), webOrigin);
                 applicationModel.addWebOrigin(webOrigin);
             }
+        } else {
+            // add origins from redirect uris
+            if (resourceRep.getRedirectUris() != null) {
+                Set<String> origins = new HashSet<String>();
+                for (String redirectUri : resourceRep.getRedirectUris()) {
+                    logger.info("add redirectUri to origin: " + redirectUri);
+                    if (redirectUri.startsWith("http:")) {
+                        URI uri = URI.create(redirectUri);
+                        String origin = uri.getScheme() + "://" + uri.getHost();
+                        if (uri.getPort() != -1) {
+                            origin += ":" + uri.getPort();
+                        }
+                        logger.debugv("adding default application origin: {0}" , origin);
+                        origins.add(origin);
+                    }
+                }
+                if (origins.size() > 0) {
+                    applicationModel.setWebOrigins(origins);
+                }
+            }
         }
 
         if (resourceRep.getDefaultRoles() != null) {
diff --git a/services/src/main/java/org/keycloak/services/managers/Auth.java b/services/src/main/java/org/keycloak/services/managers/Auth.java
index 1966f43..f13cfb2 100755
--- a/services/src/main/java/org/keycloak/services/managers/Auth.java
+++ b/services/src/main/java/org/keycloak/services/managers/Auth.java
@@ -17,19 +17,10 @@ public class Auth {
     private final UserModel user;
     private final ClientModel client;
 
-    public Auth(RealmModel realm, UserModel user, ClientModel client) {
-        this.cookie = true;
-        this.realm = realm;
-        this.token = null;
-
-        this.user = user;
-        this.client = client;
-    }
-
-    public Auth(AccessToken token, UserModel user, ClientModel client) {
-        this.cookie = false;
+    public Auth(RealmModel realm, AccessToken token, UserModel user, ClientModel client, boolean cookie) {
+        this.cookie = cookie;
         this.token = token;
-        this.realm = null;
+        this.realm = realm;
 
         this.user = user;
         this.client = client;
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index c23858d..513d9c0 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -221,7 +221,7 @@ public class AuthenticationManager {
                 return null;
             }
 
-            return new AuthResult(user, session);
+            return new AuthResult(user, session, token);
         } catch (VerificationException e) {
             logger.info("Failed to verify identity token", e);
         }
@@ -361,10 +361,12 @@ public class AuthenticationManager {
     public class AuthResult {
         private final UserModel user;
         private final UserSessionModel session;
+        private final AccessToken token;
 
-        public AuthResult(UserModel user, UserSessionModel session) {
+        public AuthResult(UserModel user, UserSessionModel session, AccessToken token) {
             this.user = user;
             this.session = session;
+            this.token = token;
         }
 
         public UserSessionModel getSession() {
@@ -374,6 +376,10 @@ public class AuthenticationManager {
         public UserModel getUser() {
             return user;
         }
+
+        public AccessToken getToken() {
+            return token;
+        }
     }
 
 }
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 1543087..66a49e0 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -103,7 +103,8 @@ public class RealmManager {
     }
 
     protected void setupAdminConsole(RealmModel realm) {
-        ApplicationModel adminConsole = new ApplicationManager(this).createApplication(realm, Constants.ADMIN_CONSOLE_APPLICATION);
+        ApplicationModel adminConsole = realm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION);
+        if (adminConsole == null) adminConsole = new ApplicationManager(this).createApplication(realm, Constants.ADMIN_CONSOLE_APPLICATION);
         String baseUrl = contextPath + "/admin/" + realm.getName() + "/console";
         adminConsole.setBaseUrl(baseUrl + "/index.html");
         adminConsole.setEnabled(true);
@@ -113,12 +114,10 @@ public class RealmManager {
         RoleModel adminRole;
         if (realm.getName().equals(Config.getAdminRealm())) {
             adminRole = realm.getRole(AdminRoles.ADMIN);
+            realm.addScopeMapping(adminConsole, adminRole);
         } else {
-            ApplicationModel realmApp = realm.getApplicationByName(getRealmAdminApplicationName(realm));
-            adminRole = realmApp.getRole(AdminRoles.REALM_ADMIN);
-
+            // security roles are defined in application for the realm.
         }
-        realm.addScopeMapping(adminConsole, adminRole);
     }
 
     public String getMasterRealmAdminApplicationName(RealmModel realm) {
@@ -265,7 +264,11 @@ public class RealmManager {
 
         ApplicationManager applicationManager = new ApplicationManager(new RealmManager(identitySession));
 
-        ApplicationModel realmAdminApp = applicationManager.createApplication(realm, getRealmAdminApplicationName(realm));
+        String realmAdminApplicationName = getRealmAdminApplicationName(realm);
+        ApplicationModel realmAdminApp = realm.getApplicationByName(realmAdminApplicationName);
+        if (realmAdminApp == null) {
+            realmAdminApp = applicationManager.createApplication(realm, realmAdminApplicationName);
+        }
         RoleModel adminRole = realmAdminApp.addRole(AdminRoles.REALM_ADMIN);
         realmAdminApp.setBearerOnly(true);
 
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index d641441..b232de5 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -145,9 +145,16 @@ public class AccountService {
         account = providers.getProvider(AccountProvider.class).setRealm(realm).setUriInfo(uriInfo);
 
         boolean passwordUpdateSupported = false;
-        AuthenticationManager.AuthResult authResult = authManager.authenticateRequest(realm, uriInfo, headers);
+        AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
+        if (authResult != null) {
+            auth = new Auth(realm, authResult.getToken(), authResult.getUser(), application, true);
+        } else {
+            authResult = authManager.authenticateBearerToken(realm, uriInfo, headers);
+            if (authResult != null) {
+                auth = new Auth(realm, authResult.getToken(), authResult.getUser(), application, false);
+            }
+        }
         if (authResult != null) {
-            auth = new Auth(realm, authResult.getUser(), application);
             if (authResult.getSession() != null) {
                 authResult.getSession().associateClient(application);
             }
@@ -208,7 +215,7 @@ public class AccountService {
         } else if (types.contains(MediaType.APPLICATION_JSON_TYPE)) {
             requireOneOf(AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_PROFILE);
 
-            return Cors.add(request, Response.ok(ModelToRepresentation.toRepresentation(auth.getUser()))).auth().allowedOrigins(auth.getClient()).build();
+            return Cors.add(request, Response.ok(ModelToRepresentation.toRepresentation(auth.getUser()))).auth().allowedOrigins(auth.getToken()).build();
         } else {
             return Response.notAcceptable(Variant.VariantListBuilder.newInstance().mediaTypes(MediaType.TEXT_HTML_TYPE, MediaType.APPLICATION_JSON_TYPE).build()).build();
         }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java
new file mode 100755
index 0000000..dcfad7c
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java
@@ -0,0 +1,83 @@
+package org.keycloak.services.resources.admin;
+
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.AccessToken;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class AdminAuth {
+
+    private final RealmModel realm;
+    private final AccessToken token;
+    private final UserModel user;
+    private final ClientModel client;
+
+    public AdminAuth(RealmModel realm, AccessToken token, UserModel user, ClientModel client) {
+        this.token = token;
+        this.realm = realm;
+
+        this.user = user;
+        this.client = client;
+    }
+
+    public RealmModel getRealm() {
+        return realm;
+    }
+
+    public UserModel getUser() {
+        return user;
+    }
+
+    public ClientModel getClient() {
+        return client;
+    }
+
+    public AccessToken getToken() {
+        return token;
+    }
+
+
+    public boolean hasRealmRole(String role) {
+        if (client instanceof ApplicationModel) {
+            RoleModel roleModel = realm.getRole(role);
+            return realm.hasRole(user, roleModel) && realm.hasScope(client, roleModel);
+        } else {
+            AccessToken.Access access = token.getRealmAccess();
+            return access != null && access.isUserInRole(role);
+        }
+    }
+
+    public boolean hasOneOfRealmRole(String... roles) {
+        for (String r : roles) {
+            if (hasRealmRole(r)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean hasAppRole(ApplicationModel app, String role) {
+        if (client instanceof ApplicationModel) {
+            RoleModel roleModel = app.getRole(role);
+            return realm.hasRole(user, roleModel) && realm.hasScope(client, roleModel);
+        } else {
+            AccessToken.Access access = token.getResourceAccess(app.getName());
+            return access != null && access.isUserInRole(role);
+        }
+    }
+
+    public boolean hasOneOfAppRole(ApplicationModel app, String... roles) {
+        for (String r : roles) {
+            if (hasAppRole(app, r)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
index 1c01d84..1c36506 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
@@ -1,11 +1,15 @@
 package org.keycloak.services.resources.admin;
 
 import org.jboss.logging.Logger;
+import org.jboss.resteasy.spi.DefaultOptionsMethodException;
+import org.jboss.resteasy.spi.HttpRequest;
+import org.jboss.resteasy.spi.HttpResponse;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.jboss.resteasy.spi.UnauthorizedException;
 import org.keycloak.jose.jws.JWSInput;
 import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
@@ -17,10 +21,12 @@ import org.keycloak.services.managers.Auth;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.managers.TokenManager;
+import org.keycloak.services.resources.Cors;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
+import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
@@ -39,6 +45,12 @@ public class AdminRoot {
     @Context
     protected UriInfo uriInfo;
 
+    @Context
+    protected HttpRequest request;
+
+    @Context
+    protected HttpResponse response;
+
     protected AppAuthManager authManager;
     protected TokenManager tokenManager;
 
@@ -101,7 +113,7 @@ public class AdminRoot {
     }
 
 
-    protected Auth authenticateRealmAdminRequest(HttpHeaders headers) {
+    protected AdminAuth authenticateRealmAdminRequest(HttpHeaders headers) {
         String tokenString = authManager.extractAuthorizationHeaderToken(headers);
         if (tokenString == null) throw new UnauthorizedException("Bearer");
         JWSInput input = new JWSInput(tokenString);
@@ -123,14 +135,13 @@ public class AdminRoot {
             throw new UnauthorizedException("Bearer");
         }
 
-        ApplicationModel consoleApp = realm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION);
-        if (consoleApp == null) {
-            throw new NotFoundException("Could not find admin console application");
-        }
-        Auth auth = new Auth(realm, authResult.getUser(), consoleApp);
-        return auth;
+        ClientModel client = realm.findClient(token.getIssuedFor());
+        if (client == null) {
+            throw new NotFoundException("Could not find client for authorization");
 
+        }
 
+        return new AdminAuth(realm, authResult.getToken(), authResult.getUser(), client);
     }
 
     public static UriBuilder realmsUrl(UriInfo uriInfo) {
@@ -143,10 +154,19 @@ public class AdminRoot {
 
     @Path("realms")
     public RealmsAdminResource getRealmsAdmin(@Context final HttpHeaders headers) {
-        Auth auth = authenticateRealmAdminRequest(headers);
+        if (request.getHttpMethod().equalsIgnoreCase("OPTIONS")) {
+            logger.info("*** CORS ADMIN PREFLIGHT!!!!");
+            Response response = Cors.add(request, Response.ok()).preflight().allowedMethods("GET", "PUT", "POST", "DELETE").auth().build();
+            throw new WebApplicationException(response);
+        }
+
+        AdminAuth auth = authenticateRealmAdminRequest(headers);
         if (auth != null) {
             logger.info("authenticated admin access for: " + auth.getUser().getLoginName());
         }
+
+        Cors.add(request).allowedOrigins(auth.getToken()).allowedMethods("GET", "PUT", "POST", "DELETE").auth().build(response);
+
         RealmsAdminResource adminResource = new RealmsAdminResource(auth, tokenManager);
         ResteasyProviderFactory.getInstance().injectProperties(adminResource);
         //resourceContext.initResource(adminResource);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java
index fc0d174..89d9ef3 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java
@@ -1,95 +1,95 @@
-package org.keycloak.services.resources.admin;
-
-import org.keycloak.models.AdminRoles;
-import org.keycloak.models.ApplicationModel;
-import org.keycloak.services.ForbiddenException;
-import org.keycloak.services.managers.Auth;
-
-import javax.ws.rs.WebApplicationException;
-
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class RealmAuth {
-
-    private Resource resource;
-
-    public enum Resource {
-        APPLICATION, CLIENT, USER, REALM, AUDIT
-    }
-
-    private Auth auth;
-    private ApplicationModel realmAdminApp;
-
-    public RealmAuth(Auth auth, ApplicationModel realmAdminApp) {
-        this.auth = auth;
-        this.realmAdminApp = realmAdminApp;
-    }
-
-    public RealmAuth init(Resource resource) {
-        this.resource = resource;
-        return this;
-    }
-
-    public void requireAny() {
-        if (!auth.hasOneOfAppRole(realmAdminApp, AdminRoles.ALL_REALM_ROLES)) {
-            throw new ForbiddenException();
-        }
-    }
-
-    public boolean hasView() {
-        return auth.hasOneOfAppRole(realmAdminApp, getViewRole(resource), getManageRole(resource));
-    }
-
-    public boolean hasManage() {
-        return auth.hasOneOfAppRole(realmAdminApp, getManageRole(resource));
-    }
-
-    public void requireView() {
-        if (!hasView()) {
-            throw new ForbiddenException();
-        }
-    }
-
-    public void requireManage() {
-        if (!hasManage()) {
-            throw new ForbiddenException();
-        }
-    }
-
-    private String getViewRole(Resource resource) {
-        switch (resource) {
-            case APPLICATION:
-                return AdminRoles.VIEW_APPLICATIONS;
-            case CLIENT:
-                return AdminRoles.VIEW_CLIENTS;
-            case USER:
-                return AdminRoles.VIEW_USERS;
-            case REALM:
-                return AdminRoles.VIEW_REALM;
-            case AUDIT:
-                return AdminRoles.VIEW_AUDIT;
-            default:
-                throw new IllegalStateException();
-        }
-    }
-
-    private String getManageRole(Resource resource) {
-        switch (resource) {
-            case APPLICATION:
-                return AdminRoles.MANAGE_APPLICATIONS;
-            case CLIENT:
-                return AdminRoles.MANAGE_CLIENTS;
-            case USER:
-                return AdminRoles.MANAGE_USERS;
-            case REALM:
-                return AdminRoles.MANAGE_REALM;
-            case AUDIT:
-                return AdminRoles.MANAGE_AUDIT;
-            default:
-                throw new IllegalStateException();
-        }
-    }
-
-}
+package org.keycloak.services.resources.admin;
+
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.services.ForbiddenException;
+import org.keycloak.services.managers.Auth;
+
+import javax.ws.rs.WebApplicationException;
+
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class RealmAuth {
+
+    private Resource resource;
+
+    public enum Resource {
+        APPLICATION, CLIENT, USER, REALM, AUDIT
+    }
+
+    private AdminAuth auth;
+    private ApplicationModel realmAdminApp;
+
+    public RealmAuth(AdminAuth auth, ApplicationModel realmAdminApp) {
+        this.auth = auth;
+        this.realmAdminApp = realmAdminApp;
+    }
+
+    public RealmAuth init(Resource resource) {
+        this.resource = resource;
+        return this;
+    }
+
+    public void requireAny() {
+        if (!auth.hasOneOfAppRole(realmAdminApp, AdminRoles.ALL_REALM_ROLES)) {
+            throw new ForbiddenException();
+        }
+    }
+
+    public boolean hasView() {
+        return auth.hasOneOfAppRole(realmAdminApp, getViewRole(resource), getManageRole(resource));
+    }
+
+    public boolean hasManage() {
+        return auth.hasOneOfAppRole(realmAdminApp, getManageRole(resource));
+    }
+
+    public void requireView() {
+        if (!hasView()) {
+            throw new ForbiddenException();
+        }
+    }
+
+    public void requireManage() {
+        if (!hasManage()) {
+            throw new ForbiddenException();
+        }
+    }
+
+    private String getViewRole(Resource resource) {
+        switch (resource) {
+            case APPLICATION:
+                return AdminRoles.VIEW_APPLICATIONS;
+            case CLIENT:
+                return AdminRoles.VIEW_CLIENTS;
+            case USER:
+                return AdminRoles.VIEW_USERS;
+            case REALM:
+                return AdminRoles.VIEW_REALM;
+            case AUDIT:
+                return AdminRoles.VIEW_AUDIT;
+            default:
+                throw new IllegalStateException();
+        }
+    }
+
+    private String getManageRole(Resource resource) {
+        switch (resource) {
+            case APPLICATION:
+                return AdminRoles.MANAGE_APPLICATIONS;
+            case CLIENT:
+                return AdminRoles.MANAGE_CLIENTS;
+            case USER:
+                return AdminRoles.MANAGE_USERS;
+            case REALM:
+                return AdminRoles.MANAGE_REALM;
+            case AUDIT:
+                return AdminRoles.MANAGE_AUDIT;
+            default:
+                throw new IllegalStateException();
+        }
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
index 681eb89..efecbf9 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
@@ -46,10 +46,10 @@ import java.util.Map;
  */
 public class RealmsAdminResource {
     protected static final Logger logger = Logger.getLogger(RealmsAdminResource.class);
-    protected Auth auth;
+    protected AdminAuth auth;
     protected TokenManager tokenManager;
 
-    public RealmsAdminResource(Auth auth, TokenManager tokenManager) {
+    public RealmsAdminResource(AdminAuth auth, TokenManager tokenManager) {
         this.auth = auth;
         this.tokenManager = tokenManager;
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/Cors.java b/services/src/main/java/org/keycloak/services/resources/Cors.java
index 9dbcd39..c77b001 100755
--- a/services/src/main/java/org/keycloak/services/resources/Cors.java
+++ b/services/src/main/java/org/keycloak/services/resources/Cors.java
@@ -8,14 +8,18 @@ import java.util.concurrent.TimeUnit;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.ResponseBuilder;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.spi.HttpRequest;
+import org.jboss.resteasy.spi.HttpResponse;
 import org.keycloak.models.ClientModel;
+import org.keycloak.representations.AccessToken;
 import org.keycloak.util.CollectionUtil;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
 public class Cors {
+    protected static final Logger logger = Logger.getLogger(Cors.class);
 
     public static final long DEFAULT_MAX_AGE = TimeUnit.HOURS.toSeconds(1);
     public static final String DEFAULT_ALLOW_METHODS = "GET, HEAD, OPTIONS";
@@ -33,7 +37,7 @@ public class Cors {
 
 
     private HttpRequest request;
-    private ResponseBuilder response;
+    private ResponseBuilder builder;
     private Set<String> allowedOrigins;
     private Set<String> allowedMethods;
     private Set<String> exposedHeaders;
@@ -43,13 +47,21 @@ public class Cors {
 
     public Cors(HttpRequest request, ResponseBuilder response) {
         this.request = request;
-        this.response = response;
+        this.builder = response;
+    }
+
+    public Cors(HttpRequest request) {
+        this.request = request;
     }
 
     public static Cors add(HttpRequest request, ResponseBuilder response) {
         return new Cors(request, response);
     }
 
+    public static Cors add(HttpRequest request) {
+        return new Cors(request);
+    }
+
     public Cors preflight() {
         preflight = true;
         return this;
@@ -67,6 +79,13 @@ public class Cors {
         return this;
     }
 
+    public Cors allowedOrigins(AccessToken token) {
+        if (token != null) {
+            allowedOrigins = token.getAllowedOrigins();
+        }
+        return this;
+    }
+
     public Cors allowedMethods(String... allowedMethods) {
         this.allowedMethods = new HashSet<String>(Arrays.asList(allowedMethods));
         return this;
@@ -80,35 +99,69 @@ public class Cors {
     public Response build() {
         String origin = request.getHttpHeaders().getRequestHeaders().getFirst(ORIGIN_HEADER);
         if (origin == null) {
-            return response.build();
+            return builder.build();
         }
 
         if (!preflight && (allowedOrigins == null || !allowedOrigins.contains(origin))) {
-            return response.build();
+            return builder.build();
         }
 
-        response.header(ACCESS_CONTROL_ALLOW_ORIGIN, origin);
+        builder.header(ACCESS_CONTROL_ALLOW_ORIGIN, origin);
 
         if (allowedMethods != null) {
-            response.header(ACCESS_CONTROL_ALLOW_METHODS, CollectionUtil.join(allowedMethods));
+            builder.header(ACCESS_CONTROL_ALLOW_METHODS, CollectionUtil.join(allowedMethods));
         } else {
-            response.header(ACCESS_CONTROL_ALLOW_METHODS, DEFAULT_ALLOW_METHODS);
+            builder.header(ACCESS_CONTROL_ALLOW_METHODS, DEFAULT_ALLOW_METHODS);
         }
 
         if (exposedHeaders != null) {
-            response.header(ACCESS_CONTROL_EXPOSE_HEADERS, CollectionUtil.join(exposedHeaders));
+            builder.header(ACCESS_CONTROL_EXPOSE_HEADERS, CollectionUtil.join(exposedHeaders));
         }
 
-        response.header(ACCESS_CONTROL_ALLOW_CREDENTIALS, Boolean.toString(auth));
+        builder.header(ACCESS_CONTROL_ALLOW_CREDENTIALS, Boolean.toString(auth));
         if (auth) {
-            response.header(ACCESS_CONTROL_ALLOW_HEADERS, String.format("%s, %s", DEFAULT_ALLOW_HEADERS, AUTHORIZATION_HEADER));
+            builder.header(ACCESS_CONTROL_ALLOW_HEADERS, String.format("%s, %s", DEFAULT_ALLOW_HEADERS, AUTHORIZATION_HEADER));
+        } else {
+            builder.header(ACCESS_CONTROL_ALLOW_HEADERS, DEFAULT_ALLOW_HEADERS);
+        }
+
+        builder.header(ACCESS_CONTROL_MAX_AGE, DEFAULT_MAX_AGE);
+
+        return builder.build();
+    }
+    public void build(HttpResponse response) {
+        logger.info("build CORS");
+        String origin = request.getHttpHeaders().getRequestHeaders().getFirst(ORIGIN_HEADER);
+        if (origin == null) {
+            logger.info("No origin returning");
+            return;
+        }
+
+        if (!preflight && (allowedOrigins == null || !allowedOrigins.contains(origin))) {
+            logger.info("!preflight and no origin");
+            return;
+        }
+        logger.info("build CORS headers and return");
+        response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_ORIGIN, origin);
+
+        if (allowedMethods != null) {
+            response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_METHODS, CollectionUtil.join(allowedMethods));
         } else {
-            response.header(ACCESS_CONTROL_ALLOW_HEADERS, DEFAULT_ALLOW_HEADERS);
+            response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_METHODS, DEFAULT_ALLOW_METHODS);
+        }
+
+        if (exposedHeaders != null) {
+            response.getOutputHeaders().add(ACCESS_CONTROL_EXPOSE_HEADERS, CollectionUtil.join(exposedHeaders));
         }
 
-        response.header(ACCESS_CONTROL_MAX_AGE, DEFAULT_MAX_AGE);
+        response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_CREDENTIALS, Boolean.toString(auth));
+        if (auth) {
+            response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_HEADERS, String.format("%s, %s", DEFAULT_ALLOW_HEADERS, AUTHORIZATION_HEADER));
+        } else {
+            response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_HEADERS, DEFAULT_ALLOW_HEADERS);
+        }
 
-        return response.build();
+        response.getOutputHeaders().add(ACCESS_CONTROL_MAX_AGE, DEFAULT_MAX_AGE);
     }
 
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/TokenService.java b/services/src/main/java/org/keycloak/services/resources/TokenService.java
index 0a5b33c..40af5a4 100755
--- a/services/src/main/java/org/keycloak/services/resources/TokenService.java
+++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java
@@ -534,7 +534,7 @@ public class TokenService {
     @OPTIONS
     @Produces("application/json")
     public Response accessCodeToTokenPreflight() {
-        logger.info("cors request from: " + request.getHttpHeaders().getRequestHeaders().getFirst("Origin"));
+        logger.debugv("cors request from: {0}" , request.getHttpHeaders().getRequestHeaders().getFirst("Origin"));
         return Cors.add(request, Response.ok()).auth().preflight().build();
     }