keycloak-aplcache
Changes
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java 2(+1 -1)
testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeImportRoleTest.java 10(+5 -5)
testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java 10(+5 -5)
Details
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
index f1a4f49..782069a 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
@@ -7,6 +7,17 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location
$http.get('/auth/rest/admin/whoami').success(function(data, status) {
Auth.user = data;
Auth.loggedIn = true;
+
+ Auth.hasAccess = function(realm, role) {
+ var realmAccess = Auth.user['realm_access'];
+ if (realmAccess) {
+ realmAccess = realmAccess[realm];
+ if (realmAccess) {
+ return realmAccess.indexOf(role) >= 0;
+ }
+ }
+ return false;
+ }
})
.error(function(data, status) {
Auth.loggedIn = false;
@@ -62,7 +73,7 @@ module.controller('RealmDropdownCtrl', function($scope, Realm, Current, Auth, $l
}
});
-module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $http, $location, Dialog, Notifications) {
+module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $http, $location, Dialog, Notifications, Auth) {
console.log('RealmCreateCtrl');
Current.realm = null;
@@ -131,8 +142,14 @@ module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $
Current.realm = Current.realms[i];
}
}
- $location.url("/realms/" + realmCopy.realm);
- Notifications.success("The realm has been created.");
+
+ $http.get('/auth/rest/admin/whoami').success(function(data, status) {
+ Auth.user = data;
+ console.log("reloaded auth");
+
+ $location.url("/realms/" + realmCopy.realm);
+ Notifications.success("The realm has been created.");
+ });
});
});
};
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/menu.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/menu.html
index 2aeab7c..275cdae 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/menu.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/menu.html
@@ -33,7 +33,7 @@
</li>
</ul>
</li>
- <li class="active pull-right" data-ng-show="auth.loggedIn">
+ <li class="active pull-right" data-ng-show="auth.loggedIn && auth.user.admin">
<a class="button primary" href="#/create/realm" data-ng-class="path[0] == 'create' && path[1] == 'realm' && 'active'"
data-ng-show="auth.loggedIn">Add Realm</a>
</li>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-detail.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-detail.html
index da8375a..d51f280 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-detail.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-detail.html
@@ -7,98 +7,104 @@
<li><a href="#/realms/{{realm.realm}}">Settings</a></li>
<li class="active">General</li>
</ol>
- <h2 class="pull-left" data-ng-show="createRealm">Add Realm</h2>
- <h2 data-ng-hide="createRealm"><span>{{realm.realm}}</span> General Settings</h2>
- <p class="subtitle" data-ng-show="createRealm"><span class="required">*</span> Required fields</p>
- <form class="form-horizontal" name="realmForm" novalidate>
- <fieldset>
- <legend class="aj-collapse open"><span class="text">Required Settings</span></legend>
- <div class="form-group">
- <label class="col-sm-2 control-label" for="name">Name <span class="required" data-ng-show="createRealm">*</span></label>
+ <div data-ng-show="auth.hasAccess(realm.realm, 'manage-realm')">
+ <h2 class="pull-left" data-ng-show="createRealm">Add Realm</h2>
+ <h2 data-ng-hide="createRealm"><span>{{realm.realm}}</span> General Settings</h2>
+ <p class="subtitle" data-ng-show="createRealm"><span class="required">*</span> Required fields</p>
+ <form class="form-horizontal" name="realmForm" novalidate>
+ <fieldset>
+ <legend class="aj-collapse open"><span class="text">Required Settings</span></legend>
+ <div class="form-group">
+ <label class="col-sm-2 control-label" for="name">Name <span class="required" data-ng-show="createRealm">*</span></label>
- <div class="col-sm-4">
- <input class="form-control" type="text" id="name" name="name" data-ng-model="realm.realm" autofocus required>
+ <div class="col-sm-4">
+ <input class="form-control" type="text" id="name" name="name" data-ng-model="realm.realm" autofocus required>
+ </div>
</div>
- </div>
- <div class="form-group">
- <label class="col-sm-2 control-label" for="enabled">Enabled</label>
- <div class="col-sm-4">
- <input ng-model="realm.enabled" name="enabled" id="enabled" onoffswitch />
+ <div class="form-group">
+ <label class="col-sm-2 control-label" for="enabled">Enabled</label>
+ <div class="col-sm-4">
+ <input ng-model="realm.enabled" name="enabled" id="enabled" onoffswitch />
+ </div>
</div>
- </div>
- </fieldset>
- <fieldset>
- <legend><span class="text">Login Options</span></legend>
- <div class="form-group">
- <label class="col-sm-2 control-label" for="social">Social login</label>
- <div class="col-sm-4">
- <input ng-model="realm.social" name="social" id="social" onoffswitch />
+ </fieldset>
+ <fieldset>
+ <legend><span class="text">Login Options</span></legend>
+ <div class="form-group">
+ <label class="col-sm-2 control-label" for="social">Social login</label>
+ <div class="col-sm-4">
+ <input ng-model="realm.social" name="social" id="social" onoffswitch />
+ </div>
</div>
- </div>
- <div class="form-group" data-ng-show="realm.social">
- <label class="col-sm-2 control-label" for="updateProfileOnInitialSocialLogin">Update profile on first social login</label>
- <div class="col-sm-4">
- <input ng-model="realm.updateProfileOnInitialSocialLogin" name="updateProfileOnInitialSocialLogin" id="updateProfileOnInitialSocialLogin" onoffswitch />
+ <div class="form-group" data-ng-show="realm.social">
+ <label class="col-sm-2 control-label" for="updateProfileOnInitialSocialLogin">Update profile on first social login</label>
+ <div class="col-sm-4">
+ <input ng-model="realm.updateProfileOnInitialSocialLogin" name="updateProfileOnInitialSocialLogin" id="updateProfileOnInitialSocialLogin" onoffswitch />
+ </div>
</div>
- </div>
- <div class="form-group">
- <label for="registrationAllowed" class="col-sm-2 control-label">User registration</label>
- <div class="col-sm-4">
- <input ng-model="realm.registrationAllowed" name="registrationAllowed" id="registrationAllowed" onoffswitch />
+ <div class="form-group">
+ <label for="registrationAllowed" class="col-sm-2 control-label">User registration</label>
+ <div class="col-sm-4">
+ <input ng-model="realm.registrationAllowed" name="registrationAllowed" id="registrationAllowed" onoffswitch />
+ </div>
</div>
- </div>
- <div class="form-group">
- <label for="resetPasswordAllowed" class="col-sm-2 control-label">Reset password</label>
- <div class="col-sm-4">
- <input ng-model="realm.resetPasswordAllowed" name="resetPasswordAllowed" id="resetPasswordAllowed" onoffswitch />
+ <div class="form-group">
+ <label for="resetPasswordAllowed" class="col-sm-2 control-label">Reset password</label>
+ <div class="col-sm-4">
+ <input ng-model="realm.resetPasswordAllowed" name="resetPasswordAllowed" id="resetPasswordAllowed" onoffswitch />
+ </div>
</div>
- </div>
- <div class="form-group">
- <label for="verifyEmail" class="col-sm-2 control-label">Verify email</label>
- <div class="col-sm-4">
- <input ng-model="realm.verifyEmail" name="verifyEmail" id="verifyEmail" onoffswitch />
+ <div class="form-group">
+ <label for="verifyEmail" class="col-sm-2 control-label">Verify email</label>
+ <div class="col-sm-4">
+ <input ng-model="realm.verifyEmail" name="verifyEmail" id="verifyEmail" onoffswitch />
+ </div>
</div>
- </div>
- <div class="form-group">
- <label for="requireSsl" class="col-sm-2 control-label">Require SSL</label>
- <div class="col-sm-4">
- <input ng-model="realm.requireSsl" name="requireSsl" id="requireSsl" onoffswitch />
+ <div class="form-group">
+ <label for="requireSsl" class="col-sm-2 control-label">Require SSL</label>
+ <div class="col-sm-4">
+ <input ng-model="realm.requireSsl" name="requireSsl" id="requireSsl" onoffswitch />
+ </div>
</div>
- </div>
- </fieldset>
- <fieldset>
- <legend><span class="text">Optional Settings</span></legend>
- <div class="form-group">
- <label class="col-sm-2 control-label" for="loginTheme">Login Theme</label>
- <div class="col-sm-4">
- <select kc-select id="loginTheme"
- data-kc-placeholder="Select one..."
- data-kc-model="realm.loginTheme"
- data-kc-options="serverInfo.themes.login">
- </select>
+ </fieldset>
+ <fieldset>
+ <legend><span class="text">Optional Settings</span></legend>
+ <div class="form-group">
+ <label class="col-sm-2 control-label" for="loginTheme">Login Theme</label>
+ <div class="col-sm-4">
+ <select kc-select id="loginTheme"
+ data-kc-placeholder="Select one..."
+ data-kc-model="realm.loginTheme"
+ data-kc-options="serverInfo.themes.login">
+ </select>
+ </div>
</div>
- </div>
- <div class="form-group">
- <label class="col-sm-2 control-label" for="accountTheme">Account Theme</label>
- <div class="col-sm-4">
- <select kc-select id="accountTheme"
- data-kc-placeholder="Select one..."
- data-kc-model="realm.accountTheme"
- data-kc-options="serverInfo.themes.account">
- </select>
+ <div class="form-group">
+ <label class="col-sm-2 control-label" for="accountTheme">Account Theme</label>
+ <div class="col-sm-4">
+ <select kc-select id="accountTheme"
+ data-kc-placeholder="Select one..."
+ data-kc-model="realm.accountTheme"
+ data-kc-options="serverInfo.themes.account">
+ </select>
+ </div>
</div>
+ </fieldset>
+
+ <div class="pull-right form-actions" data-ng-show="createRealm">
+ <button kc-cancel data-ng-click="cancel()">Cancel</button>
+ <button kc-save data-ng-show="changed">Save</button>
+ </div>
+ <div class="pull-right form-actions" data-ng-show="!createRealm">
+ <button kc-reset data-ng-show="changed">Clear changes</button>
+ <button kc-save data-ng-show="changed">Save</button>
+ <button kc-delete data-ng-click="remove()" data-ng-hide="changed">Delete</button>
</div>
- </fieldset>
+ </form>
+ </div>
+ <div data-ng-hide="auth.hasAccess(realm.realm, 'manage-realm')">
+ <h2 ><span>{{realm.realm}}</span></h2>
+ </div>
- <div class="pull-right form-actions" data-ng-show="createRealm">
- <button kc-cancel data-ng-click="cancel()">Cancel</button>
- <button kc-save data-ng-show="changed">Save</button>
- </div>
- <div class="pull-right form-actions" data-ng-show="!createRealm">
- <button kc-reset data-ng-show="changed">Clear changes</button>
- <button kc-save data-ng-show="changed">Save</button>
- <button kc-delete data-ng-click="remove()" data-ng-hide="changed">Delete</button>
- </div>
- </form>
</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 81c9fae..6bd704c 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
@@ -1,10 +1,9 @@
<ul data-ng-hide="createRealm">
- <li data-ng-class="((!path[2] || path[1] == 'role' || path[2] == 'roles' || path[2] == 'token-settings' ||
+ <li data-ng-show="auth.hasAccess(realm.realm, 'manage-realm')" data-ng-class="((!path[2] || path[1] == 'role' || path[2] == 'roles' || path[2] == 'token-settings' ||
path[2] == 'social-settings' || path[2] == 'required-credentials' || path[2] == 'default-roles' || path[2] == 'registration-settings' ||
path[2] == 'keys-settings' || path[2] == 'smtp-settings') && path[3] != 'applications') && 'active'"><a href="#/realms/{{realm.realm}}">Settings</a></li>
- <li data-ng-class="(path[2] == 'users' || path[1] == 'user') && 'active'"><a href="#/realms/{{realm.realm}}/users">Users</a>
+ <li data-ng-show="auth.hasAccess(realm.realm, 'manage-users')" data-ng-class="(path[2] == 'users' || path[1] == 'user') && 'active'"><a href="#/realms/{{realm.realm}}/users">Users</a>
</li>
- <li data-ng-class="(path[2] == 'applications' || path[1] == 'application' || path[3] == 'applications') && 'active'"><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
- <li data-ng-class="(path[2] == 'oauth-clients' || path[1] == 'oauth-client') && 'active'"><a href="#/realms/{{realm.realm}}/oauth-clients">OAuth Clients</a></li>
-</ul>
-
+ <li data-ng-show="auth.hasAccess(realm.realm, 'manage-applications')" data-ng-class="(path[2] == 'applications' || path[1] == 'application' || path[3] == 'applications') && 'active'"><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
+ <li data-ng-show="auth.hasAccess(realm.realm, 'manage-clients')" data-ng-class="(path[2] == 'oauth-clients' || path[1] == 'oauth-client') && 'active'"><a href="#/realms/{{realm.realm}}/oauth-clients">OAuth Clients</a></li>
+</ul>
\ No newline at end of file
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/templates/kc-navigation.html b/admin-ui/src/main/resources/META-INF/resources/admin/templates/kc-navigation.html
index cfb83b2..aed507b 100644
--- a/admin-ui/src/main/resources/META-INF/resources/admin/templates/kc-navigation.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/templates/kc-navigation.html
@@ -1,10 +1,10 @@
<ul class="nav nav-tabs nav-tabs-pf">
<li ng-class="{active: kcCurrent == 'general'}"><a href="#/realms/{{kcRealm}}">General</a></li>
- <li ng-class="{active: kcCurrent == 'social'}" data-ng-show="kcSocial"><a href="#/realms/{{kcRealm}}/social-settings">Social</a></li>
- <li ng-class="{active: kcCurrent == 'roles'}"><a href="#/realms/{{kcRealm}}/roles">Roles</a></li>
- <li ng-class="{active: kcCurrent == 'defRoles'}"><a href="#/realms/{{kcRealm}}/default-roles">Default Roles</a></li>
- <li ng-class="{active: kcCurrent == 'credentials'}"><a href="#/realms/{{kcRealm}}/required-credentials">Credentials</a></li>
- <li ng-class="{active: kcCurrent == 'token'}"><a href="#/realms/{{kcRealm}}/token-settings">Token</a></li>
- <li ng-class="{active: kcCurrent == 'keys'}"><a href="#/realms/{{kcRealm}}/keys-settings">Keys</a></li>
- <li ng-class="{active: kcCurrent == 'email'}"><a href="#/realms/{{kcRealm}}/smtp-settings">Email</a></li>
-</ul>
+ <li ng-class="{active: kcCurrent == 'social'}" data-ng-show="kcSocial && auth.hasAccess(realm.realm, 'manage-realm')"><a href="#/realms/{{kcRealm}}/social-settings">Social</a></li>
+ <li ng-class="{active: kcCurrent == 'roles'}" data-ng-show="auth.hasAccess(realm.realm, 'manage-realm')"><a href="#/realms/{{kcRealm}}/roles">Roles</a></li>
+ <li ng-class="{active: kcCurrent == 'defRoles'}" data-ng-show="auth.hasAccess(realm.realm, 'manage-realm')"><a href="#/realms/{{kcRealm}}/default-roles">Default Roles</a></li>
+ <li ng-class="{active: kcCurrent == 'credentials'}" data-ng-show="auth.hasAccess(realm.realm, 'manage-realm')"><a href="#/realms/{{kcRealm}}/required-credentials">Credentials</a></li>
+ <li ng-class="{active: kcCurrent == 'token'}" data-ng-show="auth.hasAccess(realm.realm, 'manage-realm')"><a href="#/realms/{{kcRealm}}/token-settings">Token</a></li>
+ <li ng-class="{active: kcCurrent == 'keys'}" data-ng-show="auth.hasAccess(realm.realm, 'manage-realm')"><a href="#/realms/{{kcRealm}}/keys-settings">Keys</a></li>
+ <li ng-class="{active: kcCurrent == 'email'}" data-ng-show="auth.hasAccess(realm.realm, 'manage-realm')"><a href="#/realms/{{kcRealm}}/smtp-settings">Email</a></li>
+</ul>
\ No newline at end of file
diff --git a/model/api/src/main/java/org/keycloak/models/AccountRoles.java b/model/api/src/main/java/org/keycloak/models/AccountRoles.java
new file mode 100644
index 0000000..824d00a
--- /dev/null
+++ b/model/api/src/main/java/org/keycloak/models/AccountRoles.java
@@ -0,0 +1,13 @@
+package org.keycloak.models;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public interface AccountRoles {
+
+ String VIEW_PROFILE = "view-profile";
+ String MANAGE_ACCOUNT = "manage-account";
+
+ String[] ALL = {VIEW_PROFILE, MANAGE_ACCOUNT};
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/AdminRoles.java b/model/api/src/main/java/org/keycloak/models/AdminRoles.java
new file mode 100644
index 0000000..ab414bf
--- /dev/null
+++ b/model/api/src/main/java/org/keycloak/models/AdminRoles.java
@@ -0,0 +1,23 @@
+package org.keycloak.models;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class AdminRoles {
+
+ public static String APP_SUFFIX = "-realm";
+
+ public static String ADMIN = "admin";
+
+ public static String MANAGE_REALM = "manage-realm";
+ public static String MANAGE_USERS = "manage-users";
+ public static String MANAGE_APPLICATIONS = "manage-applications";
+ public static String MANAGE_CLIENTS = "manage-clients";
+
+ public static String[] ALL_REALM_ROLES = {MANAGE_REALM, MANAGE_USERS, MANAGE_APPLICATIONS, MANAGE_CLIENTS};
+
+ public static String getAdminApp(RealmModel realm) {
+ return realm.getName() + APP_SUFFIX;
+ }
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/Constants.java b/model/api/src/main/java/org/keycloak/models/Constants.java
index c2051df..9dfe1e4 100755
--- a/model/api/src/main/java/org/keycloak/models/Constants.java
+++ b/model/api/src/main/java/org/keycloak/models/Constants.java
@@ -5,14 +5,12 @@ package org.keycloak.models;
* @version $Revision: 1 $
*/
public interface Constants {
- String INTERNAL_ROLE = "KEYCLOAK_";
String ADMIN_REALM = "keycloak-admin";
String ADMIN_CONSOLE_APPLICATION = "admin-console";
- String ADMIN_CONSOLE_ADMIN_ROLE = "admin";
+
+ String INTERNAL_ROLE = "KEYCLOAK_";
String APPLICATION_ROLE = INTERNAL_ROLE + "_APPLICATION";
String IDENTITY_REQUESTER_ROLE = INTERNAL_ROLE + "_IDENTITY_REQUESTER";
- String ACCOUNT_APPLICATION = "account";
- String ACCOUNT_PROFILE_ROLE = "view-profile";
- String ACCOUNT_MANAGE_ROLE = "manage-account";
+ String ACCOUNT_MANAGEMENT_APP = "account";
}
diff --git a/model/api/src/main/java/org/keycloak/models/KeycloakSession.java b/model/api/src/main/java/org/keycloak/models/KeycloakSession.java
index f9ed6a2..00b4db9 100755
--- a/model/api/src/main/java/org/keycloak/models/KeycloakSession.java
+++ b/model/api/src/main/java/org/keycloak/models/KeycloakSession.java
@@ -13,7 +13,7 @@ public interface KeycloakSession {
RealmModel createRealm(String id, String name);
RealmModel getRealm(String id);
RealmModel getRealmByName(String name);
- List<RealmModel> getRealms(UserModel admin);
+ List<RealmModel> getRealms();
boolean removeRealm(String id);
void close();
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java
index 1a24530..7812315 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java
@@ -49,7 +49,7 @@ public class JpaKeycloakSession implements KeycloakSession {
}
@Override
- public List<RealmModel> getRealms(UserModel admin) {
+ public List<RealmModel> getRealms() {
TypedQuery<RealmEntity> query = em.createNamedQuery("getAllRealms", RealmEntity.class);
List<RealmEntity> entities = query.getResultList();
List<RealmModel> realms = new ArrayList<RealmModel>();
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java
index a57916b..1420a09 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java
@@ -67,7 +67,7 @@ public class MongoKeycloakSession implements KeycloakSession {
}
@Override
- public List<RealmModel> getRealms(UserModel admin) {
+ public List<RealmModel> getRealms() {
DBObject query = new BasicDBObject();
List<RealmEntity> realms = getMongoStore().loadEntities(RealmEntity.class, query, invocationContext);
diff --git a/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java
index c7c9671..4846b57 100644
--- a/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java
@@ -13,6 +13,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RoleModel;
import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.managers.ApplianceBootstrap;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.util.JsonSerialization;
@@ -34,6 +35,8 @@ public class AbstractModelTest {
identitySession = factory.createSession();
identitySession.getTransaction().begin();
realmManager = new RealmManager(identitySession);
+
+ new ApplianceBootstrap().bootstrap(identitySession);
}
@After
diff --git a/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java b/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java
index 6e71d6e..8aa12f9 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java
@@ -1,6 +1,7 @@
package org.keycloak.model.test;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
@@ -33,12 +34,6 @@ public class AdapterTest extends AbstractModelTest {
private RealmModel realmModel;
@Test
- public void installTest() throws Exception {
- new ApplianceBootstrap().bootstrap(identitySession);
-
- }
-
- @Test
public void test1CreateRealm() throws Exception {
realmModel = realmManager.createRealm("JUGGLER");
realmModel.setAccessCodeLifespan(100);
@@ -79,7 +74,6 @@ public class AdapterTest extends AbstractModelTest {
realmModel.setUpdateProfileOnInitialSocialLogin(true);
realmModel.addDefaultRole("foo");
- System.out.println(realmModel.getId());
realmModel = realmManager.getRealm(realmModel.getId());
Assert.assertNotNull(realmModel);
Assert.assertEquals(realmModel.getAccessCodeLifespan(), 100);
@@ -93,13 +87,11 @@ public class AdapterTest extends AbstractModelTest {
Assert.assertEquals(1, realmModel.getDefaultRoles().size());
Assert.assertEquals("foo", realmModel.getDefaultRoles().get(0));
- String id = realmModel.getId();
- System.out.println("id: " + id);
+ realmModel.getId();
commit();
- List<RealmModel> realms = identitySession.getRealms(null);
- System.out.println("num realms: " + realms.size());
- Assert.assertEquals(realms.size(), 1);
+ List<RealmModel> realms = identitySession.getRealms();
+ Assert.assertEquals(realms.size(), 2);
}
diff --git a/model/tests/src/test/java/org/keycloak/model/test/ImportTest.java b/model/tests/src/test/java/org/keycloak/model/test/ImportTest.java
index b44b32f..ba30206 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/ImportTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/ImportTest.java
@@ -4,6 +4,7 @@ import org.junit.Assert;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
+import org.keycloak.models.AccountRoles;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.Constants;
import org.keycloak.models.RealmModel;
@@ -56,7 +57,7 @@ public class ImportTest extends AbstractModelTest {
// Test applications imported
ApplicationModel application = realm.getApplicationByName("Application");
ApplicationModel otherApp = realm.getApplicationByName("OtherApp");
- ApplicationModel accountApp = realm.getApplicationByName(Constants.ACCOUNT_APPLICATION);
+ ApplicationModel accountApp = realm.getApplicationByName(Constants.ACCOUNT_MANAGEMENT_APP);
ApplicationModel nonExisting = realm.getApplicationByName("NonExisting");
Assert.assertNotNull(application);
Assert.assertNotNull(otherApp);
@@ -80,8 +81,8 @@ public class ImportTest extends AbstractModelTest {
Assert.assertTrue(allRoles.contains(realm.getRole("admin")));
Assert.assertTrue(allRoles.contains(application.getRole("app-admin")));
Assert.assertTrue(allRoles.contains(otherApp.getRole("otherapp-admin")));
- Assert.assertTrue(allRoles.contains(accountApp.getRole(Constants.ACCOUNT_PROFILE_ROLE)));
- Assert.assertTrue(allRoles.contains(accountApp.getRole(Constants.ACCOUNT_MANAGE_ROLE)));
+ Assert.assertTrue(allRoles.contains(accountApp.getRole(AccountRoles.VIEW_PROFILE)));
+ Assert.assertTrue(allRoles.contains(accountApp.getRole(AccountRoles.MANAGE_ACCOUNT)));
UserModel wburke = realm.getUser("wburke");
allRoles = realm.getRoleMappings(wburke);
diff --git a/services/src/main/java/org/keycloak/services/managers/AppAuthManager.java b/services/src/main/java/org/keycloak/services/managers/AppAuthManager.java
new file mode 100644
index 0000000..9aea2f3
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/managers/AppAuthManager.java
@@ -0,0 +1,176 @@
+package org.keycloak.services.managers;
+
+import org.jboss.resteasy.logging.Logger;
+import org.jboss.resteasy.spi.HttpResponse;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.RSATokenVerifier;
+import org.keycloak.VerificationException;
+import org.keycloak.jose.jws.JWSBuilder;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.jose.jws.crypto.RSAProvider;
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.AccessToken;
+
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.NotAuthorizedException;
+import javax.ws.rs.core.Cookie;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.NewCookie;
+import java.net.URI;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class AppAuthManager extends AuthenticationManager {
+ protected static Logger logger = Logger.getLogger(AuthenticationManager.class);
+
+ private String cookieName;
+ private TokenManager tokenManager;
+
+ public AppAuthManager(String cookieName, TokenManager tokenManager) {
+ this.cookieName = cookieName;
+ this.tokenManager = tokenManager;
+ }
+
+ public NewCookie createCookie(RealmModel realm, UserModel client, String code, URI uri) {
+ JWSInput input = new JWSInput(code);
+ boolean verifiedCode = false;
+ try {
+ verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
+ } catch (Exception ignored) {
+ logger.debug("Failed to verify signature", ignored);
+ }
+ if (!verifiedCode) {
+ logger.debug("unverified access code");
+ throw new BadRequestException();
+ }
+ String key = input.readContentAsString();
+ AccessCodeEntry accessCode = tokenManager.pullAccessCode(key);
+ if (accessCode == null) {
+ logger.debug("bad access code");
+ throw new BadRequestException();
+ }
+ if (accessCode.isExpired()) {
+ logger.debug("access code expired");
+ throw new BadRequestException();
+ }
+ if (!accessCode.getToken().isActive()) {
+ logger.debug("access token expired");
+ throw new BadRequestException();
+ }
+ if (!accessCode.getRealm().getId().equals(realm.getId())) {
+ logger.debug("bad realm");
+ throw new BadRequestException();
+
+ }
+ if (!client.getLoginName().equals(accessCode.getClient().getLoginName())) {
+ logger.debug("bad client");
+ throw new BadRequestException();
+ }
+
+ return createLoginCookie(realm, accessCode.getUser(), accessCode.getClient(), cookieName, uri.getRawPath(), false);
+ }
+
+ public NewCookie createRefreshCookie(RealmModel realm, UserModel user, UserModel client, URI uri) {
+ return createLoginCookie(realm, user, client, cookieName, uri.getRawPath(), false);
+ }
+
+ public void expireCookie(URI uri) {
+ expireCookie(cookieName, uri.getRawPath());
+ }
+
+ public Auth authenticateCookie(RealmModel realm, HttpHeaders headers) {
+ return authenticateCookie(realm, headers, cookieName, true);
+ }
+
+ public Auth authenticate(RealmModel realm, HttpHeaders headers) {
+ Auth auth = authenticateCookie(realm, headers);
+ if (auth != null) return auth;
+ return authenticateBearerToken(realm, headers);
+ }
+
+ private Auth authenticateCookie(RealmModel realm, HttpHeaders headers, String cookieName, boolean checkActive) {
+ logger.info("authenticateCookie");
+ Cookie cookie = headers.getCookies().get(cookieName);
+ if (cookie == null) {
+ logger.info("authenticateCookie could not find cookie: {0}", cookieName);
+ return null;
+ }
+
+ String tokenString = cookie.getValue();
+ try {
+ AccessToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), realm.getName(), checkActive);
+ logger.info("token verified");
+ if (checkActive && !token.isActive()) {
+ logger.info("cookie expired");
+ expireCookie(cookie.getName(), cookie.getPath());
+ return null;
+ }
+
+ UserModel user = realm.getUserById(token.getSubject());
+ if (user == null || !user.isEnabled()) {
+ logger.info("Unknown user in cookie");
+ expireCookie(cookie.getName(), cookie.getPath());
+ return null;
+ }
+
+ UserModel client = null;
+ if (token.getIssuedFor() != null) {
+ client = realm.getUser(token.getIssuedFor());
+ if (client == null || !client.isEnabled()) {
+ logger.info("Unknown client in cookie");
+ expireCookie(cookie.getName(), cookie.getPath());
+ return null;
+ }
+ }
+
+ return new Auth(realm, user, client);
+ } catch (VerificationException e) {
+ logger.info("Failed to verify cookie", e);
+ expireCookie(cookie.getName(), cookie.getPath());
+ }
+ return null;
+ }
+
+ private Auth authenticateBearerToken(RealmModel realm, HttpHeaders headers) {
+ String tokenString;
+ String authHeader = headers.getHeaderString(HttpHeaders.AUTHORIZATION);
+ if (authHeader == null) {
+ return null;
+ } else {
+ String[] split = authHeader.trim().split("\\s+");
+ if (split == null || split.length != 2) throw new NotAuthorizedException("Bearer");
+ if (!split[0].equalsIgnoreCase("Bearer")) throw new NotAuthorizedException("Bearer");
+ tokenString = split[1];
+ }
+
+ try {
+ AccessToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), realm.getName());
+ if (!token.isActive()) {
+ throw new NotAuthorizedException("token_expired");
+ }
+
+ UserModel user = realm.getUserById(token.getSubject());
+ if (user == null || !user.isEnabled()) {
+ throw new NotAuthorizedException("invalid_user");
+ }
+
+ UserModel client = null;
+ if (token.getIssuedFor() != null) {
+ client = realm.getUser(token.getIssuedFor());
+ if (client == null || !client.isEnabled()) {
+ throw new NotAuthorizedException("invalid_user");
+ }
+ }
+
+ return new Auth(token, user, client);
+ } catch (VerificationException e) {
+ logger.error("Failed to verify token", e);
+ throw new NotAuthorizedException("invalid_token");
+ }
+ }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
index 49ea96a..337dcf0 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
@@ -1,6 +1,7 @@
package org.keycloak.services.managers;
import org.jboss.resteasy.logging.Logger;
+import org.keycloak.models.AdminRoles;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
@@ -62,7 +63,9 @@ public class ApplianceBootstrap {
adminConsole.setBaseUrl("/auth/admin/index.html");
adminConsole.setEnabled(true);
- RoleModel adminRole = adminConsole.addRole(Constants.ADMIN_CONSOLE_ADMIN_ROLE);
+ RoleModel adminRole = realm.getRole(AdminRoles.ADMIN);
+
+ adminConsole.addScope(adminRole);
UserModel adminUser = realm.addUser("admin");
adminUser.setEnabled(true);
@@ -74,7 +77,7 @@ public class ApplianceBootstrap {
realm.grantRole(adminUser, adminRole);
- ApplicationModel accountApp = realm.getApplicationNameMap().get(Constants.ACCOUNT_APPLICATION);
+ ApplicationModel accountApp = realm.getApplicationNameMap().get(Constants.ACCOUNT_MANAGEMENT_APP);
for (String r : accountApp.getDefaultRoles()) {
realm.grantRole(adminUser, accountApp.getRole(r));
}
diff --git a/services/src/main/java/org/keycloak/services/managers/Auth.java b/services/src/main/java/org/keycloak/services/managers/Auth.java
new file mode 100644
index 0000000..3a2b21c
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/managers/Auth.java
@@ -0,0 +1,138 @@
+package org.keycloak.services.managers;
+
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.AccessToken;
+
+import javax.ws.rs.ForbiddenException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+*/
+public class Auth {
+ private final boolean cookie;
+ private final RealmModel realm;
+ private final AccessToken token;
+ private final UserModel user;
+ private final UserModel client;
+
+ public Auth(RealmModel realm, UserModel user, UserModel client) {
+ this.cookie = true;
+ this.realm = realm;
+ this.token = null;
+
+ this.user = user;
+ this.client = client;
+ }
+
+ public Auth(AccessToken token, UserModel user, UserModel client) {
+ this.cookie = false;
+ this.token = token;
+ this.realm = null;
+
+ this.user = user;
+ this.client = client;
+ }
+
+ public boolean isCookie() {
+ return cookie;
+ }
+
+ public RealmModel getRealm() {
+ return realm;
+ }
+
+ public UserModel getUser() {
+ return user;
+ }
+
+ public UserModel getClient() {
+ return client;
+ }
+
+ public AccessToken getToken() {
+ return token;
+ }
+
+ public void require(String role) {
+ if (!has(role)) {
+ throw new ForbiddenException();
+ }
+ }
+
+ public void require(String app, String role) {
+ if (!has(app, role)) {
+ throw new ForbiddenException();
+ }
+ }
+
+ public void require(ApplicationModel app, String role) {
+ if (!has(app, role)) {
+ throw new ForbiddenException();
+ }
+ }
+
+ public void requireOneOf(String app, String... roles) {
+ if(!hasOneOf(app, roles)) {
+ throw new ForbiddenException();
+ }
+ }
+
+ public void requireOneOf(ApplicationModel app, String... roles) {
+ if(!hasOneOf(app, roles)) {
+ throw new ForbiddenException();
+ }
+ }
+
+ public boolean has(String role) {
+ if (cookie) {
+ return realm.hasRole(user, realm.getRole(role));
+ } else {
+ return token.getRealmAccess() != null && token.getRealmAccess().isUserInRole(role);
+ }
+ }
+
+ public boolean has(String app, String role) {
+ if (cookie) {
+ return realm.hasRole(user, realm.getApplicationByName(app).getRole(role));
+ } else {
+ AccessToken.Access access = token.getResourceAccess(app);
+ return access != null && access.isUserInRole(role);
+ }
+ }
+
+ public boolean has(ApplicationModel app, String role) {
+ if (cookie) {
+ return realm.hasRole(user, app.getRole(role));
+ } else {
+ AccessToken.Access access = token.getResourceAccess(app.getName());
+ return access != null && access.isUserInRole(role);
+ }
+ }
+
+ public boolean hasOneOf(String app, String... roles) {
+ for (String r : roles) {
+ if (has(app, r)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean hasOneOf(ApplicationModel app, String... roles) {
+ for (String r : roles) {
+ if (has(app, r)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
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 b82f585..90ab901 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -14,11 +14,8 @@ import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.services.resources.AccountService;
-import org.keycloak.services.resources.admin.AdminService;
import org.keycloak.services.resources.RealmsResource;
-import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedMap;
@@ -59,19 +56,6 @@ public class AuthenticationManager {
return createLoginCookie(realm, user, null, cookieName, cookiePath, rememberMe);
}
- public NewCookie createSaasIdentityCookie(RealmModel realm, UserModel user, UriInfo uriInfo) {
- String cookieName = AdminService.SAAS_IDENTITY_COOKIE;
- URI uri = AdminService.saasCookiePath(uriInfo).build();
- String cookiePath = uri.getRawPath();
- return createLoginCookie(realm, user, null, cookieName, cookiePath, false);
- }
-
- public NewCookie createAccountIdentityCookie(RealmModel realm, UserModel user, UserModel client, URI uri) {
- String cookieName = AccountService.ACCOUNT_IDENTITY_COOKIE;
- String cookiePath = uri.getRawPath();
- return createLoginCookie(realm, user, client, cookieName, cookiePath, false);
- }
-
protected NewCookie createLoginCookie(RealmModel realm, UserModel user, UserModel client, String cookieName, String cookiePath, boolean rememberMe) {
AccessToken identityToken = createIdentityToken(realm, user);
if (client != null) {
@@ -104,7 +88,6 @@ public class AuthenticationManager {
return encodedToken;
}
-
public void expireIdentityCookie(RealmModel realm, UriInfo uriInfo) {
logger.debug("Expiring identity cookie");
String path = getIdentityCookiePath(realm, uriInfo);
@@ -123,17 +106,6 @@ public class AuthenticationManager {
return uri.getRawPath();
}
- public void expireSaasIdentityCookie(UriInfo uriInfo) {
- URI uri = AdminService.saasCookiePath(uriInfo).build();
- String cookiePath = uri.getRawPath();
- expireCookie(AdminService.SAAS_IDENTITY_COOKIE, cookiePath);
- }
-
- public void expireAccountIdentityCookie(URI uri) {
- String cookiePath = uri.getRawPath();
- expireCookie(AccountService.ACCOUNT_IDENTITY_COOKIE, cookiePath);
- }
-
public void expireCookie(String cookieName, String path) {
HttpResponse response = ResteasyProviderFactory.getContextData(HttpResponse.class);
if (response == null) {
@@ -149,42 +121,13 @@ public class AuthenticationManager {
return authenticateIdentityCookie(realm, uriInfo, headers, true);
}
-
public UserModel authenticateIdentityCookie(RealmModel realm, UriInfo uriInfo, HttpHeaders headers, boolean checkActive) {
logger.info("authenticateIdentityCookie");
String cookieName = KEYCLOAK_IDENTITY_COOKIE;
- Auth auth = authenticateIdentityCookie(realm, uriInfo, headers, cookieName, checkActive);
- return auth != null ? auth.getUser() : null;
- }
-
- public UserModel authenticateSaasIdentityCookie(RealmModel realm, UriInfo uriInfo, HttpHeaders headers) {
- String cookieName = AdminService.SAAS_IDENTITY_COOKIE;
- Auth auth = authenticateIdentityCookie(realm, uriInfo, headers, cookieName, true);
- return auth != null ? auth.getUser() : null;
+ return authenticateIdentityCookie(realm, uriInfo, headers, cookieName, checkActive);
}
- public Auth authenticateAccountIdentityCookie(RealmModel realm, UriInfo uriInfo, HttpHeaders headers) {
- String cookieName = AccountService.ACCOUNT_IDENTITY_COOKIE;
- return authenticateIdentityCookie(realm, uriInfo, headers, cookieName, true);
- }
-
- public UserModel authenticateSaasIdentity(RealmModel realm, UriInfo uriInfo, HttpHeaders headers) {
- UserModel user = authenticateSaasIdentityCookie(realm, uriInfo, headers);
- if (user != null) return user;
-
- Auth auth = authenticateBearerToken(realm, headers);
- return auth != null ? auth.getUser() : null;
- }
-
- public Auth authenticateAccountIdentity(RealmModel realm, UriInfo uriInfo, HttpHeaders headers) {
- Auth auth = authenticateAccountIdentityCookie(realm, uriInfo, headers);
- if (auth != null) return auth;
-
- return authenticateBearerToken(realm, headers);
- }
-
-
- protected Auth authenticateIdentityCookie(RealmModel realm, UriInfo uriInfo, HttpHeaders headers, String cookieName, boolean checkActive) {
+ protected UserModel authenticateIdentityCookie(RealmModel realm, UriInfo uriInfo, HttpHeaders headers, String cookieName, boolean checkActive) {
logger.info("authenticateIdentityCookie");
Cookie cookie = headers.getCookies().get(cookieName);
if (cookie == null) {
@@ -202,27 +145,14 @@ public class AuthenticationManager {
return null;
}
- Auth auth = new Auth(token);
-
UserModel user = realm.getUserById(token.getSubject());
if (user == null || !user.isEnabled()) {
logger.info("Unknown user in identity cookie");
expireIdentityCookie(realm, uriInfo);
return null;
}
- auth.setUser(user);
- if (token.getIssuedFor() != null) {
- UserModel client = realm.getUser(token.getIssuedFor());
- if (client == null || !client.isEnabled()) {
- logger.info("Unknown client in identity cookie");
- expireIdentityCookie(realm, uriInfo);
- return null;
- }
- auth.setClient(client);
- }
-
- return auth;
+ return user;
} catch (VerificationException e) {
logger.info("Failed to verify identity cookie", e);
expireCookie(cookie.getName(), cookie.getPath());
@@ -230,49 +160,6 @@ public class AuthenticationManager {
return null;
}
- public Auth authenticateBearerToken(RealmModel realm, HttpHeaders headers) {
- String tokenString = null;
- String authHeader = headers.getHeaderString(HttpHeaders.AUTHORIZATION);
- if (authHeader == null) {
- return null;
- } else {
- String[] split = authHeader.trim().split("\\s+");
- if (split == null || split.length != 2) throw new NotAuthorizedException("Bearer");
- if (!split[0].equalsIgnoreCase("Bearer")) throw new NotAuthorizedException("Bearer");
- tokenString = split[1];
- }
-
-
- try {
- AccessToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), realm.getName());
- if (!token.isActive()) {
- throw new NotAuthorizedException("token_expired");
- }
-
- Auth auth = new Auth(token);
-
- UserModel user = realm.getUserById(token.getSubject());
- if (user == null || !user.isEnabled()) {
- throw new NotAuthorizedException("invalid_user");
- }
- auth.setUser(user);
-
- if (token.getIssuedFor() != null) {
- UserModel client = realm.getUser(token.getIssuedFor());
- if (client == null || !client.isEnabled()) {
- throw new NotAuthorizedException("invalid_user");
- }
- auth.setClient(client);
- }
-
- return auth;
- } catch (VerificationException e) {
- logger.error("Failed to verify token", e);
- throw new NotAuthorizedException("invalid_token");
- }
- }
-
-
public AuthenticationStatus authenticateForm(RealmModel realm, UserModel user, MultivaluedMap<String, String> formData) {
if (user == null) {
logger.debug("Not Authenticated! Incorrect user name");
@@ -356,34 +243,4 @@ public class AuthenticationManager {
SUCCESS, ACCOUNT_DISABLED, ACTIONS_REQUIRED, INVALID_USER, INVALID_CREDENTIALS, MISSING_PASSWORD, MISSING_TOTP, FAILED
}
- public static class Auth {
- private AccessToken token;
- private UserModel user;
- private UserModel client;
-
- public Auth(AccessToken token) {
- this.token = token;
- }
-
- public AccessToken getToken() {
- return token;
- }
-
- public UserModel getUser() {
- return user;
- }
-
- public UserModel getClient() {
- return client;
- }
-
- void setUser(UserModel user) {
- this.user = user;
- }
-
- void setClient(UserModel client) {
- this.client = client;
- }
- }
-
}
diff --git a/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java b/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
index 9bf9142..303cd94 100755
--- a/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
+++ b/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
@@ -85,7 +85,7 @@ public class ModelToRepresentation {
rep.setPasswordPolicy(realm.getPasswordPolicy().toString());
}
- ApplicationModel accountManagementApplication = realm.getApplicationNameMap().get(Constants.ACCOUNT_APPLICATION);
+ ApplicationModel accountManagementApplication = realm.getApplicationNameMap().get(Constants.ACCOUNT_MANAGEMENT_APP);
List<String> defaultRoles = realm.getDefaultRoles();
if (!defaultRoles.isEmpty()) {
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 4828002..ca71051 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -1,6 +1,8 @@
package org.keycloak.services.managers;
import org.jboss.resteasy.logging.Logger;
+import org.keycloak.models.AccountRoles;
+import org.keycloak.models.AdminRoles;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
@@ -59,7 +61,6 @@ public class RealmManager {
return identitySession.getRealmByName(name);
}
-
public RealmModel createRealm(String name) {
return createRealm(name, name);
}
@@ -71,13 +72,31 @@ public class RealmManager {
realm.addRole(Constants.APPLICATION_ROLE);
realm.addRole(Constants.IDENTITY_REQUESTER_ROLE);
+ setupAdminManagement(realm);
setupAccountManagement(realm);
+
realm.addRequiredOAuthClientCredential(UserCredentialModel.SECRET);
realm.addRequiredResourceCredential(UserCredentialModel.SECRET);
return realm;
}
+ public boolean removeRealm(RealmModel realm) {
+ boolean removed = identitySession.removeRealm(realm.getId());
+
+ RealmModel adminRealm = getKeycloakAdminstrationRealm();
+ RoleModel adminRole = adminRealm.getRole(AdminRoles.ADMIN);
+
+ ApplicationModel realmAdminApp = adminRealm.getApplicationByName(AdminRoles.getAdminApp(realm));
+ for (RoleModel r : realmAdminApp.getRoles()) {
+ adminRole.removeCompositeRole(r);
+ }
+
+ adminRealm.removeApplication(realmAdminApp.getId());
+
+ return removed;
+ }
+
public void generateRealmKeys(RealmModel realm) {
KeyPair keyPair = null;
try {
@@ -134,19 +153,41 @@ public class RealmManager {
}
}
+ private void setupAdminManagement(RealmModel realm) {
+ RealmModel adminRealm;
+ RoleModel adminRole;
+
+ if (realm.getName().equals(Constants.ADMIN_REALM)) {
+ adminRealm = realm;
+
+ adminRole = realm.addRole(AdminRoles.ADMIN);
+ } else {
+ adminRealm = identitySession.getRealmByName(Constants.ADMIN_REALM);
+ adminRole = adminRealm.getRole(AdminRoles.ADMIN);
+ }
+
+ ApplicationManager applicationManager = new ApplicationManager(new RealmManager(identitySession));
+ ApplicationModel realmAdminApp = applicationManager.createApplication(adminRealm, AdminRoles.getAdminApp(realm));
+
+ for (String r : AdminRoles.ALL_REALM_ROLES) {
+ RoleModel role = realmAdminApp.addRole(r);
+ adminRole.addCompositeRole(role);
+ }
+ }
+
private void setupAccountManagement(RealmModel realm) {
- ApplicationModel application = realm.getApplicationNameMap().get(Constants.ACCOUNT_APPLICATION);
+ ApplicationModel application = realm.getApplicationNameMap().get(Constants.ACCOUNT_MANAGEMENT_APP);
if (application == null) {
- application = new ApplicationManager(this).createApplication(realm, Constants.ACCOUNT_APPLICATION);
+ application = new ApplicationManager(this).createApplication(realm, Constants.ACCOUNT_MANAGEMENT_APP);
application.setEnabled(true);
- application.addDefaultRole(Constants.ACCOUNT_PROFILE_ROLE);
- application.addDefaultRole(Constants.ACCOUNT_MANAGE_ROLE);
-
+ for (String role : AccountRoles.ALL) {
+ application.addDefaultRole(role);
+ }
}
}
- public RealmModel importRealm(RealmRepresentation rep, UserModel realmCreator) {
+ public RealmModel importRealm(RealmRepresentation rep) {
String id = rep.getId();
if (id == null) {
id = KeycloakModelUtils.generateId();
@@ -299,7 +340,6 @@ public class RealmManager {
}
-
if (rep.getRoleMappings() != null) {
for (UserRoleMappingRepresentation mapping : rep.getRoleMappings()) {
UserModel user = userMap.get(mapping.getUsername());
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 12c167a..407d2c9 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -23,7 +23,6 @@ package org.keycloak.services.resources;
import org.jboss.resteasy.logging.Logger;
import org.jboss.resteasy.spi.HttpRequest;
-import org.keycloak.AbstractOAuthClient;
import org.keycloak.account.Account;
import org.keycloak.account.AccountLoader;
import org.keycloak.account.AccountPages;
@@ -32,10 +31,10 @@ import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.crypto.RSAProvider;
import org.keycloak.models.*;
import org.keycloak.models.utils.TimeBasedOTP;
-import org.keycloak.representations.AccessToken;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.managers.AccessCodeEntry;
-import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.managers.AppAuthManager;
+import org.keycloak.services.managers.Auth;
import org.keycloak.services.managers.ModelToRepresentation;
import org.keycloak.services.managers.TokenManager;
import org.keycloak.services.messages.Messages;
@@ -68,23 +67,23 @@ public class AccountService {
@Context
private UriInfo uriInfo;
- private AuthenticationManager authManager = new AuthenticationManager();
+ private AppAuthManager authManager;
private ApplicationModel application;
- private TokenManager tokenManager;
-
public AccountService(RealmModel realm, ApplicationModel application, TokenManager tokenManager) {
this.realm = realm;
this.application = application;
- this.tokenManager = tokenManager;
+ this.authManager = new AppAuthManager("KEYCLOAK_ACCOUNT_IDENTITY", tokenManager);
}
private Response forwardToPage(String path, AccountPages page) {
- AuthenticationManager.Auth auth = getAuth(false);
+ Auth auth = getAuth(false);
if (auth != null) {
- if (!hasAccess(auth)) {
- return noAccess();
+ try {
+ auth.require(application, AccountRoles.MANAGE_ACCOUNT);
+ } catch (ForbiddenException e) {
+ return Flows.forms(realm, request, uriInfo).setError("No access").createErrorPage();
}
Account account = AccountLoader.load().createAccount(uriInfo).setRealm(realm).setUser(auth.getUser());
@@ -100,10 +99,6 @@ public class AccountService {
}
}
- private Response noAccess() {
- return Flows.forms(realm, request, uriInfo).setError("No access").createErrorPage();
- }
-
@Path("/")
@OPTIONS
public Response accountPreflight() {
@@ -117,10 +112,9 @@ public class AccountService {
if (types.contains(MediaType.WILDCARD_TYPE) || (types.contains(MediaType.TEXT_HTML_TYPE))) {
return forwardToPage(null, AccountPages.ACCOUNT);
} else if (types.contains(MediaType.APPLICATION_JSON_TYPE)) {
- AuthenticationManager.Auth auth = getAuth(true);
- if (!hasAccess(auth, Constants.ACCOUNT_PROFILE_ROLE)) {
- return Response.status(Response.Status.FORBIDDEN).build();
- }
+ Auth auth = getAuth(true);
+ auth.requireOneOf(application, AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_PROFILE);
+
return Cors.add(request, Response.ok(ModelToRepresentation.toRepresentation(auth.getUser()))).auth().allowedOrigins(auth.getClient()).build();
} else {
return Response.notAcceptable(Variant.VariantListBuilder.newInstance().mediaTypes(MediaType.TEXT_HTML_TYPE, MediaType.APPLICATION_JSON_TYPE).build()).build();
@@ -143,10 +137,8 @@ public class AccountService {
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processAccountUpdate(final MultivaluedMap<String, String> formData) {
- AuthenticationManager.Auth auth = getAuth(true);
- if (!hasAccess(auth)) {
- return noAccess();
- }
+ Auth auth = getAuth(true);
+ auth.require(application, AccountRoles.MANAGE_ACCOUNT);
UserModel user = auth.getUser();
@@ -167,10 +159,8 @@ public class AccountService {
@Path("totp-remove")
@GET
public Response processTotpRemove() {
- AuthenticationManager.Auth auth = getAuth(true);
- if (!hasAccess(auth)) {
- return noAccess();
- }
+ Auth auth = getAuth(true);
+ auth.require(application, AccountRoles.MANAGE_ACCOUNT);
UserModel user = auth.getUser();
user.setTotp(false);
@@ -183,10 +173,8 @@ public class AccountService {
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processTotpUpdate(final MultivaluedMap<String, String> formData) {
- AuthenticationManager.Auth auth = getAuth(true);
- if (!hasAccess(auth)) {
- return noAccess();
- }
+ Auth auth = getAuth(true);
+ auth.require(application, AccountRoles.MANAGE_ACCOUNT);
UserModel user = auth.getUser();
@@ -215,10 +203,8 @@ public class AccountService {
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processPasswordUpdate(final MultivaluedMap<String, String> formData) {
- AuthenticationManager.Auth auth = getAuth(true);
- if (!hasAccess(auth)) {
- return noAccess();
- }
+ Auth auth = getAuth(true);
+ auth.require(application, AccountRoles.MANAGE_ACCOUNT);
UserModel user = auth.getUser();
@@ -285,61 +271,25 @@ public class AccountService {
throw new BadRequestException();
}
- JWSInput input = new JWSInput(code);
- boolean verifiedCode = false;
- try {
- verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
- } catch (Exception ignored) {
- logger.debug("Failed to verify signature", ignored);
- }
- if (!verifiedCode) {
- logger.debug("unverified access code");
- throw new BadRequestException();
- }
- String key = input.readContentAsString();
- AccessCodeEntry accessCode = tokenManager.pullAccessCode(key);
- if (accessCode == null) {
- logger.debug("bad access code");
- throw new BadRequestException();
- }
- if (accessCode.isExpired()) {
- logger.debug("access code expired");
- throw new BadRequestException();
- }
- if (!accessCode.getToken().isActive()) {
- logger.debug("access token expired");
- throw new BadRequestException();
- }
- if (!accessCode.getRealm().getId().equals(realm.getId())) {
- logger.debug("bad realm");
- throw new BadRequestException();
-
- }
- if (!client.getLoginName().equals(accessCode.getClient().getLoginName())) {
- logger.debug("bad client");
- throw new BadRequestException();
- }
-
URI accountUri = Urls.accountBase(uriInfo.getBaseUri()).path("/").build(realm.getName());
URI redirectUri = path != null ? accountUri.resolve(path) : accountUri;
if (referrer != null) {
redirectUri = redirectUri.resolve("?referrer=" + referrer);
}
- NewCookie cookie = authManager.createAccountIdentityCookie(realm, accessCode.getUser(), client, Urls.accountBase(uriInfo.getBaseUri()).build(realm.getName()));
+ NewCookie cookie = authManager.createCookie(realm, client, code, Urls.accountBase(uriInfo.getBaseUri()).build(realm.getName()));
return Response.status(302).cookie(cookie).location(redirectUri).build();
} finally {
- authManager.expireCookie(AbstractOAuthClient.OAUTH_TOKEN_REQUEST_STATE, uriInfo.getAbsolutePath().getRawPath());
+ authManager.expireCookie(Urls.accountBase(uriInfo.getBaseUri()).build(realm.getName()));
}
}
@Path("logout")
@GET
public Response logout() {
- // TODO Should use single-sign out via TokenService
URI baseUri = Urls.accountBase(uriInfo.getBaseUri()).build(realm.getName());
authManager.expireIdentityCookie(realm, uriInfo);
- authManager.expireAccountIdentityCookie(baseUri);
+ authManager.expireCookie(baseUri);
return Response.status(302).location(baseUri).build();
}
@@ -348,7 +298,7 @@ public class AccountService {
String authUrl = Urls.realmLoginPage(uriInfo.getBaseUri(), realm.getName()).toString();
oauth.setAuthUrl(authUrl);
- oauth.setClientId(Constants.ACCOUNT_APPLICATION);
+ oauth.setClientId(Constants.ACCOUNT_MANAGEMENT_APP);
UriBuilder uriBuilder = Urls.accountPageBuilder(uriInfo.getBaseUri()).path(AccountService.class, "loginRedirect");
@@ -368,42 +318,14 @@ public class AccountService {
return oauth.redirect(uriInfo, accountUri.toString());
}
- private AuthenticationManager.Auth getAuth(boolean error) {
- AuthenticationManager.Auth auth = authManager.authenticateAccountIdentity(realm, uriInfo, headers);
+ private Auth getAuth(boolean error) {
+ Auth auth = authManager.authenticate(realm, headers);
if (auth == null && error) {
throw new ForbiddenException();
}
return auth;
}
- private boolean hasAccess(AuthenticationManager.Auth auth) {
- return hasAccess(auth, null);
- }
-
- private boolean hasAccess(AuthenticationManager.Auth auth, String role) {
- UserModel client = auth.getClient();
- if (realm.hasRole(client, realm.getRole(Constants.APPLICATION_ROLE))) {
- // Tokens from cookies don't have roles
- UserModel user = auth.getUser();
- if (hasRole(user, Constants.ACCOUNT_MANAGE_ROLE) || (role != null && hasRole(user, role))) {
- return true;
- }
- }
-
- AccessToken.Access access = auth.getToken().getResourceAccess(application.getName());
- if (access != null) {
- if (access.isUserInRole(Constants.ACCOUNT_MANAGE_ROLE) || (role != null && access.isUserInRole(role))) {
- return true;
- }
- }
-
- return false;
- }
-
- private boolean hasRole(UserModel user, String role) {
- return realm.hasRole(user, application.getRole(role));
- }
-
private String getReferrer() {
String referrer = uriInfo.getQueryParameters().getFirst("referrer");
if (referrer != null) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
index 8665803..7a5719a 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
@@ -1,49 +1,44 @@
package org.keycloak.services.resources.admin;
+import org.codehaus.jackson.annotate.JsonProperty;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.logging.Logger;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.HttpResponse;
-import org.jboss.resteasy.spi.NotImplementedYetException;
-import org.keycloak.AbstractOAuthClient;
import org.keycloak.jaxrs.JaxrsOAuthClient;
-import org.keycloak.jose.jws.JWSInput;
-import org.keycloak.jose.jws.crypto.RSAProvider;
+import org.keycloak.models.AdminRoles;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
-import org.keycloak.services.managers.AccessCodeEntry;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.managers.AuthenticationManager.AuthenticationStatus;
+import org.keycloak.services.managers.AppAuthManager;
+import org.keycloak.services.managers.Auth;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.TokenManager;
-import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.TokenService;
import org.keycloak.services.resources.flows.Flows;
-import org.keycloak.services.resources.flows.OAuthFlows;
-import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.NotFoundException;
-import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Providers;
import java.net.URI;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -52,8 +47,6 @@ import java.net.URI;
@Path("/admin")
public class AdminService {
protected static final Logger logger = Logger.getLogger(AdminService.class);
- public static final String REALM_CREATOR_ROLE = "realm-creator";
- public static final String SAAS_IDENTITY_COOKIE = "KEYCLOAK_SAAS_IDENTITY";
@Context
protected UriInfo uriInfo;
@@ -73,25 +66,32 @@ public class AdminService {
@Context
protected Providers providers;
-
protected String adminPath = "/admin/index.html";
- protected AuthenticationManager authManager = new AuthenticationManager();
+ protected AppAuthManager authManager;
protected TokenManager tokenManager;
public AdminService(TokenManager tokenManager) {
this.tokenManager = tokenManager;
+ this.authManager = new AppAuthManager("KEYCLOAK_ADMIN_CONSOLE_IDENTITY", tokenManager);
}
public static class WhoAmI {
protected String userId;
protected String displayName;
+ @JsonProperty("admin")
+ protected boolean admin;
+ @JsonProperty("realm_access")
+ protected Map<String, Set<String>> realmAccess = new HashMap<String, Set<String>>();
+
public WhoAmI() {
}
- public WhoAmI(String userId, String displayName) {
+ public WhoAmI(String userId, String displayName, boolean admin, Map<String, Set<String>> realmAccess) {
this.userId = userId;
this.displayName = displayName;
+ this.admin = admin;
+ this.realmAccess = realmAccess;
}
public String getUserId() {
@@ -109,6 +109,22 @@ public class AdminService {
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
+
+ public boolean isAdmin() {
+ return admin;
+ }
+
+ public void setAdmin(boolean admin) {
+ this.admin = admin;
+ }
+
+ public Map<String, Set<String>> getRealmAccess() {
+ return realmAccess;
+ }
+
+ public void setRealmAccess(Map<String, Set<String>> realmAccess) {
+ this.realmAccess = realmAccess;
+ }
}
@Path("keepalive")
@@ -120,11 +136,11 @@ public class AdminService {
RealmModel realm = getAdminstrationRealm(realmManager);
if (realm == null)
throw new NotFoundException();
- UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers);
- if (user == null) {
+ Auth auth = authManager.authenticateCookie(realm, headers);
+ if (auth == null) {
return Response.status(401).build();
}
- NewCookie refreshCookie = authManager.createSaasIdentityCookie(realm, user, uriInfo);
+ NewCookie refreshCookie = authManager.createRefreshCookie(realm, auth.getUser(), auth.getClient(), AdminService.saasCookiePath(uriInfo).build());
return Response.noContent().cookie(refreshCookie).build();
}
@@ -137,15 +153,50 @@ public class AdminService {
RealmModel realm = getAdminstrationRealm(realmManager);
if (realm == null)
throw new NotFoundException();
- UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers);
+ Auth auth = authManager.authenticateCookie(realm, headers);
+ UserModel user = auth.getUser();
if (user == null) {
return Response.status(401).build();
}
- // keycloak is bootstrapped with an admin user with no first/last name, so use login name as display name
- return Response.ok(new WhoAmI(user.getLoginName(), user.getLoginName())).build();
+
+ String displayName;
+ if (user.getFirstName() != null || user.getLastName() != null) {
+ displayName = user.getFirstName();
+ if (user.getLastName() != null) {
+ displayName = displayName != null ? displayName + " " + user.getLastName() : user.getLastName();
+ }
+ } else {
+ displayName = user.getLoginName();
+ }
+
+ boolean admin = realm.hasRole(user, realm.getRole("admin"));
+
+ Map<String, Set<String>> realmAccess = new HashMap<String, Set<String>>();
+ addRealmAdminAccess(realmAccess, auth.getRealm().getRoleMappings(auth.getUser()));
+
+ return Response.ok(new WhoAmI(user.getId(), displayName, admin, realmAccess)).build();
+ }
+
+ private void addRealmAdminAccess(Map<String, Set<String>> realmAdminAccess, Set<RoleModel> roles) {
+ for (RoleModel r : roles) {
+ if (r.getContainer() instanceof ApplicationModel) {
+ ApplicationModel app = (ApplicationModel) r.getContainer();
+ if (app.getName().endsWith(AdminRoles.APP_SUFFIX)) {
+ String realm = app.getName().substring(0, app.getName().length() - AdminRoles.APP_SUFFIX.length());
+ if (!realmAdminAccess.containsKey(realm)) {
+ realmAdminAccess.put(realm, new HashSet<String>());
+ }
+ realmAdminAccess.get(realm).add(r.getName());
+ }
+ }
+
+ if (r.isComposite()) {
+ addRealmAdminAccess(realmAdminAccess, r.getComposites());
+ }
+ }
}
- @Path("isLoggedIn.js")
+ @Path("isLoggedIn.js")
@GET
@Produces("application/javascript")
@NoCache
@@ -157,7 +208,7 @@ public class AdminService {
return "var keycloakCookieLoggedIn = false;";
}
- UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers);
+ UserModel user = authManager.authenticateCookie(realm, headers).getUser();
if (user == null) {
return "var keycloakCookieLoggedIn = false;";
}
@@ -176,23 +227,14 @@ public class AdminService {
@Path("realms")
public RealmsAdminResource getRealmsAdmin(@Context final HttpHeaders headers) {
RealmManager realmManager = new RealmManager(session);
- RealmModel saasRealm = getAdminstrationRealm(realmManager);
- if (saasRealm == null)
+ RealmModel adminRealm = getAdminstrationRealm(realmManager);
+ if (adminRealm == null)
throw new NotFoundException();
- UserModel admin = authManager.authenticateSaasIdentity(saasRealm, uriInfo, headers);
- if (admin == null) {
+ Auth auth = authManager.authenticate(adminRealm, headers);
+ if (auth == null) {
throw new NotAuthorizedException("Bearer");
}
- ApplicationModel adminConsole = saasRealm.getApplicationNameMap().get(Constants.ADMIN_CONSOLE_APPLICATION);
- if (adminConsole == null) {
- throw new NotFoundException();
- }
- RoleModel adminRole = adminConsole.getRole(Constants.ADMIN_CONSOLE_ADMIN_ROLE);
- if (!saasRealm.hasRole(admin, adminRole)) {
- logger.warn("not a Realm admin");
- throw new NotAuthorizedException("Bearer");
- }
- RealmsAdminResource adminResource = new RealmsAdminResource(admin, tokenManager);
+ RealmsAdminResource adminResource = new RealmsAdminResource(auth, tokenManager);
resourceContext.initResource(adminResource);
return adminResource;
}
@@ -200,35 +242,33 @@ public class AdminService {
@Path("serverinfo")
public ServerInfoAdminResource getServerInfo(@Context final HttpHeaders headers) {
RealmManager realmManager = new RealmManager(session);
- RealmModel saasRealm = getAdminstrationRealm(realmManager);
- if (saasRealm == null)
+ RealmModel adminRealm = getAdminstrationRealm(realmManager);
+ if (adminRealm == null)
throw new NotFoundException();
- UserModel admin = authManager.authenticateSaasIdentity(saasRealm, uriInfo, headers);
+ Auth auth = authManager.authenticate(adminRealm, headers);
+ UserModel admin = auth.getUser();
if (admin == null) {
throw new NotAuthorizedException("Bearer");
}
- ApplicationModel adminConsole = saasRealm.getApplicationNameMap().get(Constants.ADMIN_CONSOLE_APPLICATION);
+ ApplicationModel adminConsole = adminRealm.getApplicationNameMap().get(Constants.ADMIN_CONSOLE_APPLICATION);
if (adminConsole == null) {
throw new NotFoundException();
}
- RoleModel adminRole = adminConsole.getRole(Constants.ADMIN_CONSOLE_ADMIN_ROLE);
- if (!saasRealm.hasRole(admin, adminRole)) {
- logger.warn("not a Realm admin");
- throw new NotAuthorizedException("Bearer");
- }
ServerInfoAdminResource adminResource = new ServerInfoAdminResource();
resourceContext.initResource(adminResource);
return adminResource;
}
+ private void expireCookie() {
+ authManager.expireCookie(AdminService.saasCookiePath(uriInfo).build());
+ }
+
@Path("login")
@GET
@NoCache
public Response loginPage(@QueryParam("path") String path) {
logger.debug("loginPage ********************** <---");
- RealmManager realmManager = new RealmManager(session);
- RealmModel realm = getAdminstrationRealm(realmManager);
- authManager.expireSaasIdentityCookie(uriInfo);
+ expireCookie();
JaxrsOAuthClient oauth = new JaxrsOAuthClient();
String authUrl = TokenService.loginPageUrl(uriInfo).build(Constants.ADMIN_REALM).toString();
@@ -259,7 +299,6 @@ public class AdminService {
URI uri = uriInfo.getBaseUriBuilder().path(AdminService.class).path(AdminService.class, "errorOnLoginRedirect").queryParam("error", message).build();
URI logout = TokenService.logoutUrl(uriInfo).queryParam("redirect_uri", uri.toString()).build(Constants.ADMIN_REALM);
return Response.status(302).location(logout).build();
-
}
@Path("login-redirect")
@@ -279,12 +318,12 @@ public class AdminService {
return redirectOnLoginError(error);
}
RealmManager realmManager = new RealmManager(session);
- RealmModel realm = getAdminstrationRealm(realmManager);
- if (!realm.isEnabled()) {
+ RealmModel adminRealm = getAdminstrationRealm(realmManager);
+ if (!adminRealm.isEnabled()) {
logger.debug("realm not enabled");
return redirectOnLoginError("realm not enabled");
}
- ApplicationModel adminConsole = realm.getApplicationNameMap().get(Constants.ADMIN_CONSOLE_APPLICATION);
+ ApplicationModel adminConsole = adminRealm.getApplicationNameMap().get(Constants.ADMIN_CONSOLE_APPLICATION);
UserModel adminConsoleUser = adminConsole.getApplicationUser();
if (!adminConsole.isEnabled() || !adminConsoleUser.isEnabled()) {
logger.debug("admin app not enabled");
@@ -301,47 +340,8 @@ public class AdminService {
}
new JaxrsOAuthClient().checkStateCookie(uriInfo, headers);
- JWSInput input = new JWSInput(code);
- boolean verifiedCode = false;
- try {
- verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
- } catch (Exception ignored) {
- logger.debug("Failed to verify signature", ignored);
- }
- if (!verifiedCode) {
- logger.debug("unverified access code");
- return redirectOnLoginError("invalid login data");
- }
- String key = input.readContentAsString();
- AccessCodeEntry accessCode = tokenManager.pullAccessCode(key);
- if (accessCode == null) {
- logger.debug("bad access code");
- return redirectOnLoginError("invalid login data");
- }
- if (accessCode.isExpired()) {
- logger.debug("access code expired");
- return redirectOnLoginError("invalid login data");
- }
- if (!accessCode.getToken().isActive()) {
- logger.debug("access token expired");
- return redirectOnLoginError("invalid login data");
- }
- if (!accessCode.getRealm().getId().equals(realm.getId())) {
- logger.debug("bad realm");
- return redirectOnLoginError("invalid login data");
-
- }
- if (!adminConsoleUser.getLoginName().equals(accessCode.getClient().getLoginName())) {
- logger.debug("bad client");
- return redirectOnLoginError("invalid login data");
- }
- RoleModel adminConsoleAdminRole = adminConsole.getRole(Constants.ADMIN_CONSOLE_ADMIN_ROLE);
- if (!realm.hasRole(accessCode.getUser(), adminConsoleAdminRole)) {
- logger.debug("not allowed");
- return redirectOnLoginError("No permission to access console");
- }
logger.debug("loginRedirect SUCCESS");
- NewCookie cookie = authManager.createSaasIdentityCookie(realm, accessCode.getUser(), uriInfo);
+ NewCookie cookie = authManager.createCookie(adminRealm, adminConsoleUser, code, AdminService.saasCookiePath(uriInfo).build());
URI redirectUri = contextRoot(uriInfo).path(adminPath).build();
if (path != null) {
@@ -349,7 +349,7 @@ public class AdminService {
}
return Response.status(302).cookie(cookie).location(redirectUri).build();
} finally {
- authManager.expireCookie(AbstractOAuthClient.OAUTH_TOKEN_REQUEST_STATE, uriInfo.getAbsolutePath().getPath());
+ expireCookie();
}
}
@@ -359,7 +359,7 @@ public class AdminService {
public Response logout() {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = getAdminstrationRealm(realmManager);
- authManager.expireSaasIdentityCookie(uriInfo);
+ expireCookie();
authManager.expireIdentityCookie(realm, uriInfo);
return Response.status(302).location(uriInfo.getBaseUriBuilder().path(AdminService.class).path(AdminService.class, "loginPage").build()).build();
@@ -370,42 +370,7 @@ public class AdminService {
@NoCache
public void logoutCookie() {
logger.debug("*** logoutCookie");
- authManager.expireSaasIdentityCookie(uriInfo);
- }
-
- @Path("login")
- @POST
- @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
- public Response processLogin(final MultivaluedMap<String, String> formData) {
- logger.debug("processLogin start");
- RealmManager realmManager = new RealmManager(session);
- RealmModel realm = getAdminstrationRealm(realmManager);
- if (realm == null)
- throw new NotFoundException();
- ApplicationModel adminConsole = realm.getApplicationNameMap().get(Constants.ADMIN_CONSOLE_APPLICATION);
- UserModel adminConsoleUser = adminConsole.getApplicationUser();
-
- if (!realm.isEnabled()) {
- throw new NotImplementedYetException();
- }
- String username = formData.getFirst("username");
- UserModel user = realm.getUser(username);
-
- AuthenticationStatus status = authManager.authenticateForm(realm, user, formData);
-
- OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
-
- switch (status) {
- case SUCCESS:
- NewCookie cookie = authManager.createSaasIdentityCookie(realm, user, uriInfo);
- return Response.status(302).cookie(cookie).location(contextRoot(uriInfo).path(adminPath).build()).build();
- case ACCOUNT_DISABLED:
- return Flows.forms(realm, request, uriInfo).setError(Messages.ACCOUNT_DISABLED).setFormData(formData).createLogin();
- case ACTIONS_REQUIRED:
- return oauth.processAccessCode(null, "n", contextRoot(uriInfo).path(adminPath).build().toString(), adminConsoleUser, user);
- default:
- return Flows.forms(realm, request, uriInfo).setError(Messages.INVALID_USER).setFormData(formData).createLogin();
- }
+ expireCookie();
}
protected RealmModel getAdminstrationRealm(RealmManager realmManager) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index 2b5e420..5ea0987 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -2,10 +2,11 @@ package org.keycloak.services.resources.admin;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.logging.Logger;
+import org.keycloak.models.AdminRoles;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.managers.Auth;
import org.keycloak.services.managers.ModelToRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.TokenManager;
@@ -20,7 +21,7 @@ import javax.ws.rs.core.Context;
*/
public class RealmAdminResource extends RoleContainerResource {
protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
- protected UserModel admin;
+ protected Auth auth;
protected RealmModel realm;
private TokenManager tokenManager;
@@ -30,15 +31,17 @@ public class RealmAdminResource extends RoleContainerResource {
@Context
protected KeycloakSession session;
- public RealmAdminResource(UserModel admin, RealmModel realm, TokenManager tokenManager) {
+ public RealmAdminResource(Auth auth, RealmModel realm, TokenManager tokenManager) {
super(realm, realm);
- this.admin = admin;
+ this.auth = auth;
this.realm = realm;
this.tokenManager = tokenManager;
}
@Path("applications")
public ApplicationsResource getApplications() {
+ auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_APPLICATIONS);
+
ApplicationsResource applicationsResource = new ApplicationsResource(realm);
resourceContext.initResource(applicationsResource);
return applicationsResource;
@@ -46,6 +49,8 @@ public class RealmAdminResource extends RoleContainerResource {
@Path("oauth-clients")
public OAuthClientsResource getOAuthClients() {
+ auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_CLIENTS);
+
OAuthClientsResource oauth = new OAuthClientsResource(realm, session);
resourceContext.initResource(oauth);
return oauth;
@@ -55,26 +60,42 @@ public class RealmAdminResource extends RoleContainerResource {
@NoCache
@Produces("application/json")
public RealmRepresentation getRealm() {
- return ModelToRepresentation.toRepresentation(realm);
- }
+ String realmAdminApp = AdminRoles.getAdminApp(realm);
+ if (auth.has(realmAdminApp, AdminRoles.MANAGE_REALM)) {
+ return ModelToRepresentation.toRepresentation(realm);
+ } else {
+ auth.requireOneOf(AdminRoles.getAdminApp(realm), AdminRoles.ALL_REALM_ROLES);
+ RealmRepresentation rep = new RealmRepresentation();
+ rep.setId(realm.getId());
+ rep.setRealm(realm.getName());
+
+ return rep;
+ }
+ }
@PUT
@Consumes("application/json")
public void updateRealm(final RealmRepresentation rep) {
+ auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_REALM);
+
logger.debug("updating realm: " + realm.getName());
new RealmManager(session).updateRealm(rep, realm);
}
@DELETE
public void deleteRealms() {
- if (!session.removeRealm(realm.getId())) {
+ auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_REALM);
+
+ if (!new RealmManager(session).removeRealm(realm)) {
throw new NotFoundException();
}
}
@Path("users")
public UsersResource users() {
+ auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_USERS);
+
UsersResource users = new UsersResource(realm, tokenManager);
resourceContext.initResource(users);
return users;
@@ -82,12 +103,11 @@ public class RealmAdminResource extends RoleContainerResource {
@Path("roles-by-id")
public RoleByIdResource rolesById() {
+ auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_REALM);
+
RoleByIdResource resource = new RoleByIdResource(realm);
resourceContext.initResource(resource);
return resource;
-
}
-
-
}
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 48e91f8..f0691d4 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
@@ -5,10 +5,13 @@ import org.jboss.resteasy.logging.Logger;
import org.jboss.resteasy.plugins.providers.multipart.InputPart;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
import org.jboss.resteasy.util.GenericType;
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.managers.Auth;
import org.keycloak.services.managers.ModelToRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.TokenManager;
@@ -35,11 +38,11 @@ import java.util.Map;
*/
public class RealmsAdminResource {
protected static final Logger logger = Logger.getLogger(RealmsAdminResource.class);
- protected UserModel admin;
+ protected Auth auth;
protected TokenManager tokenManager;
- public RealmsAdminResource(UserModel admin, TokenManager tokenManager) {
- this.admin = admin;
+ public RealmsAdminResource(Auth auth, TokenManager tokenManager) {
+ this.auth = auth;
this.tokenManager = tokenManager;
}
@@ -59,11 +62,19 @@ public class RealmsAdminResource {
@Produces("application/json")
public List<RealmRepresentation> getRealms() {
logger.debug(("getRealms()"));
- RealmManager realmManager = new RealmManager(session);
- List<RealmModel> realms = session.getRealms(admin);
+ List<RealmModel> realms = session.getRealms();
List<RealmRepresentation> reps = new ArrayList<RealmRepresentation>();
for (RealmModel realm : realms) {
- reps.add(ModelToRepresentation.toRepresentation(realm));
+ String realmAdminApp = AdminRoles.getAdminApp(realm);
+
+ if (auth.has(realmAdminApp, AdminRoles.MANAGE_REALM)) {
+ reps.add(ModelToRepresentation.toRepresentation(realm));
+ } else if (auth.hasOneOf(realmAdminApp, AdminRoles.ALL_REALM_ROLES)) {
+ RealmRepresentation rep = new RealmRepresentation();
+ rep.setId(realm.getId());
+ rep.setRealm(realm.getName());
+ reps.add(rep);
+ }
}
return reps;
}
@@ -79,13 +90,15 @@ public class RealmsAdminResource {
@POST
@Consumes("application/json")
public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) {
+ auth.require(AdminRoles.ADMIN);
+
logger.debug("importRealm: {0}", rep.getRealm());
RealmManager realmManager = new RealmManager(session);
if (realmManager.getRealmByName(rep.getRealm()) != null) {
return Flows.errors().exists("Realm " + rep.getRealm() + " already exists");
}
- RealmModel realm = realmManager.importRealm(rep, admin);
+ RealmModel realm = realmManager.importRealm(rep);
URI location = realmUrl(uriInfo).build(realm.getName());
logger.debug("imported realm success, sending back: {0}", location.toString());
return Response.created(location).build();
@@ -94,6 +107,8 @@ public class RealmsAdminResource {
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadRealm(MultipartFormDataInput input) throws IOException {
+ auth.require(AdminRoles.ADMIN);
+
Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
List<InputPart> inputParts = uploadForm.get("file");
@@ -101,7 +116,7 @@ public class RealmsAdminResource {
for (InputPart inputPart : inputParts) {
inputPart.setMediaType(MediaType.APPLICATION_JSON_TYPE);
RealmRepresentation rep = inputPart.getBody(new GenericType<RealmRepresentation>(){});
- realmManager.importRealm(rep, admin);
+ realmManager.importRealm(rep);
}
return Response.noContent().build();
}
@@ -113,8 +128,11 @@ public class RealmsAdminResource {
RealmModel realm = realmManager.getRealmByName(name);
if (realm == null) throw new NotFoundException("{realm} = " + name);
- RealmAdminResource adminResource = new RealmAdminResource(admin, realm, tokenManager);
+ auth.requireOneOf(AdminRoles.getAdminApp(realm), AdminRoles.ALL_REALM_ROLES);
+
+ RealmAdminResource adminResource = new RealmAdminResource(auth, realm, tokenManager);
resourceContext.initResource(adminResource);
return adminResource;
}
+
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index 24cfdc6..2af61a9 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -23,7 +23,6 @@ import javax.ws.rs.BadRequestException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
-import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
@@ -31,12 +30,10 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
-import javax.ws.rs.ServerErrorException;
import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
-import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -431,7 +428,7 @@ public class UsersResource {
}
String redirect = Urls.accountBase(uriInfo.getBaseUri()).path("/").build(realm.getName()).toString();
- String clientId = Constants.ACCOUNT_APPLICATION;
+ String clientId = Constants.ACCOUNT_MANAGEMENT_APP;
String state = null;
String scope = null;
diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
index 2338387..3a2ea92 100755
--- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
@@ -69,7 +69,7 @@ public class RealmsResource {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = locateRealm(name, realmManager);
- ApplicationModel application = realm.getApplicationNameMap().get(Constants.ACCOUNT_APPLICATION);
+ ApplicationModel application = realm.getApplicationNameMap().get(Constants.ACCOUNT_MANAGEMENT_APP);
if (application == null || !application.isEnabled()) {
logger.debug("account management not enabled");
throw new NotFoundException();
diff --git a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
index 6fbb6fd..cfcd1f3 100755
--- a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
+++ b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
@@ -228,7 +228,7 @@ public class KeycloakServer {
try {
RealmManager manager = new RealmManager(session);
- RealmModel adminRealm = manager.getRealm(Constants.ADMIN_REALM);
+ RealmModel adminRealm = manager.getKeycloakAdminstrationRealm();
UserModel admin = adminRealm.getUser("admin");
admin.removeRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
index f520c70..3c96873 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
@@ -10,6 +10,7 @@ import org.json.JSONObject;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
+import org.keycloak.models.AccountRoles;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserCredentialModel;
@@ -31,8 +32,6 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import java.io.IOException;
import java.net.URI;
-import java.util.Collections;
-import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -53,7 +52,7 @@ public class ProfileTest {
user.setAttribute("key1", "value1");
user.setAttribute("key2", "value2");
- ApplicationModel accountApp = appRealm.getApplicationNameMap().get(org.keycloak.models.Constants.ACCOUNT_APPLICATION);
+ ApplicationModel accountApp = appRealm.getApplicationNameMap().get(org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_APP);
UserModel user2 = appRealm.addUser("test-user-no-access@localhost");
user2.setEnabled(true);
@@ -66,12 +65,12 @@ public class ProfileTest {
appRealm.updateCredential(user2, creds);
ApplicationModel app = appRealm.getApplicationNameMap().get("test-app");
- appRealm.addScopeMapping(app.getApplicationUser(), accountApp.getRole(org.keycloak.models.Constants.ACCOUNT_PROFILE_ROLE));
+ appRealm.addScopeMapping(app.getApplicationUser(), accountApp.getRole(AccountRoles.VIEW_PROFILE));
app.getApplicationUser().addWebOrigin("http://localtest.me:8081");
UserModel thirdParty = appRealm.getUser("third-party");
- appRealm.addScopeMapping(thirdParty, accountApp.getRole(org.keycloak.models.Constants.ACCOUNT_PROFILE_ROLE));
+ appRealm.addScopeMapping(thirdParty, accountApp.getRole(AccountRoles.VIEW_PROFILE));
}
});
@@ -175,7 +174,7 @@ public class ProfileTest {
@Test
public void getProfileOAuthClient() throws Exception {
- oauth.addScope(org.keycloak.models.Constants.ACCOUNT_APPLICATION, org.keycloak.models.Constants.ACCOUNT_PROFILE_ROLE);
+ oauth.addScope(org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_APP, AccountRoles.VIEW_PROFILE);
oauth.clientId("third-party");
oauth.doLoginGrant("test-user@localhost", "password");
@@ -192,7 +191,7 @@ public class ProfileTest {
@Test
public void getProfileOAuthClientNoScope() throws Exception {
- oauth.addScope(org.keycloak.models.Constants.ACCOUNT_APPLICATION);
+ oauth.addScope(org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_APP);
oauth.clientId("third-party");
oauth.doLoginGrant("test-user@localhost", "password");
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeImportRoleTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeImportRoleTest.java
index 59a4c5e..7a53ae0 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeImportRoleTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeImportRoleTest.java
@@ -90,7 +90,7 @@ public class CompositeImportRoleTest {
AccessToken token = oauth.verifyToken(response.getAccessToken());
- Assert.assertEquals("APP_COMPOSITE_USER", oauth.getProfile(response.getAccessToken()).getUsername());
+ Assert.assertEquals(keycloakRule.getUser("Test", "APP_COMPOSITE_USER").getId(), token.getSubject());
Assert.assertEquals(1, token.getResourceAccess("APP_ROLE_APPLICATION").getRoles().size());
Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
@@ -115,7 +115,7 @@ public class CompositeImportRoleTest {
AccessToken token = oauth.verifyToken(response.getAccessToken());
- Assert.assertEquals("REALM_APP_COMPOSITE_USER", oauth.getProfile(response.getAccessToken()).getUsername());
+ Assert.assertEquals(keycloakRule.getUser("Test", "REALM_APP_COMPOSITE_USER").getId(), token.getSubject());
Assert.assertEquals(1, token.getResourceAccess("APP_ROLE_APPLICATION").getRoles().size());
Assert.assertTrue(token.getResourceAccess("APP_ROLE_APPLICATION").isUserInRole("APP_ROLE_1"));
@@ -139,7 +139,7 @@ public class CompositeImportRoleTest {
AccessToken token = oauth.verifyToken(response.getAccessToken());
- Assert.assertEquals("REALM_COMPOSITE_1_USER", oauth.getProfile(response.getAccessToken()).getUsername());
+ Assert.assertEquals(keycloakRule.getUser("Test", "REALM_COMPOSITE_1_USER").getId(), token.getSubject());
Assert.assertEquals(2, token.getRealmAccess().getRoles().size());
Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_COMPOSITE_1"));
@@ -162,7 +162,7 @@ public class CompositeImportRoleTest {
AccessToken token = oauth.verifyToken(response.getAccessToken());
- Assert.assertEquals("REALM_COMPOSITE_1_USER", oauth.getProfile(response.getAccessToken()).getUsername());
+ Assert.assertEquals(keycloakRule.getUser("Test", "REALM_COMPOSITE_1_USER").getId(), token.getSubject());
Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
@@ -184,7 +184,7 @@ public class CompositeImportRoleTest {
AccessToken token = oauth.verifyToken(response.getAccessToken());
- Assert.assertEquals("REALM_ROLE_1_USER", oauth.getProfile(response.getAccessToken()).getUsername());
+ Assert.assertEquals(keycloakRule.getUser("Test", "REALM_ROLE_1_USER").getId(), token.getSubject());
Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
index 6483823..7d6c128 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
@@ -168,7 +168,7 @@ public class CompositeRoleTest {
AccessToken token = oauth.verifyToken(response.getAccessToken());
- Assert.assertEquals("APP_COMPOSITE_USER", oauth.getProfile(response.getAccessToken()).getUsername());
+ Assert.assertEquals(keycloakRule.getUser("Test", "APP_COMPOSITE_USER").getId(), token.getSubject());
Assert.assertEquals(1, token.getResourceAccess("APP_ROLE_APPLICATION").getRoles().size());
Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
@@ -193,7 +193,7 @@ public class CompositeRoleTest {
AccessToken token = oauth.verifyToken(response.getAccessToken());
- Assert.assertEquals("REALM_APP_COMPOSITE_USER", oauth.getProfile(response.getAccessToken()).getUsername());
+ Assert.assertEquals(keycloakRule.getUser("Test", "REALM_APP_COMPOSITE_USER").getId(), token.getSubject());
Assert.assertEquals(1, token.getResourceAccess("APP_ROLE_APPLICATION").getRoles().size());
Assert.assertTrue(token.getResourceAccess("APP_ROLE_APPLICATION").isUserInRole("APP_ROLE_1"));
@@ -217,7 +217,7 @@ public class CompositeRoleTest {
AccessToken token = oauth.verifyToken(response.getAccessToken());
- Assert.assertEquals("REALM_COMPOSITE_1_USER", oauth.getProfile(response.getAccessToken()).getUsername());
+ Assert.assertEquals(keycloakRule.getUser("Test", "REALM_COMPOSITE_1_USER").getId(), token.getSubject());
Assert.assertEquals(2, token.getRealmAccess().getRoles().size());
Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_COMPOSITE_1"));
@@ -240,7 +240,7 @@ public class CompositeRoleTest {
AccessToken token = oauth.verifyToken(response.getAccessToken());
- Assert.assertEquals("REALM_COMPOSITE_1_USER", oauth.getProfile(response.getAccessToken()).getUsername());
+ Assert.assertEquals(keycloakRule.getUser("Test", "REALM_COMPOSITE_1_USER").getId(), token.getSubject());
Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
@@ -262,7 +262,7 @@ public class CompositeRoleTest {
AccessToken token = oauth.verifyToken(response.getAccessToken());
- Assert.assertEquals("REALM_ROLE_1_USER", oauth.getProfile(response.getAccessToken()).getUsername());
+ Assert.assertEquals(keycloakRule.getUser("Test", "REALM_ROLE_1_USER").getId(), token.getSubject());
Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AccountTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AccountTest.java
index 4168e9f..0aa9075 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AccountTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AccountTest.java
@@ -21,7 +21,6 @@
*/
package org.keycloak.testsuite.forms;
-import org.apache.http.HttpResponse;
import org.junit.*;
import org.keycloak.models.*;
import org.keycloak.models.utils.TimeBasedOTP;
@@ -35,10 +34,6 @@ import org.keycloak.testsuite.rule.KeycloakRule.KeycloakSetup;
import org.keycloak.testsuite.rule.WebResource;
import org.keycloak.testsuite.rule.WebRule;
import org.openqa.selenium.WebDriver;
-import org.openqa.selenium.WebElement;
-import org.openqa.selenium.support.FindBy;
-
-import java.util.List;
import static org.junit.Assert.assertEquals;
@@ -53,7 +48,7 @@ public class AccountTest {
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
UserModel user = appRealm.getUser("test-user@localhost");
- ApplicationModel accountApp = appRealm.getApplicationNameMap().get(org.keycloak.models.Constants.ACCOUNT_APPLICATION);
+ ApplicationModel accountApp = appRealm.getApplicationNameMap().get(org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_APP);
UserModel user2 = appRealm.addUser("test-user-no-access@localhost");
user2.setEnabled(true);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
index 964a7d3..b894e2c 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
@@ -25,8 +25,10 @@ import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
+import org.keycloak.models.RealmModel;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.services.managers.RealmManager;
import org.keycloak.testsuite.OAuthClient;
import org.keycloak.testsuite.OAuthClient.AccessTokenResponse;
import org.keycloak.testsuite.pages.LoginPage;
@@ -70,11 +72,8 @@ public class AccessTokenTest {
AccessToken token = oauth.verifyToken(response.getAccessToken());
- UserRepresentation user = oauth.getProfile(response.getAccessToken());
-
- Assert.assertEquals(user.getId(), token.getSubject());
+ Assert.assertEquals(keycloakRule.getUser("test", "test-user@localhost").getId(), token.getSubject());
Assert.assertNotEquals("test-user@localhost", token.getSubject());
- Assert.assertEquals("test-user@localhost", user.getUsername());
Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
Assert.assertTrue(token.getRealmAccess().isUserInRole("user"));
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
index a213b72..8d9b742 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
@@ -148,20 +148,6 @@ public class OAuthClient {
}
}
- public UserRepresentation getProfile(String token) {
- HttpClient client = new DefaultHttpClient();
- HttpGet get = new HttpGet(baseUrl + "/realms/" + realm + "/account");
- get.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
- get.setHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.getMimeType());
-
- try {
- HttpResponse response = client.execute(get);
- return JsonSerialization.readValue(response.getEntity().getContent(), UserRepresentation.class);
- } catch (Exception e) {
- throw new RuntimeException("Failed to retrieve profile", e);
- }
- }
-
public AccessToken verifyToken(String token) {
try {
return RSATokenVerifier.verifyToken(token, realmPublicKey, realm);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
index caf6c58..a595694 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
@@ -7,6 +7,8 @@ import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.services.managers.ModelToRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.testutils.KeycloakServer;
import org.keycloak.util.JsonSerialization;
@@ -31,6 +33,24 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
setupKeycloak();
}
+ public UserRepresentation getUser(String realm, String name) {
+ KeycloakSession session = server.getKeycloakSessionFactory().createSession();
+ try {
+ return ModelToRepresentation.toRepresentation(session.getRealmByName(realm).getUser(name));
+ } finally {
+ session.close();
+ }
+ }
+
+ public UserRepresentation getUserById(String realm, String id) {
+ KeycloakSession session = server.getKeycloakSessionFactory().createSession();
+ try {
+ return ModelToRepresentation.toRepresentation(session.getRealmByName(realm).getUserById(id));
+ } finally {
+ session.close();
+ }
+ }
+
protected void setupKeycloak() {
KeycloakSession session = server.getKeycloakSessionFactory().createSession();
session.getTransaction().begin();
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/social/SocialLoginTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/social/SocialLoginTest.java
index 7f4e17a..27e7a87 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/social/SocialLoginTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/social/SocialLoginTest.java
@@ -26,6 +26,9 @@ import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
+import org.keycloak.models.AccountRoles;
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.Constants;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.idm.UserRepresentation;
@@ -107,7 +110,7 @@ public class SocialLoginTest {
AccessToken token = oauth.verifyToken(response.getAccessToken());
Assert.assertEquals(36, token.getSubject().length());
- UserRepresentation profile = oauth.getProfile(response.getAccessToken());
+ UserRepresentation profile = keycloakRule.getUserById("test", token.getSubject());
Assert.assertEquals(36, profile.getUsername().length());
Assert.assertEquals("Bob", profile.getFirstName());
@@ -146,7 +149,9 @@ public class SocialLoginTest {
Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
AccessTokenResponse response = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get("code"), "password");
- UserRepresentation profile = oauth.getProfile(response.getAccessToken());
+ AccessToken token = oauth.verifyToken(response.getAccessToken());
+
+ UserRepresentation profile = keycloakRule.getUserById("test", token.getSubject());
Assert.assertEquals("Dummy", profile.getFirstName());
Assert.assertEquals("User", profile.getLastName());