@@ -13,7 +13,7 @@
  • Role Mappings
  • {{user.username}}'s Role Mappings

    - +
    Realm Roles @@ -54,7 +54,7 @@
    -
    diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/user-detail.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/user-detail.html index c258661b42..4ce093a959 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/user-detail.html +++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/user-detail.html @@ -3,7 +3,7 @@ @@ -22,7 +22,7 @@

    {{user.username}}'s Attributes

    - + * Required fields
    @@ -79,12 +79,12 @@
    -
    +
    -
    +
    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 715a3a7418..307aab64ca 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 @@ \ No newline at end of file diff --git a/model/api/src/main/java/org/keycloak/models/AdminRoles.java b/model/api/src/main/java/org/keycloak/models/AdminRoles.java index ab414bf992..a156be7430 100644 --- a/model/api/src/main/java/org/keycloak/models/AdminRoles.java +++ b/model/api/src/main/java/org/keycloak/models/AdminRoles.java @@ -9,12 +9,17 @@ public class AdminRoles { public static String ADMIN = "admin"; + public static String VIEW_REALM = "view-realm"; + public static String VIEW_USERS = "view-users"; + public static String VIEW_APPLICATIONS = "view-applications"; + public static String VIEW_CLIENTS = "view-clients"; + 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[] ALL_REALM_ROLES = {VIEW_REALM, VIEW_USERS, VIEW_APPLICATIONS, VIEW_CLIENTS, MANAGE_REALM, MANAGE_USERS, MANAGE_APPLICATIONS, MANAGE_CLIENTS}; public static String getAdminApp(RealmModel realm) { return realm.getName() + APP_SUFFIX; diff --git a/services/src/main/java/org/keycloak/services/managers/Auth.java b/services/src/main/java/org/keycloak/services/managers/Auth.java index 3a2b21ce28..6bc86288d6 100644 --- a/services/src/main/java/org/keycloak/services/managers/Auth.java +++ b/services/src/main/java/org/keycloak/services/managers/Auth.java @@ -1,23 +1,14 @@ 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 Stian Thorgersen */ public class Auth { + private final boolean cookie; private final RealmModel realm; private final AccessToken token; @@ -62,45 +53,25 @@ public class Auth { 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) { + public boolean hasRealmRole(String role) { + if (cookie) { return realm.hasRole(user, realm.getRole(role)); } else { - return token.getRealmAccess() != null && token.getRealmAccess().isUserInRole(role); + AccessToken.Access access = token.getRealmAccess(); + return access != null && access.isUserInRole(role); } } - public boolean has(String app, String role) { + public boolean hasOneOfRealmRole(String... roles) { + for (String r : roles) { + if (hasRealmRole(r)) { + return true; + } + } + return false; + } + + public boolean hasAppRole(String app, String role) { if (cookie) { return realm.hasRole(user, realm.getApplicationByName(app).getRole(role)); } else { @@ -109,30 +80,13 @@ public class Auth { } } - 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) { + public boolean hasOneOfAppRole(String app, String... roles) { for (String r : roles) { - if (has(app, r)) { + if (hasAppRole(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/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java index 407d2c9b4a..a3afea9b38 100755 --- a/services/src/main/java/org/keycloak/services/resources/AccountService.java +++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java @@ -81,7 +81,7 @@ public class AccountService { Auth auth = getAuth(false); if (auth != null) { try { - auth.require(application, AccountRoles.MANAGE_ACCOUNT); + require(auth, AccountRoles.MANAGE_ACCOUNT); } catch (ForbiddenException e) { return Flows.forms(realm, request, uriInfo).setError("No access").createErrorPage(); } @@ -113,7 +113,7 @@ public class AccountService { return forwardToPage(null, AccountPages.ACCOUNT); } else if (types.contains(MediaType.APPLICATION_JSON_TYPE)) { Auth auth = getAuth(true); - auth.requireOneOf(application, AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_PROFILE); + requireOneOf(auth, AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_PROFILE); return Cors.add(request, Response.ok(ModelToRepresentation.toRepresentation(auth.getUser()))).auth().allowedOrigins(auth.getClient()).build(); } else { @@ -138,7 +138,7 @@ public class AccountService { @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response processAccountUpdate(final MultivaluedMap formData) { Auth auth = getAuth(true); - auth.require(application, AccountRoles.MANAGE_ACCOUNT); + require(auth, AccountRoles.MANAGE_ACCOUNT); UserModel user = auth.getUser(); @@ -160,7 +160,7 @@ public class AccountService { @GET public Response processTotpRemove() { Auth auth = getAuth(true); - auth.require(application, AccountRoles.MANAGE_ACCOUNT); + require(auth, AccountRoles.MANAGE_ACCOUNT); UserModel user = auth.getUser(); user.setTotp(false); @@ -174,7 +174,7 @@ public class AccountService { @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response processTotpUpdate(final MultivaluedMap formData) { Auth auth = getAuth(true); - auth.require(application, AccountRoles.MANAGE_ACCOUNT); + require(auth, AccountRoles.MANAGE_ACCOUNT); UserModel user = auth.getUser(); @@ -204,7 +204,7 @@ public class AccountService { @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response processPasswordUpdate(final MultivaluedMap formData) { Auth auth = getAuth(true); - auth.require(application, AccountRoles.MANAGE_ACCOUNT); + require(auth, AccountRoles.MANAGE_ACCOUNT); UserModel user = auth.getUser(); @@ -345,4 +345,16 @@ public class AccountService { return null; } + public void require(Auth auth, String role) { + if (!auth.hasAppRole(application.getName(), role)) { + throw new ForbiddenException(); + } + } + + public void requireOneOf(Auth auth, String... roles) { + if (!auth.hasOneOfAppRole(application.getName(), roles)) { + throw new ForbiddenException(); + } + } + } 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 7a5719ad7e..7a3fad1ba2 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 @@ -234,6 +234,7 @@ public class AdminService { if (auth == null) { throw new NotAuthorizedException("Bearer"); } + RealmsAdminResource adminResource = new RealmsAdminResource(auth, tokenManager); resourceContext.initResource(adminResource); return adminResource; diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java index 3fa6d1b1fb..92c184592a 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java @@ -34,9 +34,10 @@ import java.util.Set; * @author Bill Burke * @version $Revision: 1 $ */ -public class ApplicationResource extends RoleContainerResource { +public class ApplicationResource { protected static final Logger logger = Logger.getLogger(RealmAdminResource.class); protected RealmModel realm; + private RealmAuth auth; protected ApplicationModel application; protected KeycloakSession session; @Context @@ -49,16 +50,20 @@ public class ApplicationResource extends RoleContainerResource { return (KeycloakApplication)keycloak; } - public ApplicationResource(RealmModel realm, ApplicationModel applicationModel, KeycloakSession session) { - super(realm, applicationModel); + public ApplicationResource(RealmModel realm, RealmAuth auth, ApplicationModel applicationModel, KeycloakSession session) { this.realm = realm; + this.auth = auth; this.application = applicationModel; this.session = session; + + auth.init(RealmAuth.Resource.APPLICATION); } @PUT @Consumes(MediaType.APPLICATION_JSON) public void update(final ApplicationRepresentation rep) { + auth.requireManage(); + ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session)); applicationManager.updateApplication(rep, application); } @@ -68,6 +73,8 @@ public class ApplicationResource extends RoleContainerResource { @NoCache @Produces(MediaType.APPLICATION_JSON) public ApplicationRepresentation getApplication() { + auth.requireView(); + ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session)); return applicationManager.toRepresentation(application); } @@ -78,6 +85,8 @@ public class ApplicationResource extends RoleContainerResource { @Path("installation/json") @Produces(MediaType.APPLICATION_JSON) public String getInstallation() throws IOException { + auth.requireView(); + ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session)); Object rep = applicationManager.toInstallationRepresentation(realm, application, getKeycloakApplication().getBaseUri(uriInfo)); @@ -90,6 +99,8 @@ public class ApplicationResource extends RoleContainerResource { @Path("installation/jboss") @Produces(MediaType.TEXT_PLAIN) public String getJBossInstallation() throws IOException { + auth.requireView(); + ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session)); return applicationManager.toJBossSubsystemConfig(realm, application, getKeycloakApplication().getBaseUri(uriInfo)); } @@ -97,6 +108,8 @@ public class ApplicationResource extends RoleContainerResource { @DELETE @NoCache public void deleteApplication() { + auth.requireManage(); + realm.removeApplication(application.getId()); } @@ -105,6 +118,8 @@ public class ApplicationResource extends RoleContainerResource { @Produces("application/json") @Consumes("application/json") public CredentialRepresentation regenerateSecret() { + auth.requireManage(); + logger.debug("regenerateSecret"); UserCredentialModel cred = new ApplicationManager().generateSecret(realm, application); CredentialRepresentation rep = ModelToRepresentation.toRepresentation(cred); @@ -115,6 +130,8 @@ public class ApplicationResource extends RoleContainerResource { @GET @Produces("application/json") public CredentialRepresentation getClientSecret() { + auth.requireView(); + logger.debug("getClientSecret"); UserCredentialModel model = realm.getSecret(application.getApplicationUser()); if (model == null) throw new NotFoundException("Application does not have a secret"); @@ -124,7 +141,12 @@ public class ApplicationResource extends RoleContainerResource { @Path("scope-mappings") public ScopeMappedResource getScopeMappedResource() { - return new ScopeMappedResource(realm, application.getApplicationUser(), session); + return new ScopeMappedResource(realm, auth, application.getApplicationUser(), session); + } + + @Path("roles") + public RoleContainerResource getRoleContainerResource() { + return new RoleContainerResource(realm, auth, application); } @Path("allowed-origins") @@ -132,6 +154,8 @@ public class ApplicationResource extends RoleContainerResource { @Produces("application/json") public Set getAllowedOrigins() { + auth.requireView(); + return application.getApplicationUser().getWebOrigins(); } @@ -140,6 +164,8 @@ public class ApplicationResource extends RoleContainerResource { @Consumes("application/json") public void updateAllowedOrigins(Set allowedOrigins) { + auth.requireManage(); + application.getApplicationUser().setWebOrigins(allowedOrigins); } @@ -148,6 +174,8 @@ public class ApplicationResource extends RoleContainerResource { @Consumes("application/json") public void deleteAllowedOrigins(Set allowedOrigins) { + auth.requireManage(); + for (String origin : allowedOrigins) { application.getApplicationUser().removeWebOrigin(origin); } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java index 4f9d5ca7df..6387e00c50 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java @@ -32,6 +32,7 @@ import java.util.List; public class ApplicationsResource { protected static final Logger logger = Logger.getLogger(RealmAdminResource.class); protected RealmModel realm; + private RealmAuth auth; @Context protected ResourceContext resourceContext; @@ -39,19 +40,32 @@ public class ApplicationsResource { @Context protected KeycloakSession session; - public ApplicationsResource(RealmModel realm) { + public ApplicationsResource(RealmModel realm, RealmAuth auth) { this.realm = realm; + this.auth = auth; + + auth.init(RealmAuth.Resource.APPLICATION); } @GET @Produces(MediaType.APPLICATION_JSON) @NoCache public List getApplications() { + auth.requireAny(); + List rep = new ArrayList(); List applicationModels = realm.getApplications(); ApplicationManager resourceManager = new ApplicationManager(new RealmManager(session)); + + boolean view = auth.hasView(); for (ApplicationModel applicationModel : applicationModels) { - rep.add(resourceManager.toRepresentation(applicationModel)); + if (view) { + rep.add(resourceManager.toRepresentation(applicationModel)); + } else { + ApplicationRepresentation app = new ApplicationRepresentation(); + app.setName(applicationModel.getName()); + rep.add(app); + } } return rep; } @@ -59,6 +73,8 @@ public class ApplicationsResource { @POST @Consumes(MediaType.APPLICATION_JSON) public Response createApplication(final @Context UriInfo uriInfo, final ApplicationRepresentation rep) { + auth.requireManage(); + if (realm.getApplicationNameMap().containsKey(rep.getName())) { return Flows.errors().exists("Application " + rep.getName() + " already exists"); } @@ -73,7 +89,7 @@ public class ApplicationsResource { if (applicationModel == null) { throw new NotFoundException("Could not find application: " + name); } - ApplicationResource applicationResource = new ApplicationResource(realm, applicationModel, session); + ApplicationResource applicationResource = new ApplicationResource(realm, auth, applicationModel, session); resourceContext.initResource(applicationResource); return applicationResource; } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java index 9bdc837484..7ae8fe33cb 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java @@ -38,6 +38,7 @@ import java.util.List; public class OAuthClientResource { protected static final Logger logger = Logger.getLogger(RealmAdminResource.class); protected RealmModel realm; + private RealmAuth auth; protected OAuthClientModel oauthClient; protected KeycloakSession session; @Context @@ -50,15 +51,20 @@ public class OAuthClientResource { return (KeycloakApplication)application; } - public OAuthClientResource(RealmModel realm, OAuthClientModel oauthClient, KeycloakSession session) { + public OAuthClientResource(RealmModel realm, RealmAuth auth, OAuthClientModel oauthClient, KeycloakSession session) { this.realm = realm; + this.auth = auth; this.oauthClient = oauthClient; this.session = session; + + auth.init(RealmAuth.Resource.CLIENT); } @PUT @Consumes(MediaType.APPLICATION_JSON) public void update(final OAuthClientRepresentation rep) { + auth.requireManage(); + OAuthClientManager manager = new OAuthClientManager(realm); manager.update(rep, oauthClient); } @@ -68,6 +74,8 @@ public class OAuthClientResource { @NoCache @Produces(MediaType.APPLICATION_JSON) public OAuthClientRepresentation getOAuthClient() { + auth.requireView(); + return OAuthClientManager.toRepresentation(oauthClient); } @@ -76,6 +84,8 @@ public class OAuthClientResource { @Path("installation") @Produces(MediaType.APPLICATION_JSON) public String getInstallation() throws IOException { + auth.requireView(); + OAuthClientManager manager = new OAuthClientManager(realm); Object rep = manager.toInstallationRepresentation(realm, oauthClient, getApplication().getBaseUri(uriInfo)); @@ -86,6 +96,8 @@ public class OAuthClientResource { @DELETE @NoCache public void deleteOAuthClient() { + auth.requireManage(); + realm.removeOAuthClient(oauthClient.getId()); } @@ -94,6 +106,8 @@ public class OAuthClientResource { @Produces("application/json") @Consumes("application/json") public CredentialRepresentation regenerateSecret() { + auth.requireManage(); + logger.debug("regenerateSecret"); UserCredentialModel cred = UserCredentialModel.generateSecret(); realm.updateCredential(oauthClient.getOAuthAgent(), cred); @@ -105,6 +119,8 @@ public class OAuthClientResource { @GET @Produces("application/json") public CredentialRepresentation getClientSecret() { + auth.requireView(); + logger.debug("getClientSecret"); UserCredentialModel model = realm.getSecret(oauthClient.getOAuthAgent()); if (model == null) throw new NotFoundException("Application does not have a secret"); @@ -113,7 +129,7 @@ public class OAuthClientResource { @Path("scope-mappings") public ScopeMappedResource getScopeMappedResource() { - return new ScopeMappedResource(realm, oauthClient.getOAuthAgent(), session); + return new ScopeMappedResource(realm, auth, oauthClient.getOAuthAgent(), session); } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java index eaacae6399..445622429a 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java @@ -35,10 +35,14 @@ public class OAuthClientsResource { @Context protected ResourceContext resourceContext; + private RealmAuth auth; - public OAuthClientsResource(RealmModel realm, KeycloakSession session) { + public OAuthClientsResource(RealmModel realm, RealmAuth auth, KeycloakSession session) { + this.auth = auth; this.realm = realm; this.session = session; + + auth.init(RealmAuth.Resource.CLIENT); } @GET @@ -47,8 +51,16 @@ public class OAuthClientsResource { public List getOAuthClients() { List rep = new ArrayList(); List oauthModels = realm.getOAuthClients(); + + boolean view = auth.hasView(); for (OAuthClientModel oauth : oauthModels) { - rep.add(OAuthClientManager.toRepresentation(oauth)); + if (view) { + rep.add(OAuthClientManager.toRepresentation(oauth)); + } else { + OAuthClientRepresentation client = new OAuthClientRepresentation(); + client.setName(oauth.getOAuthAgent().getLoginName()); + rep.add(client); + } } return rep; } @@ -56,6 +68,8 @@ public class OAuthClientsResource { @POST @Consumes(MediaType.APPLICATION_JSON) public Response createOAuthClient(final @Context UriInfo uriInfo, final OAuthClientRepresentation rep) { + auth.requireManage(); + OAuthClientManager resourceManager = new OAuthClientManager(realm); OAuthClientModel oauth = resourceManager.create(rep); return Response.created(uriInfo.getAbsolutePathBuilder().path(oauth.getId()).build()).build(); @@ -63,11 +77,13 @@ public class OAuthClientsResource { @Path("{id}") public OAuthClientResource getOAuthClient(final @PathParam("id") String id) { + auth.requireView(); + OAuthClientModel oauth = realm.getOAuthClientById(id); if (oauth == null) { throw new NotFoundException(); } - OAuthClientResource oAuthClientResource = new OAuthClientResource(realm, oauth, session); + OAuthClientResource oAuthClientResource = new OAuthClientResource(realm, auth, oauth, session); resourceContext.initResource(oAuthClientResource); return oAuthClientResource; } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java index 5ea09877a8..7f2f020e40 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 @@ -19,9 +19,9 @@ import javax.ws.rs.core.Context; * @author Bill Burke * @version $Revision: 1 $ */ -public class RealmAdminResource extends RoleContainerResource { +public class RealmAdminResource { protected static final Logger logger = Logger.getLogger(RealmAdminResource.class); - protected Auth auth; + protected RealmAuth auth; protected RealmModel realm; private TokenManager tokenManager; @@ -31,43 +31,43 @@ public class RealmAdminResource extends RoleContainerResource { @Context protected KeycloakSession session; - public RealmAdminResource(Auth auth, RealmModel realm, TokenManager tokenManager) { - super(realm, realm); + public RealmAdminResource(RealmAuth auth, RealmModel realm, TokenManager tokenManager) { this.auth = auth; this.realm = realm; this.tokenManager = tokenManager; + + auth.init(RealmAuth.Resource.REALM); } @Path("applications") public ApplicationsResource getApplications() { - auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_APPLICATIONS); - - ApplicationsResource applicationsResource = new ApplicationsResource(realm); + ApplicationsResource applicationsResource = new ApplicationsResource(realm, auth); resourceContext.initResource(applicationsResource); return applicationsResource; } @Path("oauth-clients") public OAuthClientsResource getOAuthClients() { - auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_CLIENTS); - - OAuthClientsResource oauth = new OAuthClientsResource(realm, session); + OAuthClientsResource oauth = new OAuthClientsResource(realm, auth, session); resourceContext.initResource(oauth); return oauth; } + @Path("roles") + public RoleContainerResource getRoleContainerResource() { + return new RoleContainerResource(realm, auth, realm); + } + @GET @NoCache @Produces("application/json") public RealmRepresentation getRealm() { - String realmAdminApp = AdminRoles.getAdminApp(realm); - if (auth.has(realmAdminApp, AdminRoles.MANAGE_REALM)) { + if (auth.hasView()) { return ModelToRepresentation.toRepresentation(realm); } else { - auth.requireOneOf(AdminRoles.getAdminApp(realm), AdminRoles.ALL_REALM_ROLES); + auth.requireAny(); RealmRepresentation rep = new RealmRepresentation(); - rep.setId(realm.getId()); rep.setRealm(realm.getName()); return rep; @@ -77,15 +77,15 @@ public class RealmAdminResource extends RoleContainerResource { @PUT @Consumes("application/json") public void updateRealm(final RealmRepresentation rep) { - auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_REALM); + auth.requireManage(); logger.debug("updating realm: " + realm.getName()); new RealmManager(session).updateRealm(rep, realm); } @DELETE - public void deleteRealms() { - auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_REALM); + public void deleteRealm() { + auth.requireManage(); if (!new RealmManager(session).removeRealm(realm)) { throw new NotFoundException(); @@ -94,18 +94,14 @@ public class RealmAdminResource extends RoleContainerResource { @Path("users") public UsersResource users() { - auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_USERS); - - UsersResource users = new UsersResource(realm, tokenManager); + UsersResource users = new UsersResource(realm, auth, tokenManager); resourceContext.initResource(users); return users; } @Path("roles-by-id") public RoleByIdResource rolesById() { - auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_REALM); - - RoleByIdResource resource = new RoleByIdResource(realm); + RoleByIdResource resource = new RoleByIdResource(realm, auth); resourceContext.initResource(resource); return resource; } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java new file mode 100644 index 0000000000..d059c4c68c --- /dev/null +++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java @@ -0,0 +1,88 @@ +package org.keycloak.services.resources.admin; + +import org.keycloak.models.AdminRoles; +import org.keycloak.services.managers.Auth; + +import javax.ws.rs.ForbiddenException; + +/** + * @author Stian Thorgersen + */ +public class RealmAuth { + + private Resource resource; + + public enum Resource { + APPLICATION, CLIENT, USER, REALM + } + + private Auth auth; + private String realmAdminApp; + + public RealmAuth(Auth auth, String realmAdminApp) { + this.auth = auth; + this.realmAdminApp = realmAdminApp; + } + + public RealmAuth init(Resource resource) { + this.resource = resource; + return this; + } + + public void requireAny() { + if (!auth.hasOneOfAppRole(realmAdminApp, AdminRoles.ALL_REALM_ROLES)) { + throw new ForbiddenException(); + } + } + + public boolean hasView() { + return auth.hasOneOfAppRole(realmAdminApp, getViewRole(resource), getManageRole(resource)); + } + + public boolean hasManage() { + return auth.hasOneOfAppRole(realmAdminApp, getManageRole(resource)); + } + + public void requireView() { + if (!hasView()) { + throw new ForbiddenException(); + } + } + + public void requireManage() { + if (!hasManage()) { + throw new ForbiddenException(); + } + } + + private String getViewRole(Resource resource) { + switch (resource) { + case APPLICATION: + return AdminRoles.VIEW_APPLICATIONS; + case CLIENT: + return AdminRoles.VIEW_CLIENTS; + case USER: + return AdminRoles.VIEW_USERS; + case REALM: + return AdminRoles.VIEW_REALM; + default: + throw new IllegalStateException(); + } + } + + private String getManageRole(Resource resource) { + switch (resource) { + case APPLICATION: + return AdminRoles.MANAGE_APPLICATIONS; + case CLIENT: + return AdminRoles.MANAGE_CLIENTS; + case USER: + return AdminRoles.MANAGE_USERS; + case REALM: + return AdminRoles.MANAGE_REALM; + default: + throw new IllegalStateException(); + } + } + +} diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java index f0691d4517..c2cbafb021 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 @@ -6,8 +6,6 @@ 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.representations.idm.RealmRepresentation; @@ -67,11 +65,10 @@ public class RealmsAdminResource { for (RealmModel realm : realms) { String realmAdminApp = AdminRoles.getAdminApp(realm); - if (auth.has(realmAdminApp, AdminRoles.MANAGE_REALM)) { + if (auth.hasAppRole(realmAdminApp, AdminRoles.MANAGE_REALM)) { reps.add(ModelToRepresentation.toRepresentation(realm)); - } else if (auth.hasOneOf(realmAdminApp, AdminRoles.ALL_REALM_ROLES)) { + } else if (auth.hasOneOfAppRole(realmAdminApp, AdminRoles.ALL_REALM_ROLES)) { RealmRepresentation rep = new RealmRepresentation(); - rep.setId(realm.getId()); rep.setRealm(realm.getName()); reps.add(rep); } @@ -90,7 +87,9 @@ public class RealmsAdminResource { @POST @Consumes("application/json") public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) { - auth.require(AdminRoles.ADMIN); + if (!auth.hasRealmRole(AdminRoles.ADMIN)) { + throw new ForbiddenException(); + } logger.debug("importRealm: {0}", rep.getRealm()); RealmManager realmManager = new RealmManager(session); @@ -107,7 +106,9 @@ public class RealmsAdminResource { @POST @Consumes(MediaType.MULTIPART_FORM_DATA) public Response uploadRealm(MultipartFormDataInput input) throws IOException { - auth.require(AdminRoles.ADMIN); + if (!auth.hasRealmRole(AdminRoles.ADMIN)) { + throw new ForbiddenException(); + } Map> uploadForm = input.getFormDataMap(); List inputParts = uploadForm.get("file"); @@ -128,9 +129,9 @@ public class RealmsAdminResource { RealmModel realm = realmManager.getRealmByName(name); if (realm == null) throw new NotFoundException("{realm} = " + name); - auth.requireOneOf(AdminRoles.getAdminApp(realm), AdminRoles.ALL_REALM_ROLES); + RealmAuth realmAuth = new RealmAuth(auth, AdminRoles.getAdminApp(realm)); - RealmAdminResource adminResource = new RealmAdminResource(auth, realm, tokenManager); + RealmAdminResource adminResource = new RealmAdminResource(realmAuth, realm, tokenManager); resourceContext.initResource(adminResource); return adminResource; } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java index 98869bfd68..f5b7cb0bc0 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java @@ -1,14 +1,13 @@ package org.keycloak.services.resources.admin; import org.jboss.resteasy.annotations.cache.NoCache; +import org.keycloak.models.ApplicationModel; import org.keycloak.models.Constants; +import org.keycloak.models.OAuthClientModel; import org.keycloak.models.RealmModel; -import org.keycloak.models.RoleContainerModel; import org.keycloak.models.RoleModel; +import org.keycloak.models.UserModel; import org.keycloak.representations.idm.RoleRepresentation; -import org.keycloak.services.managers.ModelToRepresentation; -import org.keycloak.services.resources.admin.RoleResource; -import org.keycloak.services.resources.flows.Flows; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -19,10 +18,6 @@ import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -33,8 +28,14 @@ import java.util.Set; * @version $Revision: 1 $ */ public class RoleByIdResource extends RoleResource { - public RoleByIdResource(RealmModel realm) { + private final RealmModel realm; + private final RealmAuth auth; + + public RoleByIdResource(RealmModel realm, RealmAuth auth) { super(realm); + + this.realm = realm; + this.auth = auth; } @Path("{role-id}") @@ -43,6 +44,7 @@ public class RoleByIdResource extends RoleResource { @Produces("application/json") public RoleRepresentation getRole(final @PathParam("role-id") String id) { RoleModel roleModel = getRoleModel(id); + auth.requireView(); return getRole(roleModel); } @@ -51,6 +53,19 @@ public class RoleByIdResource extends RoleResource { if (roleModel == null || roleModel.getName().startsWith(Constants.INTERNAL_ROLE)) { throw new NotFoundException("Could not find role with id: " + id); } + + RealmAuth.Resource r = null; + if (roleModel.getContainer() instanceof RealmModel) { + r = RealmAuth.Resource.REALM; + } else if (roleModel.getContainer() instanceof ApplicationModel) { + r = RealmAuth.Resource.APPLICATION; + } else if (roleModel.getContainer() instanceof OAuthClientModel) { + r = RealmAuth.Resource.CLIENT; + } else if (roleModel.getContainer() instanceof UserModel) { + r = RealmAuth.Resource.USER; + } + auth.init(r); + return roleModel; } @@ -59,6 +74,7 @@ public class RoleByIdResource extends RoleResource { @NoCache public void deleteRole(final @PathParam("role-id") String id) { RoleModel role = getRoleModel(id); + auth.requireManage(); deleteRole(role); } @@ -67,6 +83,7 @@ public class RoleByIdResource extends RoleResource { @Consumes("application/json") public void updateRole(final @PathParam("role-id") String id, final RoleRepresentation rep) { RoleModel role = getRoleModel(id); + auth.requireManage(); updateRole(rep, role); } @@ -75,6 +92,7 @@ public class RoleByIdResource extends RoleResource { @Consumes("application/json") public void addComposites(final @PathParam("role-id") String id, List roles) { RoleModel role = getRoleModel(id); + auth.requireManage(); addComposites(roles, role); } @@ -84,6 +102,7 @@ public class RoleByIdResource extends RoleResource { @Produces("application/json") public Set getRoleComposites(final @PathParam("role-id") String id) { RoleModel role = getRoleModel(id); + auth.requireView(); return getRoleComposites(role); } @@ -93,6 +112,7 @@ public class RoleByIdResource extends RoleResource { @Produces("application/json") public Set getRealmRoleComposites(final @PathParam("role-id") String id) { RoleModel role = getRoleModel(id); + auth.requireView(); return getRealmRoleComposites(role); } @@ -103,6 +123,7 @@ public class RoleByIdResource extends RoleResource { public Set getApplicationRoleComposites(final @PathParam("role-id") String id, final @PathParam("app") String appName) { RoleModel role = getRoleModel(id); + auth.requireView(); return getApplicationRoleComposites(appName, role); } @@ -112,8 +133,8 @@ public class RoleByIdResource extends RoleResource { @Consumes("application/json") public void deleteComposites(final @PathParam("role-id") String id, List roles) { RoleModel role = getRoleModel(id); + auth.requireManage(); deleteComposites(roles, role); } - } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java index e1f07fb333..5bbd44b6fd 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java @@ -1,7 +1,6 @@ package org.keycloak.services.resources.admin; import org.jboss.resteasy.annotations.cache.NoCache; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.Constants; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleContainerModel; @@ -10,13 +9,19 @@ import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.services.managers.ModelToRepresentation; import org.keycloak.services.resources.flows.Flows; -import javax.ws.rs.*; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Set; @@ -25,18 +30,24 @@ import java.util.Set; * @version $Revision: 1 $ */ public class RoleContainerResource extends RoleResource { + private final RealmModel realm; + private final RealmAuth auth; protected RoleContainerModel roleContainer; - public RoleContainerResource(RealmModel realm, RoleContainerModel roleContainer) { + public RoleContainerResource(RealmModel realm, RealmAuth auth, RoleContainerModel roleContainer) { super(realm); + this.realm = realm; + this.auth = auth; this.roleContainer = roleContainer; } - @Path("roles") + @Path("") @GET @NoCache @Produces("application/json") public List getRoles() { + auth.requireAny(); + Set roleModels = roleContainer.getRoles(); List roles = new ArrayList(); for (RoleModel roleModel : roleModels) { @@ -47,10 +58,12 @@ public class RoleContainerResource extends RoleResource { return roles; } - @Path("roles") + @Path("") @POST @Consumes("application/json") public Response createRole(final @Context UriInfo uriInfo, final RoleRepresentation rep) { + auth.requireManage(); + if (roleContainer.getRole(rep.getName()) != null || rep.getName().startsWith(Constants.INTERNAL_ROLE)) { return Flows.errors().exists("Role with name " + rep.getName() + " already exists"); } @@ -62,11 +75,13 @@ public class RoleContainerResource extends RoleResource { return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getName()).build()).build(); } - @Path("roles/{role-name}") + @Path("{role-name}") @GET @NoCache @Produces("application/json") public RoleRepresentation getRole(final @PathParam("role-name") String roleName) { + auth.requireView(); + RoleModel roleModel = roleContainer.getRole(roleName); if (roleModel == null || roleModel.getName().startsWith(Constants.INTERNAL_ROLE)) { throw new NotFoundException("Could not find role: " + roleName); @@ -74,10 +89,12 @@ public class RoleContainerResource extends RoleResource { return getRole(roleModel); } - @Path("roles/{role-name}") + @Path("{role-name}") @DELETE @NoCache public void deleteRole(final @PathParam("role-name") String roleName) { + auth.requireManage(); + RoleModel role = roleContainer.getRole(roleName); if (role == null) { throw new NotFoundException("Could not find role: " + roleName); @@ -85,10 +102,12 @@ public class RoleContainerResource extends RoleResource { deleteRole(role); } - @Path("roles/{role-name}") + @Path("{role-name}") @PUT @Consumes("application/json") public void updateRole(final @PathParam("role-name") String roleName, final RoleRepresentation rep) { + auth.requireManage(); + RoleModel role = roleContainer.getRole(roleName); if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) { throw new NotFoundException("Could not find role: " + roleName); @@ -96,10 +115,12 @@ public class RoleContainerResource extends RoleResource { updateRole(rep, role); } - @Path("roles/{role-name}/composites") + @Path("{role-name}/composites") @POST @Consumes("application/json") public void addComposites(final @PathParam("role-name") String roleName, List roles) { + auth.requireManage(); + RoleModel role = roleContainer.getRole(roleName); if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) { throw new NotFoundException("Could not find role: " + roleName); @@ -107,11 +128,13 @@ public class RoleContainerResource extends RoleResource { addComposites(roles, role); } - @Path("roles/{role-name}/composites") + @Path("{role-name}/composites") @GET @NoCache @Produces("application/json") public Set getRoleComposites(final @PathParam("role-name") String roleName) { + auth.requireManage(); + RoleModel role = roleContainer.getRole(roleName); if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) { throw new NotFoundException("Could not find role: " + roleName); @@ -119,11 +142,13 @@ public class RoleContainerResource extends RoleResource { return getRoleComposites(role); } - @Path("roles/{role-name}/composites/realm") + @Path("{role-name}/composites/realm") @GET @NoCache @Produces("application/json") public Set getRealmRoleComposites(final @PathParam("role-name") String roleName) { + auth.requireManage(); + RoleModel role = roleContainer.getRole(roleName); if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) { throw new NotFoundException("Could not find role: " + roleName); @@ -131,12 +156,14 @@ public class RoleContainerResource extends RoleResource { return getRealmRoleComposites(role); } - @Path("roles/{role-name}/composites/application/{app}") + @Path("{role-name}/composites/application/{app}") @GET @NoCache @Produces("application/json") public Set getApplicationRoleComposites(final @PathParam("role-name") String roleName, final @PathParam("app") String appName) { + auth.requireManage(); + RoleModel role = roleContainer.getRole(roleName); if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) { throw new NotFoundException("Could not find role: " + roleName); @@ -145,10 +172,12 @@ public class RoleContainerResource extends RoleResource { } - @Path("roles/{role-name}/composites") + @Path("{role-name}/composites") @DELETE @Consumes("application/json") public void deleteComposites(final @PathParam("role-name") String roleName, List roles) { + auth.requireManage(); + RoleModel role = roleContainer.getRole(roleName); if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) { throw new NotFoundException("Could not find role: " + roleName); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java index 91e42b44b8..94d95af59b 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java @@ -16,7 +16,7 @@ import java.util.Set; * @author Bill Burke * @version $Revision: 1 $ */ -public class RoleResource { +public abstract class RoleResource { protected RealmModel realm; public RoleResource(RealmModel realm) { diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java index c630d281f4..c5e8662c39 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java @@ -32,11 +32,13 @@ import java.util.Set; */ public class ScopeMappedResource { protected RealmModel realm; + private RealmAuth auth; protected UserModel agent; protected KeycloakSession session; - public ScopeMappedResource(RealmModel realm, UserModel account, KeycloakSession session) { + public ScopeMappedResource(RealmModel realm, RealmAuth auth, UserModel account, KeycloakSession session) { this.realm = realm; + this.auth = auth; this.agent = account; this.session = session; } @@ -45,6 +47,8 @@ public class ScopeMappedResource { @Produces("application/json") @NoCache public MappingsRepresentation getScopeMappings() { + auth.requireView(); + MappingsRepresentation all = new MappingsRepresentation(); Set realmMappings = realm.getRealmScopeMappings(agent); RealmManager manager = new RealmManager(session); @@ -83,6 +87,8 @@ public class ScopeMappedResource { @Produces("application/json") @NoCache public List getRealmScopeMappings() { + auth.requireView(); + Set realmMappings = realm.getRealmScopeMappings(agent); List realmMappingsRep = new ArrayList(); RealmManager manager = new RealmManager(session); @@ -96,6 +102,8 @@ public class ScopeMappedResource { @POST @Consumes("application/json") public void addRealmScopeMappings(List roles) { + auth.requireManage(); + for (RoleRepresentation role : roles) { RoleModel roleModel = realm.getRoleById(role.getId()); if (roleModel == null) { @@ -111,6 +119,8 @@ public class ScopeMappedResource { @DELETE @Consumes("application/json") public void deleteRealmScopeMappings(List roles) { + auth.requireManage(); + if (roles == null) { Set roleModels = realm.getRealmScopeMappings(agent); for (RoleModel roleModel : roleModels) { @@ -133,6 +143,8 @@ public class ScopeMappedResource { @Produces("application/json") @NoCache public List getApplicationScopeMappings(@PathParam("app") String appName) { + auth.requireView(); + ApplicationModel app = realm.getApplicationByName(appName); if (app == null) { @@ -151,6 +163,8 @@ public class ScopeMappedResource { @POST @Consumes("application/json") public void addApplicationScopeMapping(@PathParam("app") String appName, List roles) { + auth.requireManage(); + ApplicationModel app = realm.getApplicationByName(appName); if (app == null) { @@ -171,6 +185,8 @@ public class ScopeMappedResource { @DELETE @Consumes("application/json") public void deleteApplicationScopeMapping(@PathParam("app") String appName, List roles) { + auth.requireManage(); + ApplicationModel app = realm.getApplicationByName(appName); if (app == null) { 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 2af61a9e8d..212c6b6510 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 @@ -13,6 +13,7 @@ import org.keycloak.representations.idm.*; import org.keycloak.services.email.EmailException; import org.keycloak.services.email.EmailSender; import org.keycloak.services.managers.AccessCodeEntry; +import org.keycloak.services.managers.Auth; import org.keycloak.services.managers.ModelToRepresentation; import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.TokenManager; @@ -50,11 +51,15 @@ public class UsersResource { protected RealmModel realm; + private RealmAuth auth; private TokenManager tokenManager; - public UsersResource(RealmModel realm, TokenManager tokenManager) { + public UsersResource(RealmModel realm, RealmAuth auth, TokenManager tokenManager) { + this.auth = auth; this.realm = realm; this.tokenManager = tokenManager; + + auth.init(RealmAuth.Resource.USER); } @Context @@ -71,6 +76,8 @@ public class UsersResource { @PUT @Consumes("application/json") public void updateUser(final @PathParam("username") String username, final UserRepresentation rep) { + auth.requireManage(); + UserModel user = realm.getUser(username); if (user == null) { throw new NotFoundException(); @@ -81,6 +88,8 @@ public class UsersResource { @POST @Consumes("application/json") public Response createUser(final @Context UriInfo uriInfo, final UserRepresentation rep) { + auth.requireManage(); + if (realm.getUser(rep.getUsername()) != null) { return Flows.errors().exists("User with username " + rep.getUsername() + " already exists"); } @@ -125,6 +134,8 @@ public class UsersResource { @NoCache @Produces("application/json") public UserRepresentation getUser(final @PathParam("username") String username) { + auth.requireView(); + UserModel user = realm.getUser(username); if (user == null || !isUser(user)) { throw new NotFoundException(); @@ -136,6 +147,8 @@ public class UsersResource { @DELETE @NoCache public void deleteUser(final @PathParam("username") String username) { + auth.requireManage(); + realm.removeUser(username); } @@ -147,6 +160,8 @@ public class UsersResource { @QueryParam("firstName") String first, @QueryParam("email") String email, @QueryParam("username") String username) { + auth.requireView(); + RealmManager manager = new RealmManager(session); List results = new ArrayList(); List userModels; @@ -191,6 +206,8 @@ public class UsersResource { @Produces("application/json") @NoCache public MappingsRepresentation getRoleMappings(@PathParam("username") String username) { + auth.requireView(); + UserModel user = realm.getUser(username); if (user == null) { throw new NotFoundException(); @@ -234,6 +251,8 @@ public class UsersResource { @Produces("application/json") @NoCache public List getRealmRoleMappings(@PathParam("username") String username) { + auth.requireView(); + UserModel user = realm.getUser(username); if (user == null) { throw new NotFoundException(); @@ -252,6 +271,8 @@ public class UsersResource { @POST @Consumes("application/json") public void addRealmRoleMappings(@PathParam("username") String username, List roles) { + auth.requireManage(); + logger.debug("** addRealmRoleMappings: {0}", roles); UserModel user = realm.getUser(username); if (user == null) { @@ -273,6 +294,8 @@ public class UsersResource { @DELETE @Consumes("application/json") public void deleteRealmRoleMappings(@PathParam("username") String username, List roles) { + auth.requireManage(); + logger.debug("deleteRealmRoleMappings"); UserModel user = realm.getUser(username); if (user == null) { @@ -301,6 +324,8 @@ public class UsersResource { @Produces("application/json") @NoCache public List getApplicationRoleMappings(@PathParam("username") String username, @PathParam("app") String appName) { + auth.requireView(); + logger.debug("getApplicationRoleMappings"); UserModel user = realm.getUser(username); @@ -327,6 +352,8 @@ public class UsersResource { @POST @Consumes("application/json") public void addApplicationRoleMapping(@PathParam("username") String username, @PathParam("app") String appName, List roles) { + auth.requireManage(); + logger.debug("addApplicationRoleMapping"); UserModel user = realm.getUser(username); if (user == null) { @@ -353,6 +380,8 @@ public class UsersResource { @DELETE @Consumes("application/json") public void deleteApplicationRoleMapping(@PathParam("username") String username, @PathParam("app") String appName, List roles) { + auth.requireManage(); + UserModel user = realm.getUser(username); if (user == null) { throw new NotFoundException(); @@ -389,6 +418,8 @@ public class UsersResource { @PUT @Consumes("application/json") public void resetPassword(@PathParam("username") String username, CredentialRepresentation pass) { + auth.requireManage(); + UserModel user = realm.getUser(username); if (user == null) { throw new NotFoundException(); @@ -406,6 +437,8 @@ public class UsersResource { @PUT @Consumes("application/json") public void removeTotp(@PathParam("username") String username) { + auth.requireManage(); + UserModel user = realm.getUser(username); if (user == null) { throw new NotFoundException(); @@ -418,6 +451,8 @@ public class UsersResource { @PUT @Consumes("application/json") public Response resetPasswordEmail(@PathParam("username") String username) { + auth.requireManage(); + UserModel user = realm.getUser(username); if (user == null) { throw new NotFoundException();