keycloak-aplcache
Changes
integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientsResource.java 4(+4 -0)
services/src/main/java/org/keycloak/authorization/admin/permissions/MgmtPermissions.java 118(+0 -118)
services/src/main/java/org/keycloak/authorization/admin/permissions/RoleMgmtPermissions.java 208(+0 -208)
services/src/main/java/org/keycloak/authorization/admin/permissions/UsersPermissions.java 246(+0 -246)
services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java 68(+34 -34)
services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java 43(+10 -33)
services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java 12(+6 -6)
services/src/main/java/org/keycloak/services/resources/admin/ClientRegistrationPolicyResource.java 6(+3 -3)
services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java 63(+16 -47)
services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java 31(+12 -19)
services/src/main/java/org/keycloak/services/resources/admin/ClientTemplatesResource.java 25(+10 -15)
services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java 25(+13 -12)
services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java 18(+9 -9)
services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissionEvaluator.java 55(+55 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissionManagement.java 35(+35 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissions.java 43(+43 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java 68(+68 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionManagement.java 29(+29 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java 309(+309 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionEvaluator.java 53(+53 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionManagement.java 37(+37 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissions.java 383(+383 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/MgmtPermissions.java 274(+274 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmPermissionEvaluator.java 59(+59 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmPermissions.java 188(+188 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissionEvaluator.java 47(+47 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissionManagement.java 56(+56 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissions.java 378(+378 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java 46(+46 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionManagement.java 41(+41 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java 382(+382 -0)
services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java 58(+18 -40)
services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java 109(+31 -78)
services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedClientResource.java 43(+15 -28)
services/src/main/java/org/keycloak/services/resources/admin/UserStorageProviderResource.java 15(+7 -8)
Details
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientsResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientsResource.java
index 47b4db4..3c8552e 100755
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientsResource.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientsResource.java
@@ -48,6 +48,10 @@ public interface ClientsResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
+ public List<ClientRepresentation> findAll(@QueryParam("viewableOnly") boolean viewableOnly);
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
public List<ClientRepresentation> findByClientId(@QueryParam("clientId") String clientId);
diff --git a/services/src/main/java/org/keycloak/authorization/admin/AuthorizationService.java b/services/src/main/java/org/keycloak/authorization/admin/AuthorizationService.java
index a4ff868..d062856 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/AuthorizationService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/AuthorizationService.java
@@ -23,7 +23,7 @@ import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
-import org.keycloak.services.resources.admin.RealmAuth;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import javax.ws.rs.Path;
@@ -32,22 +32,18 @@ import javax.ws.rs.Path;
*/
public class AuthorizationService {
- private final RealmAuth auth;
+ private final AdminPermissionEvaluator auth;
private final ClientModel client;
private final KeycloakSession session;
private final ResourceServer resourceServer;
private final AuthorizationProvider authorization;
- public AuthorizationService(KeycloakSession session, ClientModel client, RealmAuth auth) {
+ public AuthorizationService(KeycloakSession session, ClientModel client, AdminPermissionEvaluator auth) {
this.session = session;
this.client = client;
this.authorization = session.getProvider(AuthorizationProvider.class);
this.resourceServer = this.authorization.getStoreFactory().getResourceServerStore().findByClient(this.client.getId());
this.auth = auth;
-
- if (auth != null) {
- this.auth.init(RealmAuth.Resource.AUTHORIZATION);
- }
}
@Path("/resource-server")
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PermissionService.java b/services/src/main/java/org/keycloak/authorization/admin/PermissionService.java
index 4ada87d..e7f4633 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PermissionService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PermissionService.java
@@ -22,14 +22,14 @@ import java.util.Map;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.ResourceServer;
-import org.keycloak.services.resources.admin.RealmAuth;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class PermissionService extends PolicyService {
- public PermissionService(ResourceServer resourceServer, AuthorizationProvider authorization, RealmAuth auth) {
+ public PermissionService(ResourceServer resourceServer, AuthorizationProvider authorization, AdminPermissionEvaluator auth) {
super(resourceServer, authorization, auth);
}
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java
index 24e1a89..0a913dd 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java
@@ -63,14 +63,12 @@ import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.protocol.ProtocolMapper;
-import org.keycloak.protocol.oidc.mappers.OIDCAccessTokenMapper;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
import org.keycloak.services.Urls;
import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.resources.admin.RealmAuth;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.sessions.AuthenticationSessionModel;
/**
@@ -79,13 +77,13 @@ import org.keycloak.sessions.AuthenticationSessionModel;
public class PolicyEvaluationService {
private final AuthorizationProvider authorization;
- private final RealmAuth auth;
+ private final AdminPermissionEvaluator auth;
@Context
private HttpRequest httpRequest;
private final ResourceServer resourceServer;
- PolicyEvaluationService(ResourceServer resourceServer, AuthorizationProvider authorization, RealmAuth auth) {
+ PolicyEvaluationService(ResourceServer resourceServer, AuthorizationProvider authorization, AdminPermissionEvaluator auth) {
this.resourceServer = resourceServer;
this.authorization = authorization;
this.auth = auth;
@@ -117,7 +115,7 @@ public class PolicyEvaluationService {
@Consumes("application/json")
@Produces("application/json")
public Response evaluate(PolicyEvaluationRequest evaluationRequest) throws Throwable {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
CloseableKeycloakIdentity identity = createIdentity(evaluationRequest);
try {
EvaluationContext evaluationContext = createEvaluationContext(evaluationRequest, identity);
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyResourceService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyResourceService.java
index 85e0943..51bc2a6 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PolicyResourceService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyResourceService.java
@@ -42,7 +42,7 @@ import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentati
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
-import org.keycloak.services.resources.admin.RealmAuth;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.util.JsonSerialization;
/**
@@ -53,9 +53,9 @@ public class PolicyResourceService {
private final Policy policy;
protected final ResourceServer resourceServer;
protected final AuthorizationProvider authorization;
- protected final RealmAuth auth;
+ protected final AdminPermissionEvaluator auth;
- public PolicyResourceService(Policy policy, ResourceServer resourceServer, AuthorizationProvider authorization, RealmAuth auth) {
+ public PolicyResourceService(Policy policy, ResourceServer resourceServer, AuthorizationProvider authorization, AdminPermissionEvaluator auth) {
this.policy = policy;
this.resourceServer = resourceServer;
this.authorization = authorization;
@@ -67,7 +67,7 @@ public class PolicyResourceService {
@Produces("application/json")
@NoCache
public Response update(String payload) {
- this.auth.requireManage();
+ this.auth.realm().requireManageAuthorization();
AbstractPolicyRepresentation representation = doCreateRepresentation(payload);
@@ -84,7 +84,7 @@ public class PolicyResourceService {
@DELETE
public Response delete() {
- this.auth.requireManage();
+ this.auth.realm().requireManageAuthorization();
if (policy == null) {
return Response.status(Status.NOT_FOUND).build();
@@ -105,7 +105,7 @@ public class PolicyResourceService {
@Produces("application/json")
@NoCache
public Response findById() {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
if (policy == null) {
return Response.status(Status.NOT_FOUND).build();
@@ -123,7 +123,7 @@ public class PolicyResourceService {
@Produces("application/json")
@NoCache
public Response getDependentPolicies() {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
if (policy == null) {
return Response.status(Status.NOT_FOUND).build();
@@ -147,7 +147,7 @@ public class PolicyResourceService {
@Produces("application/json")
@NoCache
public Response getScopes() {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
if (policy == null) {
return Response.status(Status.NOT_FOUND).build();
@@ -168,7 +168,7 @@ public class PolicyResourceService {
@Produces("application/json")
@NoCache
public Response getResources() {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
if (policy == null) {
return Response.status(Status.NOT_FOUND).build();
@@ -189,7 +189,7 @@ public class PolicyResourceService {
@Produces("application/json")
@NoCache
public Response getAssociatedPolicies() {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
if (policy == null) {
return Response.status(Status.NOT_FOUND).build();
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
index 011aa2d..6ebed11 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
@@ -52,7 +52,7 @@ import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentati
import org.keycloak.representations.idm.authorization.PolicyProviderRepresentation;
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
import org.keycloak.services.ErrorResponseException;
-import org.keycloak.services.resources.admin.RealmAuth;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.util.JsonSerialization;
/**
@@ -62,9 +62,9 @@ public class PolicyService {
protected final ResourceServer resourceServer;
protected final AuthorizationProvider authorization;
- protected final RealmAuth auth;
+ protected final AdminPermissionEvaluator auth;
- public PolicyService(ResourceServer resourceServer, AuthorizationProvider authorization, RealmAuth auth) {
+ public PolicyService(ResourceServer resourceServer, AuthorizationProvider authorization, AdminPermissionEvaluator auth) {
this.resourceServer = resourceServer;
this.authorization = authorization;
this.auth = auth;
@@ -92,7 +92,7 @@ public class PolicyService {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public Response create(String payload) {
- this.auth.requireManage();
+ this.auth.realm().requireManageAuthorization();
AbstractPolicyRepresentation representation = doCreateRepresentation(payload);
Policy policy = create(representation);
@@ -130,7 +130,7 @@ public class PolicyService {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public Response findByName(@QueryParam("name") String name) {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
StoreFactory storeFactory = authorization.getStoreFactory();
if (name == null) {
@@ -157,7 +157,7 @@ public class PolicyService {
@QueryParam("permission") Boolean permission,
@QueryParam("first") Integer firstResult,
@QueryParam("max") Integer maxResult) {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
Map<String, String[]> search = new HashMap<>();
@@ -236,7 +236,7 @@ public class PolicyService {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public Response findPolicyProviders() {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
return Response.ok(
authorization.getProviderFactories().stream()
.map(provider -> {
@@ -254,7 +254,7 @@ public class PolicyService {
@Path("evaluate")
public PolicyEvaluationService getPolicyEvaluateResource() {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
PolicyEvaluationService resource = new PolicyEvaluationService(this.resourceServer, this.authorization, this.auth);
ResteasyProviderFactory.getInstance().injectProperties(resource);
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyTypeResourceService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyTypeResourceService.java
index 8756721..71a6695 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PolicyTypeResourceService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyTypeResourceService.java
@@ -24,7 +24,7 @@ import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
-import org.keycloak.services.resources.admin.RealmAuth;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.util.JsonSerialization;
/**
@@ -32,7 +32,7 @@ import org.keycloak.util.JsonSerialization;
*/
public class PolicyTypeResourceService extends PolicyResourceService {
- public PolicyTypeResourceService(Policy policy, ResourceServer resourceServer, AuthorizationProvider authorization, RealmAuth auth) {
+ public PolicyTypeResourceService(Policy policy, ResourceServer resourceServer, AuthorizationProvider authorization, AdminPermissionEvaluator auth) {
super(policy, resourceServer, authorization, auth);
}
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyTypeService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyTypeService.java
index c2e4db5..d6868c5 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PolicyTypeService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyTypeService.java
@@ -28,7 +28,7 @@ import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
-import org.keycloak.services.resources.admin.RealmAuth;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.util.JsonSerialization;
/**
@@ -38,7 +38,7 @@ public class PolicyTypeService extends PolicyService {
private final String type;
- PolicyTypeService(String type, ResourceServer resourceServer, AuthorizationProvider authorization, RealmAuth auth) {
+ PolicyTypeService(String type, ResourceServer resourceServer, AuthorizationProvider authorization, AdminPermissionEvaluator auth) {
super(resourceServer, authorization, auth);
this.type = type;
}
diff --git a/services/src/main/java/org/keycloak/authorization/admin/ResourceServerService.java b/services/src/main/java/org/keycloak/authorization/admin/ResourceServerService.java
index 15f1db7..a9dc6e0 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/ResourceServerService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/ResourceServerService.java
@@ -53,7 +53,7 @@ import org.keycloak.representations.idm.authorization.PolicyRepresentation;
import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
-import org.keycloak.services.resources.admin.RealmAuth;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@@ -61,12 +61,12 @@ import org.keycloak.services.resources.admin.RealmAuth;
public class ResourceServerService {
private final AuthorizationProvider authorization;
- private final RealmAuth auth;
+ private final AdminPermissionEvaluator auth;
private final KeycloakSession session;
private ResourceServer resourceServer;
private final ClientModel client;
- public ResourceServerService(AuthorizationProvider authorization, ResourceServer resourceServer, ClientModel client, RealmAuth auth) {
+ public ResourceServerService(AuthorizationProvider authorization, ResourceServer resourceServer, ClientModel client, AdminPermissionEvaluator auth) {
this.authorization = authorization;
this.session = authorization.getKeycloakSession();
this.client = client;
@@ -75,7 +75,7 @@ public class ResourceServerService {
}
public void create() {
- this.auth.requireManage();
+ this.auth.realm().requireManageAuthorization();
UserModel serviceAccount = this.session.users().getServiceAccount(client);
@@ -92,7 +92,7 @@ public class ResourceServerService {
@Consumes("application/json")
@Produces("application/json")
public Response update(ResourceServerRepresentation server) {
- this.auth.requireManage();
+ this.auth.realm().requireManageAuthorization();
this.resourceServer.setAllowRemoteResourceManagement(server.isAllowRemoteResourceManagement());
this.resourceServer.setPolicyEnforcementMode(server.getPolicyEnforcementMode());
@@ -100,7 +100,7 @@ public class ResourceServerService {
}
public void delete() {
- this.auth.requireManage();
+ this.auth.realm().requireManageAuthorization();
StoreFactory storeFactory = authorization.getStoreFactory();
ResourceStore resourceStore = storeFactory.getResourceStore();
String id = resourceServer.getId();
@@ -121,7 +121,7 @@ public class ResourceServerService {
@GET
@Produces("application/json")
public Response findById() {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
return Response.ok(toRepresentation(this.resourceServer, this.client)).build();
}
@@ -129,7 +129,7 @@ public class ResourceServerService {
@GET
@Produces("application/json")
public Response exportSettings() {
- this.auth.requireManage();
+ this.auth.realm().requireManageAuthorization();
return Response.ok(ExportUtils.exportAuthorizationSettings(session, client)).build();
}
@@ -137,7 +137,7 @@ public class ResourceServerService {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response importSettings(@Context final UriInfo uriInfo, ResourceServerRepresentation rep) throws IOException {
- this.auth.requireManage();
+ this.auth.realm().requireManageAuthorization();
rep.setClientId(client.getId());
@@ -175,7 +175,7 @@ public class ResourceServerService {
@Path("/permission")
public Object getPermissionTypeResource() {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
PermissionService resource = new PermissionService(this.resourceServer, this.authorization, this.auth);
ResteasyProviderFactory.getInstance().injectProperties(resource);
diff --git a/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java b/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java
index 5d65923..c8eaafe 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java
@@ -37,7 +37,7 @@ import org.keycloak.representations.idm.authorization.ResourceOwnerRepresentatio
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
import org.keycloak.services.ErrorResponse;
-import org.keycloak.services.resources.admin.RealmAuth;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@@ -69,10 +69,10 @@ import static org.keycloak.models.utils.RepresentationToModel.toModel;
public class ResourceSetService {
private final AuthorizationProvider authorization;
- private final RealmAuth auth;
+ private final AdminPermissionEvaluator auth;
private ResourceServer resourceServer;
- public ResourceSetService(ResourceServer resourceServer, AuthorizationProvider authorization, RealmAuth auth) {
+ public ResourceSetService(ResourceServer resourceServer, AuthorizationProvider authorization, AdminPermissionEvaluator auth) {
this.resourceServer = resourceServer;
this.authorization = authorization;
this.auth = auth;
@@ -272,7 +272,7 @@ public class ResourceSetService {
@Produces("application/json")
@NoCache
public Response find(@QueryParam("name") String name) {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
StoreFactory storeFactory = authorization.getStoreFactory();
if (name == null) {
@@ -367,13 +367,13 @@ public class ResourceSetService {
private void requireView() {
if (this.auth != null) {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
}
}
private void requireManage() {
if (this.auth != null) {
- this.auth.requireManage();
+ this.auth.realm().requireManageAuthorization();
}
}
}
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java b/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
index 1ec9a13..157b3a0 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
@@ -30,7 +30,7 @@ import org.keycloak.representations.idm.authorization.PolicyRepresentation;
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
import org.keycloak.services.ErrorResponse;
-import org.keycloak.services.resources.admin.RealmAuth;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@@ -60,10 +60,10 @@ import static org.keycloak.models.utils.RepresentationToModel.toModel;
public class ScopeService {
private final AuthorizationProvider authorization;
- private final RealmAuth auth;
+ private final AdminPermissionEvaluator auth;
private ResourceServer resourceServer;
- public ScopeService(ResourceServer resourceServer, AuthorizationProvider authorization, RealmAuth auth) {
+ public ScopeService(ResourceServer resourceServer, AuthorizationProvider authorization, AdminPermissionEvaluator auth) {
this.resourceServer = resourceServer;
this.authorization = authorization;
this.auth = auth;
@@ -73,7 +73,7 @@ public class ScopeService {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response create(ScopeRepresentation scope) {
- this.auth.requireManage();
+ this.auth.realm().requireManageAuthorization();
Scope model = toModel(scope, this.resourceServer, authorization);
scope.setId(model.getId());
@@ -86,7 +86,7 @@ public class ScopeService {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response update(@PathParam("id") String id, ScopeRepresentation scope) {
- this.auth.requireManage();
+ this.auth.realm().requireManageAuthorization();
scope.setId(id);
StoreFactory storeFactory = authorization.getStoreFactory();
Scope model = storeFactory.getScopeStore().findById(scope.getId(), resourceServer.getId());
@@ -103,7 +103,7 @@ public class ScopeService {
@Path("{id}")
@DELETE
public Response delete(@PathParam("id") String id) {
- this.auth.requireManage();
+ this.auth.realm().requireManageAuthorization();
StoreFactory storeFactory = authorization.getStoreFactory();
List<Resource> resources = storeFactory.getResourceStore().findByScope(Arrays.asList(id), resourceServer.getId());
@@ -137,7 +137,7 @@ public class ScopeService {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response findById(@PathParam("id") String id) {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
Scope model = this.authorization.getStoreFactory().getScopeStore().findById(id, resourceServer.getId());
if (model == null) {
@@ -151,7 +151,7 @@ public class ScopeService {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getResources(@PathParam("id") String id) {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
StoreFactory storeFactory = this.authorization.getStoreFactory();
Scope model = storeFactory.getScopeStore().findById(id, resourceServer.getId());
@@ -173,7 +173,7 @@ public class ScopeService {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getPermissions(@PathParam("id") String id) {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
StoreFactory storeFactory = this.authorization.getStoreFactory();
Scope model = storeFactory.getScopeStore().findById(id, resourceServer.getId());
@@ -199,7 +199,7 @@ public class ScopeService {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public Response find(@QueryParam("name") String name) {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
StoreFactory storeFactory = authorization.getStoreFactory();
if (name == null) {
@@ -222,7 +222,7 @@ public class ScopeService {
@QueryParam("deep") Boolean deep,
@QueryParam("first") Integer firstResult,
@QueryParam("max") Integer maxResult) {
- this.auth.requireView();
+ this.auth.realm().requireViewAuthorization();
if (deep == null) {
deep = true;
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java
index 924b35e..98d4538 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java
@@ -98,4 +98,7 @@ public class AdminAuth {
return false;
}
+ public enum Resource {
+ CLIENT, USER, REALM, EVENTS, IDENTITY_PROVIDER, IMPERSONATION, AUTHORIZATION
+ }
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AttackDetectionResource.java b/services/src/main/java/org/keycloak/services/resources/admin/AttackDetectionResource.java
index 5ac7593..2154ad6 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AttackDetectionResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AttackDetectionResource.java
@@ -26,6 +26,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.UserLoginFailureModel;
import org.keycloak.models.UserModel;
import org.keycloak.services.managers.BruteForceProtector;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
@@ -48,7 +49,7 @@ import java.util.Map;
*/
public class AttackDetectionResource {
protected static final Logger logger = Logger.getLogger(AttackDetectionResource.class);
- protected RealmAuth auth;
+ protected AdminPermissionEvaluator auth;
protected RealmModel realm;
private AdminEventBuilder adminEvent;
@@ -64,12 +65,10 @@ public class AttackDetectionResource {
@Context
protected HttpHeaders headers;
- public AttackDetectionResource(RealmAuth auth, RealmModel realm, AdminEventBuilder adminEvent) {
+ public AttackDetectionResource(AdminPermissionEvaluator auth, RealmModel realm, AdminEventBuilder adminEvent) {
this.auth = auth;
this.realm = realm;
this.adminEvent = adminEvent.realm(realm).resource(ResourceType.USER_LOGIN_FAILURE);
-
- auth.init(RealmAuth.Resource.USER);
}
/**
@@ -83,7 +82,8 @@ public class AttackDetectionResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public Map<String, Object> bruteForceUserStatus(@PathParam("userId") String userId) {
- auth.requireView();
+ UserModel user = session.users().getUserById(userId, realm);
+ auth.users().requireView(user);
Map<String, Object> data = new HashMap<>();
data.put("disabled", false);
@@ -92,7 +92,6 @@ public class AttackDetectionResource {
data.put("lastIPFailure", "n/a");
if (!realm.isBruteForceProtected()) return data;
- UserModel user = session.users().getUserById(userId, realm);
UserLoginFailureModel model = session.sessions().getUserLoginFailure(realm, userId);
if (model == null) return data;
@@ -115,10 +114,10 @@ public class AttackDetectionResource {
@Path("brute-force/users/{userId}")
@DELETE
public void clearBruteForceForUser(@PathParam("userId") String userId) {
- auth.requireManage();
-
UserLoginFailureModel model = session.sessions().getUserLoginFailure(realm, userId);
if (model != null) {
+ UserModel user = session.users().getUserById(userId, realm);
+ auth.users().requireView(user);
session.sessions().removeUserLoginFailure(realm, userId);
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
}
@@ -133,7 +132,7 @@ public class AttackDetectionResource {
@Path("brute-force/users")
@DELETE
public void clearAllBruteForce() {
- auth.requireManage();
+ auth.users().requireManage();
session.sessions().removeAllUserLoginFailures(realm);
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
index 2f7362b..ba7eccc 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
@@ -50,6 +50,7 @@ import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
import org.keycloak.representations.idm.ConfigPropertyRepresentation;
import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
import org.keycloak.services.ErrorResponse;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.utils.CredentialHelper;
import javax.ws.rs.Consumes;
@@ -80,18 +81,17 @@ public class AuthenticationManagementResource {
private final RealmModel realm;
private final KeycloakSession session;
- private RealmAuth auth;
+ private AdminPermissionEvaluator auth;
private AdminEventBuilder adminEvent;
@Context
private UriInfo uriInfo;
protected static final Logger logger = Logger.getLogger(AuthenticationManagementResource.class);
- public AuthenticationManagementResource(RealmModel realm, KeycloakSession session, RealmAuth auth, AdminEventBuilder adminEvent) {
+ public AuthenticationManagementResource(RealmModel realm, KeycloakSession session, AdminPermissionEvaluator auth, AdminEventBuilder adminEvent) {
this.realm = realm;
this.session = session;
this.auth = auth;
- this.auth.init(RealmAuth.Resource.REALM);
this.adminEvent = adminEvent.resource(ResourceType.AUTH_FLOW);
}
@@ -105,7 +105,7 @@ public class AuthenticationManagementResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<Map<String, Object>> getFormProviders() {
- auth.requireView();
+ auth.realm().requireViewRealm();
List<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactories(FormAuthenticator.class);
return buildProviderMetadata(factories);
@@ -121,7 +121,7 @@ public class AuthenticationManagementResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<Map<String, Object>> getAuthenticatorProviders() {
- auth.requireView();
+ auth.realm().requireViewRealm();
List<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactories(Authenticator.class);
return buildProviderMetadata(factories);
@@ -137,7 +137,7 @@ public class AuthenticationManagementResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<Map<String, Object>> getClientAuthenticatorProviders() {
- auth.requireAny();
+ auth.realm().requireViewRealm();
List<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactories(ClientAuthenticator.class);
return buildProviderMetadata(factories);
@@ -167,7 +167,7 @@ public class AuthenticationManagementResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<Map<String, Object>> getFormActionProviders() {
- auth.requireView();
+ auth.realm().requireViewRealm();
List<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactories(FormAction.class);
return buildProviderMetadata(factories);
@@ -184,7 +184,7 @@ public class AuthenticationManagementResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<AuthenticationFlowRepresentation> getFlows() {
- auth.requireAny();
+ auth.realm().requireViewRealm();
List<AuthenticationFlowRepresentation> flows = new LinkedList<>();
for (AuthenticationFlowModel flow : realm.getAuthenticationFlows()) {
@@ -207,7 +207,7 @@ public class AuthenticationManagementResource {
@NoCache
@Consumes(MediaType.APPLICATION_JSON)
public Response createFlow(AuthenticationFlowRepresentation flow) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
if (flow.getAlias() == null || flow.getAlias().isEmpty()) {
return ErrorResponse.exists("Failed to create flow with empty alias name");
@@ -235,7 +235,7 @@ public class AuthenticationManagementResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public AuthenticationFlowRepresentation getFlow(@PathParam("id") String id) {
- auth.requireView();
+ auth.realm().requireViewRealm();
AuthenticationFlowModel flow = realm.getAuthenticationFlowById(id);
if (flow == null) {
@@ -253,7 +253,7 @@ public class AuthenticationManagementResource {
@DELETE
@NoCache
public void deleteFlow(@PathParam("id") String id) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
deleteFlow(id, true);
}
@@ -292,7 +292,7 @@ public class AuthenticationManagementResource {
@NoCache
@Consumes(MediaType.APPLICATION_JSON)
public Response copy(@PathParam("flowAlias") String flowAlias, Map<String, String> data) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
String newName = data.get("newName");
if (realm.getFlowByAlias(newName) != null) {
@@ -351,7 +351,7 @@ public class AuthenticationManagementResource {
@NoCache
@Consumes(MediaType.APPLICATION_JSON)
public Response addExecutionFlow(@PathParam("flowAlias") String flowAlias, Map<String, String> data) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
AuthenticationFlowModel parentFlow = realm.getFlowByAlias(flowAlias);
if (parentFlow == null) {
@@ -403,7 +403,7 @@ public class AuthenticationManagementResource {
@NoCache
@Consumes(MediaType.APPLICATION_JSON)
public void addExecution(@PathParam("flowAlias") String flowAlias, Map<String, String> data) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
AuthenticationFlowModel parentFlow = realm.getFlowByAlias(flowAlias);
if (parentFlow == null) {
@@ -450,7 +450,7 @@ public class AuthenticationManagementResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public Response getExecutions(@PathParam("flowAlias") String flowAlias) {
- auth.requireView();
+ auth.realm().requireViewRealm();
AuthenticationFlowModel flow = realm.getFlowByAlias(flowAlias);
if (flow == null) {
@@ -535,7 +535,7 @@ public class AuthenticationManagementResource {
@NoCache
@Consumes(MediaType.APPLICATION_JSON)
public void updateExecutions(@PathParam("flowAlias") String flowAlias, AuthenticationExecutionInfoRepresentation rep) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
AuthenticationFlowModel flow = realm.getFlowByAlias(flowAlias);
if (flow == null) {
@@ -566,7 +566,7 @@ public class AuthenticationManagementResource {
@NoCache
@Consumes(MediaType.APPLICATION_JSON)
public Response addExecution(AuthenticationExecutionRepresentation execution) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
AuthenticationExecutionModel model = RepresentationToModel.toModel(realm, execution);
AuthenticationFlowModel parentFlow = getParentFlow(model);
@@ -601,7 +601,7 @@ public class AuthenticationManagementResource {
@POST
@NoCache
public void raisePriority(@PathParam("executionId") String execution) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
if (model == null) {
@@ -647,7 +647,7 @@ public class AuthenticationManagementResource {
@POST
@NoCache
public void lowerPriority(@PathParam("executionId") String execution) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
if (model == null) {
@@ -687,7 +687,7 @@ public class AuthenticationManagementResource {
@DELETE
@NoCache
public void removeExecution(@PathParam("executionId") String execution) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
if (model == null) {
@@ -723,7 +723,7 @@ public class AuthenticationManagementResource {
@NoCache
@Consumes(MediaType.APPLICATION_JSON)
public Response newExecutionConfig(@PathParam("executionId") String execution, AuthenticatorConfigRepresentation json) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
if (model == null) {
@@ -753,7 +753,7 @@ public class AuthenticationManagementResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public AuthenticatorConfigRepresentation getAuthenticatorConfig(@PathParam("executionId") String execution,@PathParam("id") String id) {
- auth.requireView();
+ auth.realm().requireViewRealm();
AuthenticatorConfigModel config = realm.getAuthenticatorConfigById(id);
if (config == null) {
@@ -773,7 +773,7 @@ public class AuthenticationManagementResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<Map<String, String>> getUnregisteredRequiredActions() {
- auth.requireView();
+ auth.realm().requireViewRealm();
List<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactories(RequiredActionProvider.class);
List<Map<String, String>> unregisteredList = new LinkedList<>();
@@ -807,7 +807,7 @@ public class AuthenticationManagementResource {
@Consumes(MediaType.APPLICATION_JSON)
@NoCache
public void registerRequiredAction(Map<String, String> data) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
String providerId = data.get("providerId");
String name = data.get("name");
@@ -834,7 +834,7 @@ public class AuthenticationManagementResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RequiredActionProviderRepresentation> getRequiredActions() {
- auth.requireAny();
+ auth.realm().requireViewRealm();
List<RequiredActionProviderRepresentation> list = new LinkedList<>();
for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) {
@@ -863,7 +863,7 @@ public class AuthenticationManagementResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public RequiredActionProviderRepresentation getRequiredAction(@PathParam("alias") String alias) {
- auth.requireView();
+ auth.realm().requireViewRealm();
RequiredActionProviderModel model = realm.getRequiredActionProviderByAlias(alias);
if (model == null) {
@@ -883,7 +883,7 @@ public class AuthenticationManagementResource {
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public void updateRequiredAction(@PathParam("alias") String alias, RequiredActionProviderRepresentation rep) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
RequiredActionProviderModel model = realm.getRequiredActionProviderByAlias(alias);
if (model == null) {
@@ -909,7 +909,7 @@ public class AuthenticationManagementResource {
@Path("required-actions/{alias}")
@DELETE
public void removeRequiredAction(@PathParam("alias") String alias) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
RequiredActionProviderModel model = realm.getRequiredActionProviderByAlias(alias);
if (model == null) {
@@ -928,7 +928,7 @@ public class AuthenticationManagementResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public AuthenticatorConfigInfoRepresentation getAuthenticatorConfigDescription(@PathParam("providerId") String providerId) {
- auth.requireView();
+ auth.realm().requireViewRealm();
ConfigurableAuthenticatorFactory factory = CredentialHelper.getConfigurableAuthenticatorFactory(session, providerId);
if (factory == null) {
@@ -959,7 +959,7 @@ public class AuthenticationManagementResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public Map<String, List<ConfigPropertyRepresentation>> getPerClientConfigDescription() {
- auth.requireAny();
+ auth.realm().requireViewRealm();
List<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactories(ClientAuthenticator.class);
@@ -991,7 +991,7 @@ public class AuthenticationManagementResource {
@NoCache
@Consumes(MediaType.APPLICATION_JSON)
public Response createAuthenticatorConfig(AuthenticatorConfigRepresentation rep) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
AuthenticatorConfigModel config = realm.addAuthenticatorConfig(RepresentationToModel.toModel(rep));
adminEvent.operation(OperationType.CREATE).resource(ResourceType.AUTHENTICATOR_CONFIG).resourcePath(uriInfo, config.getId()).representation(rep).success();
@@ -1007,7 +1007,7 @@ public class AuthenticationManagementResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public AuthenticatorConfigRepresentation getAuthenticatorConfig(@PathParam("id") String id) {
- auth.requireView();
+ auth.realm().requireViewRealm();
AuthenticatorConfigModel config = realm.getAuthenticatorConfigById(id);
if (config == null) {
@@ -1025,7 +1025,7 @@ public class AuthenticationManagementResource {
@DELETE
@NoCache
public void removeAuthenticatorConfig(@PathParam("id") String id) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
AuthenticatorConfigModel config = realm.getAuthenticatorConfigById(id);
if (config == null) {
@@ -1057,7 +1057,7 @@ public class AuthenticationManagementResource {
@Consumes(MediaType.APPLICATION_JSON)
@NoCache
public void updateAuthenticatorConfig(@PathParam("id") String id, AuthenticatorConfigRepresentation rep) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
AuthenticatorConfigModel exists = realm.getAuthenticatorConfigById(id);
if (exists == null) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
index 1f4277b..1de2c9d 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
@@ -37,6 +37,7 @@ import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.KeyStoreConfig;
import org.keycloak.representations.idm.CertificateRepresentation;
import org.keycloak.services.ErrorResponseException;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.services.util.CertificateInfoHelper;
import org.keycloak.util.JWKSUtils;
import org.keycloak.util.JsonSerialization;
@@ -73,13 +74,13 @@ public class ClientAttributeCertificateResource {
public static final String JSON_WEB_KEY_SET = "JSON Web Key Set";
protected RealmModel realm;
- private RealmAuth auth;
+ private AdminPermissionEvaluator auth;
protected ClientModel client;
protected KeycloakSession session;
protected AdminEventBuilder adminEvent;
protected String attributePrefix;
- public ClientAttributeCertificateResource(RealmModel realm, RealmAuth auth, ClientModel client, KeycloakSession session, String attributePrefix, AdminEventBuilder adminEvent) {
+ public ClientAttributeCertificateResource(RealmModel realm, AdminPermissionEvaluator auth, ClientModel client, KeycloakSession session, String attributePrefix, AdminEventBuilder adminEvent) {
this.realm = realm;
this.auth = auth;
this.client = client;
@@ -97,11 +98,7 @@ public class ClientAttributeCertificateResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public CertificateRepresentation getKeyInfo() {
- auth.requireView();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireView(client);
CertificateRepresentation info = CertificateInfoHelper.getCertificateFromClient(client, attributePrefix);
return info;
@@ -117,11 +114,7 @@ public class ClientAttributeCertificateResource {
@Path("generate")
@Produces(MediaType.APPLICATION_JSON)
public CertificateRepresentation generate() {
- auth.requireManage();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireManage(client);
CertificateRepresentation info = KeycloakModelUtils.generateKeyPairCertificate(client.getClientId());
@@ -145,11 +138,7 @@ public class ClientAttributeCertificateResource {
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
public CertificateRepresentation uploadJks(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
- auth.requireManage();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireManage(client);
try {
CertificateRepresentation info = getCertFromRequest(input);
@@ -175,11 +164,7 @@ public class ClientAttributeCertificateResource {
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
public CertificateRepresentation uploadJksCertificate(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
- auth.requireManage();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireManage(client);
try {
CertificateRepresentation info = getCertFromRequest(input);
@@ -194,7 +179,7 @@ public class ClientAttributeCertificateResource {
}
private CertificateRepresentation getCertFromRequest(MultipartFormDataInput input) throws IOException {
- auth.requireManage();
+ auth.clients().requireManage(client);
CertificateRepresentation info = new CertificateRepresentation();
Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
String keystoreFormat = uploadForm.get("keystoreFormat").get(0).getBodyAsString();
@@ -279,11 +264,7 @@ public class ClientAttributeCertificateResource {
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Consumes(MediaType.APPLICATION_JSON)
public byte[] getKeystore(final KeyStoreConfig config) {
- auth.requireView();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireView(client);
if (config.getFormat() != null && !config.getFormat().equals("JKS") && !config.getFormat().equals("PKCS12")) {
throw new NotAcceptableException("Only support jks or pkcs12 format.");
@@ -322,11 +303,7 @@ public class ClientAttributeCertificateResource {
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Consumes(MediaType.APPLICATION_JSON)
public byte[] generateAndGetKeystore(final KeyStoreConfig config) {
- auth.requireManage();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireManage(client);
if (config.getFormat() != null && !config.getFormat().equals("JKS") && !config.getFormat().equals("PKCS12")) {
throw new NotAcceptableException("Only support jks or pkcs12 format.");
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java
index dfd28cc..65941af 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java
@@ -25,6 +25,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.ClientInitialAccessCreatePresentation;
import org.keycloak.representations.idm.ClientInitialAccessPresentation;
import org.keycloak.services.clientregistration.ClientRegistrationTokenUtils;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
@@ -48,7 +49,7 @@ import java.util.List;
*/
public class ClientInitialAccessResource {
- private final RealmAuth auth;
+ private final AdminPermissionEvaluator auth;
private final RealmModel realm;
private final AdminEventBuilder adminEvent;
@@ -58,12 +59,11 @@ public class ClientInitialAccessResource {
@Context
protected UriInfo uriInfo;
- public ClientInitialAccessResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
+ public ClientInitialAccessResource(RealmModel realm, AdminPermissionEvaluator auth, AdminEventBuilder adminEvent) {
this.auth = auth;
this.realm = realm;
this.adminEvent = adminEvent.resource(ResourceType.CLIENT_INITIAL_ACCESS_MODEL);
- auth.init(RealmAuth.Resource.CLIENT);
}
/**
@@ -76,7 +76,7 @@ public class ClientInitialAccessResource {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public ClientInitialAccessPresentation create(ClientInitialAccessCreatePresentation config, @Context final HttpServletResponse response) {
- auth.requireManage();
+ auth.clients().requireManage();
int expiration = config.getExpiration() != null ? config.getExpiration() : 0;
int count = config.getCount() != null ? config.getCount() : 1;
@@ -99,7 +99,7 @@ public class ClientInitialAccessResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<ClientInitialAccessPresentation> list() {
- auth.requireView();
+ auth.clients().requireView();
List<ClientInitialAccessModel> models = session.sessions().listClientInitialAccess(realm);
List<ClientInitialAccessPresentation> reps = new LinkedList<>();
@@ -113,7 +113,7 @@ public class ClientInitialAccessResource {
@DELETE
@Path("{id}")
public void delete(final @PathParam("id") String id) {
- auth.requireManage();
+ auth.clients().requireManage();
session.sessions().removeClientInitialAccessModel(realm, id);
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientRegistrationPolicyResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientRegistrationPolicyResource.java
index f8c57e2..9250326 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientRegistrationPolicyResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientRegistrationPolicyResource.java
@@ -37,6 +37,7 @@ import org.keycloak.provider.ProviderFactory;
import org.keycloak.representations.idm.ComponentTypeRepresentation;
import org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy;
import org.keycloak.services.clientregistration.policy.ClientRegistrationPolicyFactory;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
/**
* @resource Client Registration Policy
@@ -44,7 +45,7 @@ import org.keycloak.services.clientregistration.policy.ClientRegistrationPolicyF
*/
public class ClientRegistrationPolicyResource {
- private final RealmAuth auth;
+ private final AdminPermissionEvaluator auth;
private final RealmModel realm;
private final AdminEventBuilder adminEvent;
@@ -54,12 +55,11 @@ public class ClientRegistrationPolicyResource {
@Context
protected UriInfo uriInfo;
- public ClientRegistrationPolicyResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
+ public ClientRegistrationPolicyResource(RealmModel realm, AdminPermissionEvaluator auth, AdminEventBuilder adminEvent) {
this.auth = auth;
this.realm = realm;
this.adminEvent = adminEvent.resource(ResourceType.CLIENT_INITIAL_ACCESS_MODEL);
- auth.init(RealmAuth.Resource.CLIENT);
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
index ac5e6d1..ba6bd03 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
@@ -51,6 +51,7 @@ import org.keycloak.services.managers.ClientManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.ResourceAdminManager;
import org.keycloak.services.resources.KeycloakApplication;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.services.validation.ClientValidator;
import org.keycloak.services.validation.PairwiseClientValidator;
import org.keycloak.services.validation.ValidationMessages;
@@ -89,7 +90,7 @@ import static java.lang.Boolean.TRUE;
public class ClientResource {
protected static final Logger logger = Logger.getLogger(ClientResource.class);
protected RealmModel realm;
- private RealmAuth auth;
+ private AdminPermissionEvaluator auth;
private AdminEventBuilder adminEvent;
protected ClientModel client;
protected KeycloakSession session;
@@ -104,19 +105,19 @@ public class ClientResource {
return keycloak;
}
- public ClientResource(RealmModel realm, RealmAuth auth, ClientModel clientModel, KeycloakSession session, AdminEventBuilder adminEvent) {
+ public ClientResource(RealmModel realm, AdminPermissionEvaluator auth, ClientModel clientModel, KeycloakSession session, AdminEventBuilder adminEvent) {
this.realm = realm;
this.auth = auth;
this.client = clientModel;
this.session = session;
this.adminEvent = adminEvent.resource(ResourceType.CLIENT);
-
- auth.init(RealmAuth.Resource.CLIENT);
}
@Path("protocol-mappers")
public ProtocolMappersResource getProtocolMappers() {
- ProtocolMappersResource mappers = new ProtocolMappersResource(realm, client, auth, adminEvent);
+ AdminPermissionEvaluator.RequirePermissionCheck manageCheck = () -> auth.clients().requireManage(client);
+ AdminPermissionEvaluator.RequirePermissionCheck viewCheck = () -> auth.clients().requireView(client);
+ ProtocolMappersResource mappers = new ProtocolMappersResource(realm, client, auth, adminEvent, manageCheck, viewCheck);
ResteasyProviderFactory.getInstance().injectProperties(mappers);
return mappers;
}
@@ -129,15 +130,11 @@ public class ClientResource {
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public Response update(final ClientRepresentation rep) {
- auth.requireManage();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireManage(client);
ValidationMessages validationMessages = new ValidationMessages();
if (!ClientValidator.validate(rep, validationMessages) || !PairwiseClientValidator.validate(session, rep, validationMessages)) {
- Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
+ Properties messages = AdminRoot.getMessages(session, realm, auth.adminAuth().getToken().getLocale());
throw new ErrorResponseException(
validationMessages.getStringMessages(),
validationMessages.getStringMessages(messages),
@@ -187,11 +184,7 @@ public class ClientResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public ClientRepresentation getClient() {
- auth.requireView();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireView(client);
ClientRepresentation representation = ModelToRepresentation.toRepresentation(client);
@@ -217,11 +210,7 @@ public class ClientResource {
@NoCache
@Path("installation/providers/{providerId}")
public Response getInstallationProvider(@PathParam("providerId") String providerId) {
- auth.requireView();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireView(client);
ClientInstallationProvider provider = session.getProvider(ClientInstallationProvider.class, providerId);
if (provider == null) throw new NotFoundException("Unknown Provider");
@@ -235,7 +224,7 @@ public class ClientResource {
@DELETE
@NoCache
public void deleteClient() {
- auth.requireManage();
+ auth.clients().requireManage(client);
if (client == null) {
throw new NotFoundException("Could not find client");
@@ -256,11 +245,7 @@ public class ClientResource {
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public CredentialRepresentation regenerateSecret() {
- auth.requireManage();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireManage(client);
logger.debug("regenerateSecret");
UserCredentialModel cred = KeycloakModelUtils.generateSecret(client);
@@ -279,11 +264,7 @@ public class ClientResource {
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public ClientRepresentation regenerateRegistrationAccessToken() {
- auth.requireManage();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireManage(client);
String token = ClientRegistrationTokenUtils.updateRegistrationAccessToken(session, realm, uriInfo, client, RegistrationAuth.AUTHENTICATED);
@@ -304,11 +285,7 @@ public class ClientResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public CredentialRepresentation getClientSecret() {
- auth.requireView();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireView(client);
logger.debug("getClientSecret");
UserCredentialModel model = UserCredentialModel.secret(client.getSecret());
@@ -323,12 +300,16 @@ public class ClientResource {
*/
@Path("scope-mappings")
public ScopeMappedResource getScopeMappedResource() {
- return new ScopeMappedResource(realm, auth, client, session, adminEvent);
+ AdminPermissionEvaluator.RequirePermissionCheck manageCheck = () -> auth.clients().requireManage(client);
+ AdminPermissionEvaluator.RequirePermissionCheck viewCheck = () -> auth.clients().requireView(client);
+ return new ScopeMappedResource(realm, auth, client, session, adminEvent, manageCheck, viewCheck);
}
@Path("roles")
public RoleContainerResource getRoleContainerResource() {
- return new RoleContainerResource(session, uriInfo, realm, auth, client, adminEvent);
+ AdminPermissionEvaluator.RequirePermissionCheck manageCheck = () -> auth.clients().requireManage(client);
+ AdminPermissionEvaluator.RequirePermissionCheck viewCheck = () -> auth.clients().requireView(client);
+ return new RoleContainerResource(session, uriInfo, realm, auth, client, adminEvent, manageCheck, viewCheck);
}
/**
@@ -341,11 +322,7 @@ public class ClientResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public UserRepresentation getServiceAccountUser() {
- auth.requireView();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireView(client);
UserModel user = session.users().getServiceAccount(client);
if (user == null) {
@@ -369,11 +346,7 @@ public class ClientResource {
@POST
@Produces(MediaType.APPLICATION_JSON)
public GlobalRequestResult pushRevocation() {
- auth.requireManage();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireManage(client);
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).resource(ResourceType.CLIENT).success();
return new ResourceAdminManager(session).pushClientRevocationPolicy(uriInfo.getRequestUri(), realm, client);
@@ -396,11 +369,7 @@ public class ClientResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public Map<String, Long> getApplicationSessionCount() {
- auth.requireView();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireView(client);
Map<String, Long> map = new HashMap<>();
map.put("count", session.sessions().getActiveUserSessions(client.getRealm(), client));
@@ -421,11 +390,7 @@ public class ClientResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<UserSessionRepresentation> getUserSessions(@QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResults) {
- auth.requireView();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireView(client);
firstResult = firstResult != null ? firstResult : -1;
maxResults = maxResults != null ? maxResults : Constants.DEFAULT_MAX_RESULTS;
@@ -453,11 +418,7 @@ public class ClientResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public Map<String, Long> getOfflineSessionCount() {
- auth.requireView();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireView(client);
Map<String, Long> map = new HashMap<>();
map.put("count", session.sessions().getOfflineSessionsCount(client.getRealm(), client));
@@ -478,11 +439,7 @@ public class ClientResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<UserSessionRepresentation> getOfflineUserSessions(@QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResults) {
- auth.requireView();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireView(client);
firstResult = firstResult != null ? firstResult : -1;
maxResults = maxResults != null ? maxResults : Constants.DEFAULT_MAX_RESULTS;
@@ -519,11 +476,7 @@ public class ClientResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public void registerNode(Map<String, String> formParams) {
- auth.requireManage();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireManage(client);
String node = formParams.get("node");
if (node == null) {
@@ -543,11 +496,7 @@ public class ClientResource {
@DELETE
@NoCache
public void unregisterNode(final @PathParam("node") String node) {
- auth.requireManage();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireManage(client);
if (logger.isDebugEnabled()) logger.debug("Unregister node: " + node);
@@ -571,11 +520,7 @@ public class ClientResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public GlobalRequestResult testNodesAvailable() {
- auth.requireManage();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.clients().requireManage(client);
logger.debug("Test availability of cluster nodes");
GlobalRequestResult result = new ResourceAdminManager(session).testNodesAvailability(uriInfo.getRequestUri(), realm, client);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java
index b5f1996..c619669 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java
@@ -19,7 +19,7 @@ package org.keycloak.services.resources.admin;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.authorization.admin.permissions.MgmtPermissions;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.events.admin.OperationType;
import org.keycloak.events.admin.ResourceType;
import org.keycloak.models.ClientModel;
@@ -61,30 +61,29 @@ public class ClientRoleMappingsResource {
protected KeycloakSession session;
protected RealmModel realm;
- protected RealmAuth auth;
+ protected AdminPermissionEvaluator auth;
protected RoleMapperModel user;
protected ClientModel client;
protected AdminEventBuilder adminEvent;
private UriInfo uriInfo;
- private RoleMapperResource.ManageResourcePermissionCheck manageResourcePermissionCheck;
+ protected AdminPermissionEvaluator.RequirePermissionCheck managePermission;
+ protected AdminPermissionEvaluator.RequirePermissionCheck viewPermission;
- public ClientRoleMappingsResource(UriInfo uriInfo, KeycloakSession session, RealmModel realm, RealmAuth auth, RoleMapperModel user, ClientModel client, AdminEventBuilder adminEvent) {
+ public ClientRoleMappingsResource(UriInfo uriInfo, KeycloakSession session, RealmModel realm, AdminPermissionEvaluator auth,
+ RoleMapperModel user, ClientModel client, AdminEventBuilder adminEvent,
+ AdminPermissionEvaluator.RequirePermissionCheck manageCheck, AdminPermissionEvaluator.RequirePermissionCheck viewCheck ) {
this.uriInfo = uriInfo;
this.session = session;
this.realm = realm;
this.auth = auth;
this.user = user;
this.client = client;
+ this.managePermission = manageCheck;
+ this.viewPermission = viewCheck;
this.adminEvent = adminEvent.resource(ResourceType.CLIENT_ROLE_MAPPING);
}
- public void setManageCheck(RoleMapperResource.ManageResourcePermissionCheck mapperPermissions) {
- this.manageResourcePermissionCheck = mapperPermissions;
- }
-
-
-
/**
* Get client-level role mappings for the user, and the app
*
@@ -94,11 +93,7 @@ public class ClientRoleMappingsResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getClientRoleMappings() {
- auth.requireView();
-
- if (user == null || client == null) {
- throw new NotFoundException("Not found");
- }
+ viewPermission.require();
Set<RoleModel> mappings = user.getClientRoleMappings(client);
List<RoleRepresentation> mapRep = new ArrayList<RoleRepresentation>();
@@ -120,11 +115,8 @@ public class ClientRoleMappingsResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getCompositeClientRoleMappings() {
- auth.requireView();
+ viewPermission.require();
- if (user == null || client == null) {
- throw new NotFoundException("Not found");
- }
Set<RoleModel> roles = client.getRoles();
List<RoleRepresentation> mapRep = new ArrayList<RoleRepresentation>();
@@ -144,11 +136,7 @@ public class ClientRoleMappingsResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getAvailableClientRoleMappings() {
- auth.requireView();
-
- if (user == null || client == null) {
- throw new NotFoundException("Not found");
- }
+ viewPermission.require();
Set<RoleModel> available = client.getRoles();
available = available.stream().filter(r ->
@@ -171,17 +159,6 @@ public class ClientRoleMappingsResource {
return mappings;
}
- private void checkManagePermission() {
- if (manageResourcePermissionCheck == null) {
- auth.requireManage();
- } else {
- if (!manageResourcePermissionCheck.canManage()) {
- throw new ForbiddenException();
- }
- }
- }
-
-
/**
* Add client-level roles to the user role mapping
*
@@ -190,11 +167,7 @@ public class ClientRoleMappingsResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public void addClientRoleMapping(List<RoleRepresentation> roles) {
- checkManagePermission();
-
- if (user == null || client == null) {
- throw new NotFoundException("Not found");
- }
+ managePermission.require();
for (RoleRepresentation role : roles) {
RoleModel roleModel = client.getRole(role.getName());
@@ -215,7 +188,7 @@ public class ClientRoleMappingsResource {
}
private boolean canMapRole(RoleModel roleModel) {
- return new MgmtPermissions(session, realm, auth.getAuth()).roles().canMapRole(roleModel);
+ return auth.roles().canMapRole(roleModel);
}
/**
@@ -226,11 +199,7 @@ public class ClientRoleMappingsResource {
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
public void deleteClientRoleMapping(List<RoleRepresentation> roles) {
- checkManagePermission();
-
- if (user == null || client == null) {
- throw new NotFoundException("Not found");
- }
+ managePermission.require();
if (roles == null) {
Set<RoleModel> roleModels = user.getClientRoleMappings(client);
@@ -257,7 +226,7 @@ public class ClientRoleMappingsResource {
try {
user.deleteRoleMapping(roleModel);
} catch (ModelException me) {
- Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
+ Properties messages = AdminRoot.getMessages(session, realm, auth.adminAuth().getToken().getLocale());
throw new ErrorResponseException(me.getMessage(), MessageFormat.format(messages.getProperty(me.getMessage(), me.getMessage()), me.getParameters()),
Response.Status.BAD_REQUEST);
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
index 3fa3c75..e02f225 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
@@ -26,6 +26,7 @@ import org.keycloak.common.Profile;
import org.keycloak.events.admin.OperationType;
import org.keycloak.events.admin.ResourceType;
import org.keycloak.models.ClientModel;
+import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel;
@@ -34,14 +35,18 @@ import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.services.ErrorResponse;
import org.keycloak.services.ErrorResponseException;
+import org.keycloak.services.ForbiddenException;
import org.keycloak.services.managers.ClientManager;
import org.keycloak.services.managers.RealmManager;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.services.validation.ClientValidator;
import org.keycloak.services.validation.PairwiseClientValidator;
import org.keycloak.services.validation.ValidationMessages;
import javax.ws.rs.Consumes;
+import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
+import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@@ -65,18 +70,17 @@ import java.util.Properties;
public class ClientsResource {
protected static final Logger logger = Logger.getLogger(ClientsResource.class);
protected RealmModel realm;
- private RealmAuth auth;
+ private AdminPermissionEvaluator auth;
private AdminEventBuilder adminEvent;
@Context
protected KeycloakSession session;
- public ClientsResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
+ public ClientsResource(RealmModel realm, AdminPermissionEvaluator auth, AdminEventBuilder adminEvent) {
this.realm = realm;
this.auth = auth;
this.adminEvent = adminEvent.resource(ResourceType.CLIENT);
- auth.init(RealmAuth.Resource.CLIENT);
}
/**
@@ -85,21 +89,20 @@ public class ClientsResource {
* Returns a list of clients belonging to the realm
*
* @param clientId filter by clientId
+ * @param viewableOnly filter clients that cannot be viewed in full by admin
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
- public List<ClientRepresentation> getClients(@QueryParam("clientId") String clientId) {
- auth.requireAny();
-
+ public List<ClientRepresentation> getClients(@QueryParam("clientId") String clientId, @QueryParam("viewableOnly") @DefaultValue("false") boolean viewableOnly) {
List<ClientRepresentation> rep = new ArrayList<>();
if (clientId == null) {
List<ClientModel> clientModels = realm.getClients();
-
- boolean view = auth.hasView();
+ auth.clients().requireList();
+ boolean view = auth.clients().canView();
for (ClientModel clientModel : clientModels) {
- if (view) {
+ if (view || auth.clients().canView(clientModel)) {
ClientRepresentation representation = ModelToRepresentation.toRepresentation(clientModel);
if (Profile.isFeatureEnabled(Profile.Feature.AUTHORIZATION)) {
@@ -111,7 +114,7 @@ public class ClientsResource {
}
rep.add(representation);
- } else {
+ } else if (!viewableOnly) {
ClientRepresentation client = new ClientRepresentation();
client.setId(clientModel.getId());
client.setClientId(clientModel.getClientId());
@@ -120,9 +123,20 @@ public class ClientsResource {
}
}
} else {
- ClientModel client = realm.getClientByClientId(clientId);
- if (client != null) {
- rep.add(ModelToRepresentation.toRepresentation(client));
+ ClientModel clientModel = realm.getClientByClientId(clientId);
+ if (clientModel != null) {
+ if (auth.clients().canView(clientModel)) {
+ rep.add(ModelToRepresentation.toRepresentation(clientModel));
+ } else if (!viewableOnly && auth.clients().canList()){
+ ClientRepresentation client = new ClientRepresentation();
+ client.setId(clientModel.getId());
+ client.setClientId(clientModel.getClientId());
+ client.setDescription(clientModel.getDescription());
+ rep.add(client);
+
+ } else {
+ throw new ForbiddenException();
+ }
}
}
return rep;
@@ -144,11 +158,11 @@ public class ClientsResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response createClient(final @Context UriInfo uriInfo, final ClientRepresentation rep) {
- auth.requireManage();
+ auth.clients().requireManage();
ValidationMessages validationMessages = new ValidationMessages();
if (!ClientValidator.validate(rep, validationMessages) || !PairwiseClientValidator.validate(session, rep, validationMessages)) {
- Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
+ Properties messages = AdminRoot.getMessages(session, realm, auth.adminAuth().getToken().getLocale());
throw new ErrorResponseException(
validationMessages.getStringMessages(),
validationMessages.getStringMessages(messages),
@@ -190,6 +204,9 @@ public class ClientsResource {
@Path("{id}")
public ClientResource getClient(final @PathParam("id") String id) {
ClientModel clientModel = realm.getClientById(id);
+ if (clientModel == null) {
+ throw new NotFoundException("Could not find client");
+ }
session.getContext().setClient(clientModel);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java
index f760a41..f076850 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java
@@ -31,6 +31,7 @@ import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.ClientTemplateRepresentation;
import org.keycloak.services.ErrorResponse;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@@ -54,7 +55,7 @@ import javax.ws.rs.core.UriInfo;
public class ClientTemplateResource {
protected static final Logger logger = Logger.getLogger(ClientTemplateResource.class);
protected RealmModel realm;
- private RealmAuth auth;
+ private AdminPermissionEvaluator auth;
private AdminEventBuilder adminEvent;
protected ClientTemplateModel template;
protected KeycloakSession session;
@@ -62,19 +63,20 @@ public class ClientTemplateResource {
@Context
protected UriInfo uriInfo;
- public ClientTemplateResource(RealmModel realm, RealmAuth auth, ClientTemplateModel template, KeycloakSession session, AdminEventBuilder adminEvent) {
+ public ClientTemplateResource(RealmModel realm, AdminPermissionEvaluator auth, ClientTemplateModel template, KeycloakSession session, AdminEventBuilder adminEvent) {
this.realm = realm;
this.auth = auth;
this.template = template;
this.session = session;
this.adminEvent = adminEvent.resource(ResourceType.CLIENT_TEMPLATE);
- auth.init(RealmAuth.Resource.CLIENT);
}
@Path("protocol-mappers")
public ProtocolMappersResource getProtocolMappers() {
- ProtocolMappersResource mappers = new ProtocolMappersResource(realm, template, auth, adminEvent);
+ AdminPermissionEvaluator.RequirePermissionCheck manageCheck = () -> auth.clients().requireManage(template);
+ AdminPermissionEvaluator.RequirePermissionCheck viewCheck = () -> auth.clients().requireView(template);
+ ProtocolMappersResource mappers = new ProtocolMappersResource(realm, template, auth, adminEvent, manageCheck, viewCheck);
ResteasyProviderFactory.getInstance().injectProperties(mappers);
return mappers;
}
@@ -86,7 +88,9 @@ public class ClientTemplateResource {
*/
@Path("scope-mappings")
public ScopeMappedResource getScopeMappedResource() {
- return new ScopeMappedResource(realm, auth, template, session, adminEvent);
+ AdminPermissionEvaluator.RequirePermissionCheck manageCheck = () -> auth.clients().requireManage(template);
+ AdminPermissionEvaluator.RequirePermissionCheck viewCheck = () -> auth.clients().requireView(template);
+ return new ScopeMappedResource(realm, auth, template, session, adminEvent, manageCheck, viewCheck);
}
/**
@@ -97,11 +101,7 @@ public class ClientTemplateResource {
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public Response update(final ClientTemplateRepresentation rep) {
- auth.requireManage();
-
- if (template == null) {
- throw new NotFoundException("Could not find client template");
- }
+ auth.clients().requireManageTemplates();
try {
RepresentationToModel.updateClientTemplate(rep, template);
@@ -125,11 +125,8 @@ public class ClientTemplateResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public ClientTemplateRepresentation getClient() {
- auth.requireView();
+ auth.clients().requireView(template);
- if (template == null) {
- throw new NotFoundException("Could not find client template");
- }
return ModelToRepresentation.toRepresentation(template);
}
@@ -141,11 +138,7 @@ public class ClientTemplateResource {
@DELETE
@NoCache
public Response deleteClientTemplate() {
- auth.requireManage();
-
- if (template == null) {
- throw new NotFoundException("Could not find client template");
- }
+ auth.clients().requireManage(template);
try {
realm.removeClientTemplate(template.getId());
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplatesResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplatesResource.java
index 5e27712..954f0c8 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplatesResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplatesResource.java
@@ -18,6 +18,7 @@ package org.keycloak.services.resources.admin;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
+import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.events.admin.OperationType;
import org.keycloak.events.admin.ResourceType;
@@ -29,6 +30,7 @@ import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.ClientTemplateRepresentation;
import org.keycloak.services.ErrorResponse;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@@ -53,18 +55,16 @@ import java.util.List;
public class ClientTemplatesResource {
protected static final Logger logger = Logger.getLogger(ClientTemplatesResource.class);
protected RealmModel realm;
- private RealmAuth auth;
+ private AdminPermissionEvaluator auth;
private AdminEventBuilder adminEvent;
@Context
protected KeycloakSession session;
- public ClientTemplatesResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
+ public ClientTemplatesResource(RealmModel realm, AdminPermissionEvaluator auth, AdminEventBuilder adminEvent) {
this.realm = realm;
this.auth = auth;
this.adminEvent = adminEvent.resource(ResourceType.CLIENT_TEMPLATE);
-
- auth.init(RealmAuth.Resource.CLIENT);
}
/**
@@ -76,22 +76,14 @@ public class ClientTemplatesResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<ClientTemplateRepresentation> getClientTemplates() {
- auth.requireView();
List<ClientTemplateRepresentation> rep = new ArrayList<>();
List<ClientTemplateModel> clientModels = realm.getClientTemplates();
- boolean view = auth.hasView();
+ boolean view = auth.clients().canViewTemplates();
for (ClientTemplateModel clientModel : clientModels) {
- if (view) {
+ if (view || auth.clients().canView(clientModel)) {
rep.add(ModelToRepresentation.toRepresentation(clientModel));
- } else {
- ClientTemplateRepresentation client = new ClientTemplateRepresentation();
- client.setId(clientModel.getId());
- client.setName(clientModel.getName());
- client.setDescription(clientModel.getDescription());
- client.setProtocol(clientModel.getProtocol());
- rep.add(client);
}
}
return rep;
@@ -109,7 +101,7 @@ public class ClientTemplatesResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response createClientTemplate(final @Context UriInfo uriInfo, final ClientTemplateRepresentation rep) {
- auth.requireManage();
+ auth.clients().requireManageTemplates();
try {
ClientTemplateModel clientModel = RepresentationToModel.createClientTemplate(session, realm, rep);
@@ -131,6 +123,9 @@ public class ClientTemplatesResource {
@Path("{id}")
public ClientTemplateResource getClient(final @PathParam("id") String id) {
ClientTemplateModel clientModel = realm.getClientTemplateById(id);
+ if (clientModel == null) {
+ throw new NotFoundException("Could not find client template");
+ }
ClientTemplateResource clientResource = new ClientTemplateResource(realm, auth, clientModel, session, adminEvent);
ResteasyProviderFactory.getInstance().injectProperties(clientResource);
return clientResource;
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ComponentResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ComponentResource.java
index b39b773..c532245 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/ComponentResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ComponentResource.java
@@ -38,7 +38,7 @@ import org.keycloak.representations.idm.ComponentRepresentation;
import org.keycloak.representations.idm.ComponentTypeRepresentation;
import org.keycloak.representations.idm.ConfigPropertyRepresentation;
import org.keycloak.services.ErrorResponse;
-import org.keycloak.services.ErrorResponseException;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.Consumes;
@@ -63,7 +63,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
-import java.util.stream.Collectors;
/**
* @resource Component
@@ -75,7 +74,7 @@ public class ComponentResource {
protected RealmModel realm;
- private RealmAuth auth;
+ private AdminPermissionEvaluator auth;
private AdminEventBuilder adminEvent;
@@ -91,12 +90,10 @@ public class ComponentResource {
@Context
protected HttpHeaders headers;
- public ComponentResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
+ public ComponentResource(RealmModel realm, AdminPermissionEvaluator auth, AdminEventBuilder adminEvent) {
this.auth = auth;
this.realm = realm;
this.adminEvent = adminEvent.resource(ResourceType.COMPONENT);
-
- auth.init(RealmAuth.Resource.REALM);
}
@GET
@@ -105,7 +102,7 @@ public class ComponentResource {
public List<ComponentRepresentation> getComponents(@QueryParam("parent") String parent,
@QueryParam("type") String type,
@QueryParam("name") String name) {
- auth.requireView();
+ auth.realm().requireViewRealm();
List<ComponentModel> components = Collections.EMPTY_LIST;
if (parent == null && type == null) {
components = realm.getComponents();
@@ -135,7 +132,7 @@ public class ComponentResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response create(ComponentRepresentation rep) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
try {
ComponentModel model = RepresentationToModel.toModel(session, rep);
if (model.getParentId() == null) model.setParentId(realm.getId());
@@ -156,7 +153,7 @@ public class ComponentResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public ComponentRepresentation getComponent(@PathParam("id") String id) {
- auth.requireView();
+ auth.realm().requireViewRealm();
ComponentModel model = realm.getComponent(id);
if (model == null) {
throw new NotFoundException("Could not find component");
@@ -169,7 +166,7 @@ public class ComponentResource {
@Path("{id}")
@Consumes(MediaType.APPLICATION_JSON)
public Response updateComponent(@PathParam("id") String id, ComponentRepresentation rep) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
try {
ComponentModel model = realm.getComponent(id);
if (model == null) {
@@ -188,7 +185,7 @@ public class ComponentResource {
@DELETE
@Path("{id}")
public void removeComponent(@PathParam("id") String id) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
ComponentModel model = realm.getComponent(id);
if (model == null) {
throw new NotFoundException("Could not find component");
@@ -199,7 +196,7 @@ public class ComponentResource {
}
private Response localizedErrorResponse(ComponentValidationException cve) {
- Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale(), "admin-messages", "messages");
+ Properties messages = AdminRoot.getMessages(session, realm, auth.adminAuth().getToken().getLocale(), "admin-messages", "messages");
Object[] localizedParameters = cve.getParameters()==null ? null : Arrays.asList(cve.getParameters()).stream().map((Object parameter) -> {
@@ -228,7 +225,7 @@ public class ComponentResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<ComponentTypeRepresentation> getSubcomponentConfig(@PathParam("id") String parentId, @QueryParam("type") String subtype) {
- auth.requireView();
+ auth.realm().requireViewRealm();
ComponentModel parent = realm.getComponent(parentId);
if (parent == null) {
throw new NotFoundException("Could not find parent component");
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java b/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java
index c9fe194..a529a48 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java
@@ -49,6 +49,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.keycloak.services.ErrorResponse;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
/**
* @resource Groups
@@ -58,11 +59,11 @@ public class GroupResource {
private final RealmModel realm;
private final KeycloakSession session;
- private final RealmAuth auth;
+ private final AdminPermissionEvaluator auth;
private final AdminEventBuilder adminEvent;
private final GroupModel group;
- public GroupResource(RealmModel realm, GroupModel group, KeycloakSession session, RealmAuth auth, AdminEventBuilder adminEvent) {
+ public GroupResource(RealmModel realm, GroupModel group, KeycloakSession session, AdminPermissionEvaluator auth, AdminEventBuilder adminEvent) {
this.realm = realm;
this.session = session;
this.auth = auth;
@@ -81,11 +82,7 @@ public class GroupResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public GroupRepresentation getGroup() {
- this.auth.requireView();
-
- if (group == null) {
- throw new NotFoundException("Could not find group by id");
- }
+ this.auth.groups().requireView(group);
return ModelToRepresentation.toGroupHierarchy(group, true);
}
@@ -98,11 +95,7 @@ public class GroupResource {
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public void updateGroup(GroupRepresentation rep) {
- this.auth.requireManage();
-
- if (group == null) {
- throw new NotFoundException("Could not find group by id");
- }
+ this.auth.groups().requireManage(group);
updateGroup(rep, group);
adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
@@ -112,11 +105,7 @@ public class GroupResource {
@DELETE
public void deleteGroup() {
- this.auth.requireManage();
-
- if (group == null) {
- throw new NotFoundException("Could not find group by id");
- }
+ this.auth.groups().requireManage(group);
realm.removeGroup(group);
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
@@ -135,12 +124,8 @@ public class GroupResource {
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response addChild(GroupRepresentation rep) {
- this.auth.requireManage();
+ this.auth.groups().requireManage(group);
- if (group == null) {
- throw new NotFoundException("Could not find group by id");
- }
-
for (GroupModel group : group.getSubGroups()) {
if (group.getName().equals(rep.getName())) {
return ErrorResponse.exists("Parent already contains subgroup named '" + rep.getName() + "'");
@@ -191,9 +176,9 @@ public class GroupResource {
@Path("role-mappings")
public RoleMapperResource getRoleMappings() {
- auth.init(RealmAuth.Resource.USER);
-
- RoleMapperResource resource = new RoleMapperResource(realm, auth, group, adminEvent);
+ AdminPermissionEvaluator.RequirePermissionCheck manageCheck = () -> auth.groups().requireManage(group);
+ AdminPermissionEvaluator.RequirePermissionCheck viewCheck = () -> auth.groups().requireView(group);
+ RoleMapperResource resource = new RoleMapperResource(realm, auth, group, adminEvent, manageCheck, viewCheck);
ResteasyProviderFactory.getInstance().injectProperties(resource);
return resource;
@@ -214,11 +199,8 @@ public class GroupResource {
@Produces(MediaType.APPLICATION_JSON)
public List<UserRepresentation> getMembers(@QueryParam("first") Integer firstResult,
@QueryParam("max") Integer maxResults) {
- auth.requireView();
+ this.auth.groups().requireViewMembers(group);
- if (group == null) {
- throw new NotFoundException("Could not find group by id");
- }
firstResult = firstResult != null ? firstResult : 0;
maxResults = maxResults != null ? maxResults : Constants.DEFAULT_MAX_RESULTS;
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/GroupsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/GroupsResource.java
index 5be1c0d..2a1909b 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/GroupsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/GroupsResource.java
@@ -40,6 +40,7 @@ import javax.ws.rs.core.UriInfo;
import java.net.URI;
import java.util.List;
import org.keycloak.services.ErrorResponse;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
/**
* @resource Groups
@@ -49,15 +50,14 @@ public class GroupsResource {
private final RealmModel realm;
private final KeycloakSession session;
- private final RealmAuth auth;
+ private final AdminPermissionEvaluator auth;
private final AdminEventBuilder adminEvent;
- public GroupsResource(RealmModel realm, KeycloakSession session, RealmAuth auth, AdminEventBuilder adminEvent) {
+ public GroupsResource(RealmModel realm, KeycloakSession session, AdminPermissionEvaluator auth, AdminEventBuilder adminEvent) {
this.realm = realm;
this.session = session;
this.auth = auth;
this.adminEvent = adminEvent.resource(ResourceType.GROUP);
- auth.init(RealmAuth.Resource.USER);
}
@@ -72,7 +72,7 @@ public class GroupsResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<GroupRepresentation> getGroups() {
- auth.requireView();
+ auth.groups().requireList();
return ModelToRepresentation.toGroupHierarchy(realm, false);
}
@@ -85,9 +85,10 @@ public class GroupsResource {
*/
@Path("{id}")
public GroupResource getGroupById(@PathParam("id") String id) {
- auth.requireView();
-
GroupModel group = realm.getGroupById(id);
+ if (group == null) {
+ throw new NotFoundException("Could not find group by id");
+ }
GroupResource resource = new GroupResource(realm, group, session, this.auth, adminEvent);
ResteasyProviderFactory.getInstance().injectProperties(resource);
return resource;
@@ -102,7 +103,7 @@ public class GroupsResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response addTopLevelGroup(GroupRepresentation rep) {
- auth.requireManage();
+ auth.groups().requireManage();
for (GroupModel group : realm.getGroups()) {
if (group.getName().equals(rep.getName())) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
index aa4a054..4c08c20 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
@@ -44,6 +44,7 @@ import org.keycloak.representations.idm.IdentityProviderMapperRepresentation;
import org.keycloak.representations.idm.IdentityProviderMapperTypeRepresentation;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.services.ErrorResponse;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@@ -72,7 +73,7 @@ public class IdentityProviderResource {
protected static final Logger logger = Logger.getLogger(IdentityProviderResource.class);
- private final RealmAuth auth;
+ private final AdminPermissionEvaluator auth;
private final RealmModel realm;
private final KeycloakSession session;
private final IdentityProviderModel identityProviderModel;
@@ -80,7 +81,7 @@ public class IdentityProviderResource {
@Context private UriInfo uriInfo;
- public IdentityProviderResource(RealmAuth auth, RealmModel realm, KeycloakSession session, IdentityProviderModel identityProviderModel, AdminEventBuilder adminEvent) {
+ public IdentityProviderResource(AdminPermissionEvaluator auth, RealmModel realm, KeycloakSession session, IdentityProviderModel identityProviderModel, AdminEventBuilder adminEvent) {
this.realm = realm;
this.session = session;
this.identityProviderModel = identityProviderModel;
@@ -97,7 +98,7 @@ public class IdentityProviderResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public IdentityProviderRepresentation getIdentityProvider() {
- this.auth.requireView();
+ this.auth.realm().requireViewIdentityProviders();
if (identityProviderModel == null) {
throw new javax.ws.rs.NotFoundException();
@@ -115,7 +116,7 @@ public class IdentityProviderResource {
@DELETE
@NoCache
public Response delete() {
- this.auth.requireManage();
+ this.auth.realm().requireManageIdentityProviders();
if (identityProviderModel == null) {
throw new javax.ws.rs.NotFoundException();
@@ -138,7 +139,7 @@ public class IdentityProviderResource {
@Consumes(MediaType.APPLICATION_JSON)
@NoCache
public Response update(IdentityProviderRepresentation providerRep) {
- this.auth.requireManage();
+ this.auth.realm().requireManageIdentityProviders();
if (identityProviderModel == null) {
throw new javax.ws.rs.NotFoundException();
@@ -229,7 +230,7 @@ public class IdentityProviderResource {
@Path("export")
@NoCache
public Response export(@Context UriInfo uriInfo, @QueryParam("format") String format) {
- this.auth.requireView();
+ this.auth.realm().requireViewIdentityProviders();
if (identityProviderModel == null) {
throw new javax.ws.rs.NotFoundException();
@@ -250,7 +251,7 @@ public class IdentityProviderResource {
@Path("mapper-types")
@NoCache
public Map<String, IdentityProviderMapperTypeRepresentation> getMapperTypes() {
- this.auth.requireView();
+ this.auth.realm().requireViewIdentityProviders();
if (identityProviderModel == null) {
throw new javax.ws.rs.NotFoundException();
@@ -289,7 +290,7 @@ public class IdentityProviderResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<IdentityProviderMapperRepresentation> getMappers() {
- this.auth.requireView();
+ this.auth.realm().requireViewIdentityProviders();
if (identityProviderModel == null) {
throw new javax.ws.rs.NotFoundException();
@@ -312,7 +313,7 @@ public class IdentityProviderResource {
@Path("mappers")
@Consumes(MediaType.APPLICATION_JSON)
public Response addMapper(IdentityProviderMapperRepresentation mapper) {
- auth.requireManage();
+ this.auth.realm().requireManageIdentityProviders();
if (identityProviderModel == null) {
throw new javax.ws.rs.NotFoundException();
@@ -343,7 +344,7 @@ public class IdentityProviderResource {
@Path("mappers/{id}")
@Produces(MediaType.APPLICATION_JSON)
public IdentityProviderMapperRepresentation getMapperById(@PathParam("id") String id) {
- auth.requireView();
+ this.auth.realm().requireViewIdentityProviders();
if (identityProviderModel == null) {
throw new javax.ws.rs.NotFoundException();
@@ -365,7 +366,7 @@ public class IdentityProviderResource {
@Path("mappers/{id}")
@Consumes(MediaType.APPLICATION_JSON)
public void update(@PathParam("id") String id, IdentityProviderMapperRepresentation rep) {
- auth.requireManage();
+ this.auth.realm().requireManageIdentityProviders();
if (identityProviderModel == null) {
throw new javax.ws.rs.NotFoundException();
@@ -388,7 +389,7 @@ public class IdentityProviderResource {
@NoCache
@Path("mappers/{id}")
public void delete(@PathParam("id") String id) {
- auth.requireManage();
+ this.auth.realm().requireManageIdentityProviders();
if (identityProviderModel == null) {
throw new javax.ws.rs.NotFoundException();
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
index c5250ac..646b463 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
@@ -37,6 +37,7 @@ import org.keycloak.models.utils.StripSecretsUtils;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.services.ErrorResponse;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.Consumes;
@@ -65,14 +66,13 @@ public class IdentityProvidersResource {
private final RealmModel realm;
private final KeycloakSession session;
- private RealmAuth auth;
+ private AdminPermissionEvaluator auth;
private AdminEventBuilder adminEvent;
- public IdentityProvidersResource(RealmModel realm, KeycloakSession session, RealmAuth auth, AdminEventBuilder adminEvent) {
+ public IdentityProvidersResource(RealmModel realm, KeycloakSession session, AdminPermissionEvaluator auth, AdminEventBuilder adminEvent) {
this.realm = realm;
this.session = session;
this.auth = auth;
- this.auth.init(RealmAuth.Resource.IDENTITY_PROVIDER);
this.adminEvent = adminEvent.resource(ResourceType.IDENTITY_PROVIDER);
}
@@ -87,7 +87,7 @@ public class IdentityProvidersResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public Response getIdentityProviders(@PathParam("provider_id") String providerId) {
- this.auth.requireView();
+ this.auth.realm().requireViewIdentityProviders();
IdentityProviderFactory providerFactory = getProviderFactorytById(providerId);
if (providerFactory != null) {
return Response.ok(providerFactory).build();
@@ -108,7 +108,7 @@ public class IdentityProvidersResource {
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
public Map<String, String> importFrom(@Context UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
- this.auth.requireManage();
+ this.auth.realm().requireManageIdentityProviders();
Map<String, List<InputPart>> formDataMap = input.getFormDataMap();
if (!(formDataMap.containsKey("providerId") && formDataMap.containsKey("file"))) {
throw new BadRequestException();
@@ -134,7 +134,7 @@ public class IdentityProvidersResource {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Map<String, String> importFrom(@Context UriInfo uriInfo, Map<String, Object> data) throws IOException {
- this.auth.requireManage();
+ this.auth.realm().requireManageIdentityProviders();
if (!(data.containsKey("providerId") && data.containsKey("fromUrl"))) {
throw new BadRequestException();
}
@@ -164,7 +164,7 @@ public class IdentityProvidersResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<IdentityProviderRepresentation> getIdentityProviders() {
- this.auth.requireView();
+ this.auth.realm().requireViewIdentityProviders();
List<IdentityProviderRepresentation> representations = new ArrayList<IdentityProviderRepresentation>();
@@ -185,7 +185,7 @@ public class IdentityProvidersResource {
@Path("instances")
@Consumes(MediaType.APPLICATION_JSON)
public Response create(@Context UriInfo uriInfo, IdentityProviderRepresentation representation) {
- this.auth.requireManage();
+ this.auth.realm().requireManageIdentityProviders();
try {
IdentityProviderModel identityProvider = RepresentationToModel.toModel(realm, representation);
@@ -203,7 +203,7 @@ public class IdentityProvidersResource {
@Path("instances/{alias}")
public IdentityProviderResource getIdentityProvider(@PathParam("alias") String alias) {
- this.auth.requireView();
+ this.auth.realm().requireViewIdentityProviders();
IdentityProviderModel identityProviderModel = null;
for (IdentityProviderModel storedIdentityProvider : this.realm.getIdentityProviders()) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/KeyResource.java b/services/src/main/java/org/keycloak/services/resources/admin/KeyResource.java
index f2c9401..d990fd1 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/KeyResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/KeyResource.java
@@ -26,6 +26,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeyManager;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.KeysMetadataRepresentation;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
@@ -43,9 +44,9 @@ public class KeyResource {
private RealmModel realm;
private KeycloakSession session;
- private RealmAuth auth;
+ private AdminPermissionEvaluator auth;
- public KeyResource(RealmModel realm, KeycloakSession session, RealmAuth auth) {
+ public KeyResource(RealmModel realm, KeycloakSession session, AdminPermissionEvaluator auth) {
this.realm = realm;
this.session = session;
this.auth = auth;
@@ -55,7 +56,7 @@ public class KeyResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public KeysMetadataRepresentation getKeyMetadata() {
- auth.requireView();
+ auth.realm().requireViewRealm();
KeyManager keystore = session.keys();
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissionEvaluator.java
new file mode 100644
index 0000000..56be4cf
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissionEvaluator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.keycloak.services.resources.admin.AdminAuth;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface AdminPermissionEvaluator {
+ RealmPermissionEvaluator realm();
+
+ AdminAuth adminAuth();
+
+ RolePermissionEvaluator roles();
+ UserPermissionEvaluator users();
+ ClientPermissionEvaluator clients();
+ GroupPermissionEvaluator groups();
+
+ /**
+ * Useful as a function pointer, i.e. RoleMapperResource is reused bewteen GroupResource and UserResource to manage role mappings.
+ * We don't know what type of resource we're managing here (user or group), so we don't know how to query the policy engine to determine
+ * if an action is allowed.
+ *
+ */
+ interface PermissionCheck {
+ boolean evaluate();
+ }
+ /**
+ * Useful as a function pointer, i.e. RoleMapperResource is reused bewteen GroupResource and UserResource to manage role mappings.
+ * We don't know what type of resource we're managing here (user or group), so we don't know how to query the policy engine to determine
+ * if an action is allowed.
+ *
+ * throws appropriate exception if permission is deny
+ *
+ */
+ interface RequirePermissionCheck {
+ void require();
+ }
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissionManagement.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissionManagement.java
new file mode 100644
index 0000000..1f0a34d
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissionManagement.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.keycloak.authorization.model.ResourceServer;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface AdminPermissionManagement {
+ public static final String MANAGE_SCOPE = "manage";
+ public static final String VIEW_SCOPE = "view";
+
+ RolePermissionManagement roles();
+ UserPermissionManagement users();
+ GroupPermissionManagement groups();
+ ClientPermissionManagement clients();
+
+ ResourceServer realmResourceServer();
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissions.java
new file mode 100644
index 0000000..61a8bff
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissions.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.services.resources.admin.AdminAuth;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AdminPermissions {
+
+
+ public static AdminPermissionEvaluator evaluator(KeycloakSession session, RealmModel realm, AdminAuth auth) {
+ return new MgmtPermissions(session, realm, auth);
+ }
+ public static AdminPermissionEvaluator evaluator(KeycloakSession session, RealmModel realm, RealmModel adminsRealm, UserModel admin) {
+ return new MgmtPermissions(session, realm, adminsRealm, admin);
+ }
+
+ public static AdminPermissionManagement management(KeycloakSession session, RealmModel realm) {
+ return new MgmtPermissions(session, realm);
+ }
+
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java
new file mode 100644
index 0000000..8f0af4b
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientTemplateModel;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface ClientPermissionEvaluator {
+ boolean isPermissionsEnabled(ClientModel client);
+
+ void setPermissionsEnabled(ClientModel client, boolean enable);
+
+ boolean canManage();
+
+ void requireManage();
+
+ boolean canManageTemplates();
+
+ void requireManageTemplates();
+
+ boolean canView();
+
+ boolean canList();
+
+ boolean canViewTemplates();
+
+ void requireList();
+
+ boolean canListTemplates();
+
+ void requireView();
+
+ void requireViewTemplates();
+
+ boolean canManage(ClientModel client);
+
+ void requireManage(ClientModel client);
+
+ boolean canView(ClientModel client);
+
+ void requireView(ClientModel client);
+
+ boolean canManage(ClientTemplateModel template);
+
+ void requireManage(ClientTemplateModel template);
+
+ boolean canView(ClientTemplateModel template);
+
+ void requireView(ClientTemplateModel template);
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionManagement.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionManagement.java
new file mode 100644
index 0000000..27f5527
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionManagement.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.keycloak.models.ClientModel;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface ClientPermissionManagement {
+ boolean isPermissionsEnabled(ClientModel client);
+
+ void setPermissionsEnabled(ClientModel client, boolean enable);
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java
new file mode 100644
index 0000000..da1d24b
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.jboss.logging.Logger;
+import org.keycloak.authorization.AuthorizationProvider;
+import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.Resource;
+import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.authorization.model.Scope;
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientTemplateModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.services.ForbiddenException;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Manages default policies for all users.
+ *
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionManagement {
+ private static final Logger logger = Logger.getLogger(ClientPermissions.class);
+ protected final KeycloakSession session;
+ protected final RealmModel realm;
+ protected final AuthorizationProvider authz;
+ protected final MgmtPermissions root;
+
+ public ClientPermissions(KeycloakSession session, RealmModel realm, AuthorizationProvider authz, MgmtPermissions root) {
+ this.session = session;
+ this.realm = realm;
+ this.authz = authz;
+ this.root = root;
+ }
+
+ private String getResourceName(ClientModel client) {
+ return "group.resource." + client.getId();
+ }
+
+ private String getManagePermissionName(ClientModel client) {
+ return "manage.permission.client." + client.getId();
+ }
+ private String getViewPermissionName(ClientModel client) {
+ return "view.permission.client." + client.getId();
+ }
+
+ private void initialize(ClientModel client) {
+ ResourceServer server = root.findOrCreateResourceServer(client);
+ Scope manageScope = manageScope(server);
+ if (manageScope == null) {
+ authz.getStoreFactory().getScopeStore().create(AdminPermissionManagement.MANAGE_SCOPE, server);
+ }
+ Scope viewScope = viewScope(server);
+ if (manageScope == null) {
+ authz.getStoreFactory().getScopeStore().create(AdminPermissionManagement.VIEW_SCOPE, server);
+ }
+
+ String resourceName = getResourceName(client);
+ Resource resource = authz.getStoreFactory().getResourceStore().findByName(resourceName, server.getId());
+ if (resource == null) {
+ resource = authz.getStoreFactory().getResourceStore().create(resourceName, server, server.getClientId());
+ Set<Scope> scopeset = new HashSet<>();
+ scopeset.add(manageScope);
+ scopeset.add(viewScope);
+ resource.updateScopes(scopeset);
+ }
+ String managePermissionName = getManagePermissionName(client);
+ Policy managePermission = authz.getStoreFactory().getPolicyStore().findByName(managePermissionName, server.getId());
+ if (managePermission == null) {
+ RoleModel role = root.getRealmManagementClient().getRole(AdminRoles.MANAGE_CLIENTS);
+ Policy manageClientsPolicy = root.roles().rolePolicy(server, role);
+ Helper.addScopePermission(authz, server, managePermissionName, resource, manageScope, manageClientsPolicy);
+ }
+ String viewPermissionName = getViewPermissionName(client);
+ Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(viewPermissionName, server.getId());
+ if (viewPermission == null) {
+ RoleModel role = root.getRealmManagementClient().getRole(AdminRoles.VIEW_CLIENTS);
+ Policy viewClientsPolicy = root.roles().rolePolicy(server, role);
+ Helper.addScopePermission(authz, server, viewPermissionName, resource, viewScope, viewClientsPolicy);
+ }
+ }
+
+ private void deletePermissions(ClientModel client) {
+ ResourceServer server = authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
+ if (server == null) return;
+ Policy managePermission = authz.getStoreFactory().getPolicyStore().findByName(getManagePermissionName(client), server.getId());
+ if (managePermission != null) {
+ authz.getStoreFactory().getPolicyStore().delete(managePermission.getId());
+ }
+ Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(getViewPermissionName(client), server.getId());
+ if (viewPermission != null) {
+ authz.getStoreFactory().getPolicyStore().delete(viewPermission.getId());
+ }
+ Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());;
+ if (resource != null) authz.getStoreFactory().getResourceStore().delete(resource.getId());
+ }
+
+ @Override
+ public boolean isPermissionsEnabled(ClientModel client) {
+ ResourceServer server = authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
+ if (server == null) return false;
+
+ return authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId()) != null;
+ }
+
+ @Override
+ public void setPermissionsEnabled(ClientModel client, boolean enable) {
+ if (enable) {
+ initialize(client);
+ } else {
+ deletePermissions(client);
+ }
+ }
+
+
+
+ private Scope manageScope(ResourceServer server) {
+ return authz.getStoreFactory().getScopeStore().findByName(AdminPermissionManagement.MANAGE_SCOPE, server.getId());
+ }
+
+ private Scope viewScope(ResourceServer server) {
+ return authz.getStoreFactory().getScopeStore().findByName(AdminPermissionManagement.VIEW_SCOPE, server.getId());
+ }
+
+ @Override
+ public boolean canList() {
+ return root.hasAnyAdminRole();
+ }
+
+ @Override
+ public void requireList() {
+ if (!canList()) {
+ throw new ForbiddenException();
+ }
+ }
+
+ @Override
+ public boolean canListTemplates() {
+ return root.hasAnyAdminRole();
+ }
+
+ public boolean canManageClientDefault() {
+ return root.hasOneAdminRole(AdminRoles.MANAGE_CLIENTS);
+ }
+ public boolean canViewClientDefault() {
+ return root.hasOneAdminRole(AdminRoles.MANAGE_CLIENTS, AdminRoles.VIEW_CLIENTS);
+ }
+
+ @Override
+ public boolean canManage() {
+ return canManageClientDefault();
+ }
+
+ @Override
+ public void requireManage() {
+ if (!canManage()) {
+ throw new ForbiddenException();
+ }
+ }
+ @Override
+ public boolean canView() {
+ return canManageClientDefault() || canViewClientDefault();
+ }
+
+ @Override
+ public void requireView() {
+ if (!canView()) {
+ throw new ForbiddenException();
+ }
+ }
+
+ @Override
+ public boolean canManage(ClientModel client) {
+ if (!root.isAdminSameRealm()) {
+ return canManage();
+ }
+
+ ResourceServer server = authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
+ if (server == null) return canManage();
+
+ Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
+ if (resource == null) return canManage();
+
+ Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getManagePermissionName(client), server.getId());
+ if (policy == null) {
+ return canManage();
+ }
+
+ Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
+ // if no policies attached to permission then just do default behavior
+ if (associatedPolicies == null || associatedPolicies.isEmpty()) {
+ return canManage();
+ }
+
+ Scope scope = manageScope(server);
+ return root.evaluatePermission(resource, scope, server);
+ }
+
+ @Override
+ public void requireManage(ClientModel client) {
+ if (!canManage(client)) {
+ throw new ForbiddenException();
+ }
+ }
+
+ @Override
+ public boolean canView(ClientModel client) {
+ if (!root.isAdminSameRealm()) {
+ return canView();
+ }
+
+ ResourceServer server = authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
+ if (server == null) return canView();
+
+ Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
+ if (resource == null) return canView();
+
+ Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getViewPermissionName(client), server.getId());
+ if (policy == null) {
+ return canView();
+ }
+
+ Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
+ // if no policies attached to permission then just do default behavior
+ if (associatedPolicies == null || associatedPolicies.isEmpty()) {
+ return canView();
+ }
+
+ Scope scope = viewScope(server);
+ return root.evaluatePermission(resource, scope, server);
+ }
+
+ @Override
+ public void requireView(ClientModel client) {
+ if (!canView(client)) {
+ throw new ForbiddenException();
+ }
+ }
+
+ // templates
+
+ @Override
+ public boolean canViewTemplates() {
+ return canView();
+ }
+
+ @Override
+ public boolean canManageTemplates() {
+ return canManageClientDefault();
+ }
+
+ @Override
+ public void requireManageTemplates() {
+ if (!canManageTemplates()) {
+ throw new ForbiddenException();
+ }
+ }
+ @Override
+ public void requireViewTemplates() {
+ if (!canViewTemplates()) {
+ throw new ForbiddenException();
+ }
+ }
+
+ @Override
+ public boolean canManage(ClientTemplateModel template) {
+ return canManageClientDefault();
+ }
+
+ @Override
+ public void requireManage(ClientTemplateModel template) {
+ if (!canManage(template)) {
+ throw new ForbiddenException();
+ }
+ }
+
+ @Override
+ public boolean canView(ClientTemplateModel template) {
+ return canViewClientDefault();
+ }
+
+ @Override
+ public void requireView(ClientTemplateModel template) {
+ if (!canView(template)) {
+ throw new ForbiddenException();
+ }
+ }
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionEvaluator.java
new file mode 100644
index 0000000..91ca5c5
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionEvaluator.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.keycloak.models.GroupModel;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface GroupPermissionEvaluator {
+ boolean canList();
+
+ void requireList();
+
+ boolean canManage(GroupModel group);
+
+ void requireManage(GroupModel group);
+
+ boolean canView(GroupModel group);
+
+ void requireView(GroupModel group);
+
+ boolean canManage();
+
+ void requireManage();
+
+ boolean canView();
+
+ void requireView();
+
+ boolean canViewMembers(GroupModel group);
+
+ void requireViewMembers(GroupModel group);
+
+ boolean canManageMembers(GroupModel group);
+
+ void requireManageMembers(GroupModel group);
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionManagement.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionManagement.java
new file mode 100644
index 0000000..5f4097b
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionManagement.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.keycloak.authorization.model.Policy;
+import org.keycloak.models.GroupModel;
+import org.keycloak.models.RoleModel;
+
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface GroupPermissionManagement {
+ boolean isPermissionsEnabled(GroupModel group);
+ void setPermissionsEnabled(GroupModel group, boolean enable);
+
+ Policy viewMembersPermission(GroupModel group);
+ Policy manageMembersPermission(GroupModel group);
+ Policy viewPermissionGroup(GroupModel group);
+ Policy managePermissionGroup(GroupModel group);
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissions.java
new file mode 100644
index 0000000..46d8fb6
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissions.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.jboss.logging.Logger;
+import org.keycloak.authorization.AuthorizationProvider;
+import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.Resource;
+import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.authorization.model.Scope;
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.GroupModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.services.ForbiddenException;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManagement {
+ private static final Logger logger = Logger.getLogger(GroupPermissions.class);
+ public static final String MAP_ROLE_SCOPE = "map-role";
+ public static final String MANAGE_MEMBERS_SCOPE = "manage.members";
+ public static final String VIEW_MEMBERS_SCOPE = "view.members";
+ protected final KeycloakSession session;
+ protected final RealmModel realm;
+ protected final AuthorizationProvider authz;
+ protected final MgmtPermissions root;
+
+ public GroupPermissions(KeycloakSession session, RealmModel realm, AuthorizationProvider authz, MgmtPermissions root) {
+ this.session = session;
+ this.realm = realm;
+ this.authz = authz;
+ this.root = root;
+ }
+
+ private static String getGroupResourceName(GroupModel group) {
+ return "group.resource." + getGroupSuffix(group);
+ }
+
+
+ public static String getManagePermissionGroup(GroupModel group) {
+ return "manage.permission.group." + getGroupSuffix(group);
+ }
+
+ public static String getManageMembersPermissionGroup(GroupModel group) {
+ return "manage.members.permission.group." + getGroupSuffix(group);
+ }
+
+ public static String getGroupSuffix(GroupModel group) {
+ return ModelToRepresentation.buildGroupPath(group).replace('/', '.');
+ }
+
+ public static String getViewPermissionGroup(GroupModel group) {
+ return "view.permission.group." + getGroupSuffix(group);
+ }
+
+ public static String getViewMembersPermissionGroup(GroupModel group) {
+ return "view.members.permission.group." + getGroupSuffix(group);
+ }
+
+ private void initialize(GroupModel group) {
+ root.initializeRealmResourceServer();
+ root.initializeRealmDefaultScopes();
+ ResourceServer server = root.realmResourceServer();
+ Scope manageScope = root.realmManageScope();
+ Scope viewScope = root.realmViewScope();
+ Scope manageMembersScope = root.initializeRealmScope(MANAGE_MEMBERS_SCOPE);
+ Scope viewMembersScope = root.initializeRealmScope(VIEW_MEMBERS_SCOPE);
+
+ String groupResourceName = getGroupResourceName(group);
+ Resource groupResource = authz.getStoreFactory().getResourceStore().findByName(groupResourceName, server.getId());
+ if (groupResource == null) {
+ groupResource = authz.getStoreFactory().getResourceStore().create(groupResourceName, server, server.getClientId());
+ Set<Scope> scopeset = new HashSet<>();
+ scopeset.add(manageScope);
+ scopeset.add(viewScope);
+ groupResource.updateScopes(scopeset);
+ }
+ String managePermissionName = getManagePermissionGroup(group);
+ Policy managePermission = authz.getStoreFactory().getPolicyStore().findByName(managePermissionName, server.getId());
+ if (managePermission == null) {
+ Policy manageUsersPolicy = root.roles().manageUsersPolicy(server);
+ Helper.addScopePermission(authz, server, managePermissionName, groupResource, manageScope, manageUsersPolicy);
+ }
+ String viewPermissionName = getManagePermissionGroup(group);
+ Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(viewPermissionName, server.getId());
+ if (viewPermission == null) {
+ Policy viewUsersPolicy = root.roles().viewUsersPolicy(server);
+ Helper.addScopePermission(authz, server, viewPermissionName, groupResource, viewScope, viewUsersPolicy);
+ }
+ String manageMembersPermissionName = getManageMembersPermissionGroup(group);
+ Policy manageMembersPermission = authz.getStoreFactory().getPolicyStore().findByName(manageMembersPermissionName, server.getId());
+ if (manageMembersPermission == null) {
+ Policy manageUsersPolicy = root.roles().manageUsersPolicy(server);
+ Helper.addScopePermission(authz, server, manageMembersPermissionName, groupResource, manageMembersScope, manageUsersPolicy);
+ }
+ String viewMembersPermissionName = getViewMembersPermissionGroup(group);
+ Policy viewMembersPermission = authz.getStoreFactory().getPolicyStore().findByName(viewMembersPermissionName, server.getId());
+ if (viewMembersPermission == null) {
+ Policy viewUsersPolicy = root.roles().viewUsersPolicy(server);
+ Helper.addScopePermission(authz, server, viewMembersPermissionName, groupResource, viewMembersScope, viewUsersPolicy);
+ }
+ }
+
+ @Override
+ public boolean canList() {
+ return root.hasOneAdminRole(AdminRoles.VIEW_USERS, AdminRoles.MANAGE_USERS);
+ }
+
+ @Override
+ public void requireList() {
+ if (!canList()) {
+ throw new ForbiddenException();
+ }
+ }
+
+
+
+ @Override
+ public boolean isPermissionsEnabled(GroupModel group) {
+ ResourceServer server = root.realmResourceServer();
+ if (server == null) return false;
+
+ return authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId()) != null;
+ }
+
+ private Resource groupResource(GroupModel group) {
+ ResourceServer server = root.realmResourceServer();
+ if (server == null) return null;
+ String groupResourceName = getGroupResourceName(group);
+ return authz.getStoreFactory().getResourceStore().findByName(groupResourceName, server.getId());
+ }
+
+ @Override
+ public void setPermissionsEnabled(GroupModel group, boolean enable) {
+ if (enable) {
+ initialize(group);
+ } else {
+ deletePermissions(group);
+ }
+ }
+
+ private void deletePermissions(GroupModel group) {
+ ResourceServer server = root.realmResourceServer();
+ if (server == null) return;
+ Policy managePermission = managePermissionGroup(group);
+ if (managePermission != null) {
+ authz.getStoreFactory().getPolicyStore().delete(managePermission.getId());
+ }
+ Policy viewPermission = viewPermissionGroup(group);
+ if (viewPermission != null) {
+ authz.getStoreFactory().getPolicyStore().delete(viewPermission.getId());
+ }
+ Policy manageMembersPermission = manageMembersPermission(group);
+ if (manageMembersPermission != null) {
+ authz.getStoreFactory().getPolicyStore().delete(manageMembersPermission.getId());
+ }
+ Policy viewMembersPermission = viewMembersPermission(group);
+ if (manageMembersPermission == null) {
+ authz.getStoreFactory().getPolicyStore().delete(viewMembersPermission.getId());
+ }
+ Resource resource = groupResource(group);
+ if (resource != null) authz.getStoreFactory().getResourceStore().delete(resource.getId());
+ }
+
+ @Override
+ public Policy viewMembersPermission(GroupModel group) {
+ ResourceServer server = root.realmResourceServer();
+ if (server == null) return null;
+ String viewMembersPermissionName = getViewMembersPermissionGroup(group);
+ return authz.getStoreFactory().getPolicyStore().findByName(viewMembersPermissionName, server.getId());
+ }
+
+ @Override
+ public Policy manageMembersPermission(GroupModel group) {
+ ResourceServer server = root.realmResourceServer();
+ if (server == null) return null;
+ String manageMembersPermissionName = getManageMembersPermissionGroup(group);
+ return authz.getStoreFactory().getPolicyStore().findByName(manageMembersPermissionName, server.getId());
+ }
+
+ @Override
+ public Policy viewPermissionGroup(GroupModel group) {
+ ResourceServer server = root.realmResourceServer();
+ if (server == null) return null;
+ String viewPermissionName = getViewPermissionGroup(group);
+ return authz.getStoreFactory().getPolicyStore().findByName(viewPermissionName, server.getId());
+ }
+
+ @Override
+ public Policy managePermissionGroup(GroupModel group) {
+ ResourceServer server = root.realmResourceServer();
+ if (server == null) return null;
+ String managePermissionName = getManagePermissionGroup(group);
+ return authz.getStoreFactory().getPolicyStore().findByName(managePermissionName, server.getId());
+ }
+
+
+ @Override
+ public boolean canManage(GroupModel group) {
+ if (!root.isAdminSameRealm()) {
+ return canManage();
+ }
+
+ ResourceServer server = root.realmResourceServer();
+ if (server == null) return canManage();
+
+ Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
+ if (resource == null) return canManage();
+
+ Policy policy = managePermissionGroup(group);
+ if (policy == null) {
+ return canManage();
+ }
+
+ Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
+ // if no policies attached to permission then just do default behavior
+ if (associatedPolicies == null || associatedPolicies.isEmpty()) {
+ return canManage();
+ }
+
+ Scope scope = root.realmManageScope();
+ return root.evaluatePermission(resource, scope, server);
+ }
+
+ @Override
+ public void requireManage(GroupModel group) {
+ if (!canManage(group)) {
+ throw new ForbiddenException();
+ }
+ }
+ @Override
+ public boolean canView(GroupModel group) {
+ if (!root.isAdminSameRealm()) {
+ return canView();
+ }
+
+ ResourceServer server = root.realmResourceServer();
+ if (server == null) return canView();
+
+ Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
+ if (resource == null) return canView();
+
+ Policy policy = viewPermissionGroup(group);
+ if (policy == null) {
+ return canView();
+ }
+
+ Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
+ // if no policies attached to permission then abort
+ if (associatedPolicies == null || associatedPolicies.isEmpty()) {
+ return canView();
+ }
+
+ Scope scope = root.realmViewScope();
+ return root.evaluatePermission(resource, scope, server);
+ }
+
+ @Override
+ public void requireView(GroupModel group) {
+ if (!canView(group)) {
+ throw new ForbiddenException();
+ }
+ }
+
+ @Override
+ public boolean canManage() {
+ return root.users().canManageDefault();
+ }
+
+ @Override
+ public void requireManage() {
+ if (!canManage()) {
+ throw new ForbiddenException();
+ }
+ }
+ @Override
+ public boolean canView() {
+ return root.users().canViewDefault();
+ }
+
+ @Override
+ public void requireView() {
+ if (!canView()) {
+ throw new ForbiddenException();
+ }
+ }
+
+
+
+ @Override
+ public boolean canViewMembers(GroupModel group) {
+ if (!root.isAdminSameRealm()) {
+ return root.users().canView();
+ }
+
+ ResourceServer server = root.realmResourceServer();
+ if (server == null) return root.users().canView();
+
+ Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
+ if (resource == null) return root.users().canView();
+
+ Policy policy = viewMembersPermission(group);
+ if (policy == null) {
+ return root.users().canView();
+ }
+
+ Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
+ // if no policies attached to permission then just do default behavior
+ if (associatedPolicies == null || associatedPolicies.isEmpty()) {
+ return root.users().canView();
+ }
+
+ Scope scope = authz.getStoreFactory().getScopeStore().findByName(VIEW_MEMBERS_SCOPE, server.getId());
+
+ return root.evaluatePermission(resource, scope, server);
+ }
+
+ @Override
+ public void requireViewMembers(GroupModel group) {
+ if (!canViewMembers(group)) {
+ throw new ForbiddenException();
+ }
+ }
+
+
+ @Override
+ public boolean canManageMembers(GroupModel group) {
+ if (!root.isAdminSameRealm()) {
+ return root.users().canManage();
+ }
+
+ ResourceServer server = root.realmResourceServer();
+ if (server == null) return root.users().canManage();
+
+ Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
+ if (resource == null) return root.users().canManage();
+
+ Policy policy = manageMembersPermission(group);
+ if (policy == null) {
+ return root.users().canManage();
+ }
+
+ Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
+ // if no policies attached to permission then just do default behavior
+ if (associatedPolicies == null || associatedPolicies.isEmpty()) {
+ return root.users().canManage();
+ }
+
+ Scope scope = authz.getStoreFactory().getScopeStore().findByName(MANAGE_MEMBERS_SCOPE, server.getId());
+ return root.evaluatePermission(resource, scope, server);
+ }
+
+ @Override
+ public void requireManageMembers(GroupModel group) {
+ if (!canManageMembers(group)) {
+ throw new ForbiddenException();
+ }
+ }
+
+
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/MgmtPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/MgmtPermissions.java
new file mode 100644
index 0000000..9434283
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/MgmtPermissions.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.authorization.AuthorizationProvider;
+import org.keycloak.authorization.AuthorizationProviderFactory;
+import org.keycloak.authorization.Decision;
+import org.keycloak.authorization.common.DefaultEvaluationContext;
+import org.keycloak.authorization.common.KeycloakIdentity;
+import org.keycloak.authorization.common.UserModelIdentity;
+import org.keycloak.authorization.identity.Identity;
+import org.keycloak.authorization.model.Resource;
+import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.authorization.model.Scope;
+import org.keycloak.authorization.permission.ResourcePermission;
+import org.keycloak.authorization.permission.evaluator.PermissionEvaluator;
+import org.keycloak.authorization.policy.evaluation.DecisionResult;
+import org.keycloak.authorization.policy.evaluation.EvaluationContext;
+import org.keycloak.authorization.store.ResourceServerStore;
+import org.keycloak.authorization.util.Permissions;
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.services.ForbiddenException;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.services.resources.admin.AdminAuth;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManagement {
+ private static final Logger logger = Logger.getLogger(MgmtPermissions.class);
+
+ protected RealmModel realm;
+ protected KeycloakSession session;
+ protected AuthorizationProvider authz;
+ protected AdminAuth auth;
+ protected Identity identity;
+ protected UserModel admin;
+ protected RealmModel adminsRealm;
+ protected ResourceServer realmResourceServer;
+ protected UserPermissions users;
+ protected GroupPermissions groups;
+ protected RealmPermissions realmPermissions;
+ protected ClientPermissions clientPermissions;
+
+
+ MgmtPermissions(KeycloakSession session, RealmModel realm) {
+ this.session = session;
+ this.realm = realm;
+ KeycloakSessionFactory keycloakSessionFactory = session.getKeycloakSessionFactory();
+ AuthorizationProviderFactory factory = (AuthorizationProviderFactory) keycloakSessionFactory.getProviderFactory(AuthorizationProvider.class);
+ this.authz = factory.create(session, realm);
+ }
+
+ MgmtPermissions(KeycloakSession session, RealmModel realm, AdminAuth auth) {
+ this(session, realm);
+ this.auth = auth;
+ this.admin = auth.getUser();
+ this.adminsRealm = auth.getRealm();
+ if (!auth.getRealm().equals(realm)
+ && !auth.getRealm().equals(new RealmManager(session).getKeycloakAdminstrationRealm())) {
+ throw new ForbiddenException();
+ }
+ if (auth.getClient().getClientId().equals(Constants.ADMIN_CLI_CLIENT_ID)) {
+ this.identity = new UserModelIdentity(auth.getRealm(), auth.getUser());
+
+ } else {
+ this.identity = new KeycloakIdentity(auth.getToken(), session);
+ }
+ }
+ MgmtPermissions(KeycloakSession session, RealmModel realm, RealmModel adminsRealm, UserModel admin) {
+ this(session, realm);
+ this.admin = admin;
+ this.adminsRealm = adminsRealm;
+ this.identity = new UserModelIdentity(realm, admin);
+ }
+
+ public ClientModel getRealmManagementClient() {
+ ClientModel client = null;
+ if (realm.getName().equals(Config.getAdminRealm())) {
+ client = realm.getClientByClientId(Config.getAdminRealm() + "-realm");
+ } else {
+ client = realm.getClientByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID);
+
+ }
+ return client;
+ }
+
+
+
+ public boolean hasAnyAdminRole() {
+ return hasOneAdminRole(AdminRoles.ALL_REALM_ROLES);
+ }
+
+ public boolean hasOneAdminRole(String... adminRoles) {
+ String clientId;
+ RealmManager realmManager = new RealmManager(session);
+ if (adminsRealm.equals(realmManager.getKeycloakAdminstrationRealm())) {
+ clientId = realm.getMasterAdminClient().getClientId();
+ } else {
+ clientId = realm.getClientByClientId(realmManager.getRealmAdminClientId(auth.getRealm())).getClientId();
+ }
+ for (String adminRole : adminRoles) {
+ if (identity.hasClientRole(clientId, adminRole)) return true;
+ }
+ return false;
+ }
+
+
+
+ public boolean isAdminSameRealm() {
+ return auth == null || realm.getId().equals(auth.getRealm().getId());
+ }
+
+ @Override
+ public AdminAuth adminAuth() {
+ return auth;
+ }
+
+ public Identity identity() {
+ return identity;
+ }
+
+ public UserModel admin() {
+ return admin;
+ }
+
+
+ @Override
+ public RolePermissions roles() {
+ return new RolePermissions(session, realm, authz, this);
+ }
+
+ @Override
+ public UserPermissions users() {
+ if (users != null) return users;
+ users = new UserPermissions(session, realm, authz, this);
+ return users;
+ }
+
+ @Override
+ public RealmPermissions realm() {
+ if (realmPermissions != null) return realmPermissions;
+ realmPermissions = new RealmPermissions(session, realm, authz, this);
+ return realmPermissions;
+ }
+
+ @Override
+ public ClientPermissions clients() {
+ if (clientPermissions != null) return clientPermissions;
+ clientPermissions = new ClientPermissions(session, realm, authz, this);
+ return clientPermissions;
+ }
+
+ @Override
+ public GroupPermissions groups() {
+ if (groups != null) return groups;
+ groups = new GroupPermissions(session, realm, authz, this);
+ return groups;
+ }
+
+ public ResourceServer findOrCreateResourceServer(ClientModel client) {
+ ResourceServer server = authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
+ if (server == null) {
+ server = authz.getStoreFactory().getResourceServerStore().create(client.getId());
+ }
+ return server;
+ }
+
+ @Override
+ public ResourceServer realmResourceServer() {
+ if (realmResourceServer != null) return realmResourceServer;
+ ResourceServerStore resourceServerStore = authz.getStoreFactory().getResourceServerStore();
+ ClientModel client = getRealmManagementClient();
+ realmResourceServer = authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
+ return realmResourceServer;
+
+ }
+
+ public ResourceServer initializeRealmResourceServer() {
+ if (realmResourceServer != null) return realmResourceServer;
+ ClientModel client = getRealmManagementClient();
+ return findOrCreateResourceServer(client);
+ }
+
+ protected Scope manageScope;
+ protected Scope viewScope;
+
+ public void initializeRealmDefaultScopes() {
+ ResourceServer server = initializeRealmResourceServer();
+ manageScope = initializeRealmScope(MgmtPermissions.MANAGE_SCOPE);
+ viewScope = initializeRealmScope(MgmtPermissions.VIEW_SCOPE);
+ }
+
+ public Scope initializeRealmScope(String name) {
+ ResourceServer server = initializeRealmResourceServer();
+ Scope scope = authz.getStoreFactory().getScopeStore().findByName(name, server.getId());
+ if (scope == null) {
+ scope = authz.getStoreFactory().getScopeStore().create(name, server);
+ }
+ return scope;
+ }
+
+
+
+ public Scope realmManageScope() {
+ if (manageScope != null) return manageScope;
+ manageScope = realmScope(MgmtPermissions.MANAGE_SCOPE);
+ return manageScope;
+ }
+
+
+ public Scope realmViewScope() {
+ if (viewScope != null) return viewScope;
+ viewScope = realmScope(MgmtPermissions.VIEW_SCOPE);
+ return viewScope;
+ }
+
+ public Scope realmScope(String scope) {
+ ResourceServer server = realmResourceServer();
+ if (server == null) return null;
+ return authz.getStoreFactory().getScopeStore().findByName(scope, server.getId());
+ }
+
+ public boolean evaluatePermission(Resource resource, Scope scope, ResourceServer resourceServer) {
+ Identity identity = identity();
+ if (identity == null) {
+ throw new RuntimeException("Identity of admin is not set for permission query");
+ }
+ RealmModel oldRealm = session.getContext().getRealm();
+ try {
+ session.getContext().setRealm(realm);
+ EvaluationContext context = new DefaultEvaluationContext(identity, session);
+ DecisionResult decisionCollector = new DecisionResult();
+ List<ResourcePermission> permissions = Permissions.permission(resourceServer, resource, scope);
+ PermissionEvaluator from = authz.evaluators().from(permissions, context);
+ from.evaluate(decisionCollector);
+ if (!decisionCollector.completed()) {
+ logger.error("Failed to run permission check", decisionCollector.getError());
+ return false;
+ }
+ return decisionCollector.getResults().get(0).getEffect() == Decision.Effect.PERMIT;
+ } finally {
+ session.getContext().setRealm(oldRealm);
+ }
+ }
+
+
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmPermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmPermissionEvaluator.java
new file mode 100644
index 0000000..cf350a1
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmPermissionEvaluator.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface RealmPermissionEvaluator {
+ boolean canListRealm();
+
+ void requireViewRealmNameList();
+
+ boolean canManageRealm();
+
+ void requireManageRealm();
+
+ boolean canViewRealm();
+
+ void requireViewRealm();
+
+ boolean canManageIdentityProviders();
+
+ boolean canViewIdentityProviders();
+
+ void requireViewIdentityProviders();
+
+ void requireManageIdentityProviders();
+
+ boolean canManageAuthorization();
+
+ boolean canViewAuthorization();
+
+ void requireManageAuthorization();
+
+ void requireViewAuthorization();
+
+ boolean canManageEvents();
+
+ void requireManageEvents();
+
+ boolean canViewEvents();
+
+ void requireViewEvents();
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmPermissions.java
new file mode 100644
index 0000000..84b6ceb
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmPermissions.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.jboss.logging.Logger;
+import org.keycloak.authorization.AuthorizationProvider;
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.services.ForbiddenException;
+
+/**
+ * Manages default policies for all users.
+ *
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+class RealmPermissions implements RealmPermissionEvaluator {
+ private static final Logger logger = Logger.getLogger(RealmPermissions.class);
+ protected final KeycloakSession session;
+ protected final RealmModel realm;
+ protected final AuthorizationProvider authz;
+ protected final MgmtPermissions root;
+
+ public RealmPermissions(KeycloakSession session, RealmModel realm, AuthorizationProvider authz, MgmtPermissions root) {
+ this.session = session;
+ this.realm = realm;
+ this.authz = authz;
+ this.root = root;
+ }
+
+
+ public boolean canManageRealmDefault() {
+ return root.hasOneAdminRole(AdminRoles.MANAGE_REALM);
+
+ }
+ public boolean canViewRealmDefault() {
+ return root.hasOneAdminRole(AdminRoles.MANAGE_REALM, AdminRoles.VIEW_REALM);
+ }
+
+ public boolean canManageIdentityProvidersDefault() {
+ return root.hasOneAdminRole(AdminRoles.MANAGE_IDENTITY_PROVIDERS);
+
+ }
+ public boolean canViewIdentityProvidersDefault() {
+ return root.hasOneAdminRole(AdminRoles.MANAGE_IDENTITY_PROVIDERS, AdminRoles.VIEW_IDENTITY_PROVIDERS);
+ }
+
+ public boolean canManageAuthorizationDefault() {
+ return root.hasOneAdminRole(AdminRoles.MANAGE_AUTHORIZATION);
+
+ }
+ public boolean canViewAuthorizationDefault() {
+ return root.hasOneAdminRole(AdminRoles.MANAGE_AUTHORIZATION, AdminRoles.VIEW_AUTHORIZATION);
+ }
+ public boolean canManageEventsDefault() {
+ return root.hasOneAdminRole(AdminRoles.MANAGE_EVENTS);
+ }
+ public boolean canViewEventsDefault() {
+ return root.hasOneAdminRole(AdminRoles.MANAGE_EVENTS, AdminRoles.VIEW_EVENTS);
+ }
+
+ @Override
+ public boolean canListRealm() {
+ return root.hasAnyAdminRole();
+ }
+
+ @Override
+ public void requireViewRealmNameList() {
+ if (!canListRealm()) {
+ throw new ForbiddenException();
+ }
+ }
+
+ @Override
+ public boolean canManageRealm() {
+ return canManageRealmDefault();
+ }
+
+ @Override
+ public void requireManageRealm() {
+ if (!canManageRealm()) {
+ throw new ForbiddenException();
+ }
+ }
+ @Override
+ public boolean canViewRealm() {
+ return canViewRealmDefault();
+ }
+
+ @Override
+ public void requireViewRealm() {
+ if (!canViewRealm()) {
+ throw new ForbiddenException();
+ }
+ }
+
+ @Override
+ public boolean canManageIdentityProviders() {
+ return canManageIdentityProvidersDefault();
+ }
+
+ @Override
+ public boolean canViewIdentityProviders() {
+ return canViewIdentityProvidersDefault();
+ }
+
+ @Override
+ public void requireViewIdentityProviders() {
+ if (!canViewIdentityProviders()) {
+ throw new ForbiddenException();
+ }
+ }
+
+
+ @Override
+ public void requireManageIdentityProviders() {
+ if (!canManageIdentityProviders()) {
+ throw new ForbiddenException();
+ }
+ }
+
+
+ @Override
+ public boolean canManageAuthorization() {
+ return canManageAuthorizationDefault();
+ }
+
+ @Override
+ public boolean canViewAuthorization() {
+ return canViewAuthorizationDefault();
+ }
+
+ @Override
+ public void requireManageAuthorization() {
+ if (!canManageEvents()) {
+ throw new ForbiddenException();
+ }
+ }
+ @Override
+ public void requireViewAuthorization() {
+ if (!canManageEvents()) {
+ throw new ForbiddenException();
+ }
+ }
+
+ @Override
+ public boolean canManageEvents() {
+ return canManageEventsDefault();
+ }
+
+ @Override
+ public void requireManageEvents() {
+ if (!canManageEvents()) {
+ throw new ForbiddenException();
+ }
+ }
+ @Override
+ public boolean canViewEvents() {
+ return canViewEventsDefault();
+ }
+
+ @Override
+ public void requireViewEvents() {
+ if (!canViewEvents()) {
+ throw new ForbiddenException();
+ }
+ }
+
+
+
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissionEvaluator.java
new file mode 100644
index 0000000..3a87cb3
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissionEvaluator.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.keycloak.models.RoleContainerModel;
+import org.keycloak.models.RoleModel;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface RolePermissionEvaluator {
+ boolean canList(RoleContainerModel container);
+
+ void requireList(RoleContainerModel container);
+
+ boolean canMapRole(RoleModel role);
+ void requireMapRole(RoleModel role);
+
+ boolean canManage(RoleModel role);
+
+ void requireManage(RoleModel role);
+
+ boolean canView(RoleModel role);
+
+ void requireView(RoleModel role);
+
+ boolean canMapClientScope(RoleModel role);
+ void requireMapClientScope(RoleModel role);
+
+ boolean canMapComposite(RoleModel role);
+ void requireMapComposite(RoleModel role);
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissionManagement.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissionManagement.java
new file mode 100644
index 0000000..977e109
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissionManagement.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.Resource;
+import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.models.RoleContainerModel;
+import org.keycloak.models.RoleModel;
+
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface RolePermissionManagement {
+ public static final String MAP_ROLE_SCOPE = "map-role";
+ public static final String MAP_ROLE_CLIENT_SCOPE_SCOPE = "map-role-client-scope";
+ public static final String MAP_ROLE_COMPOSITE_SCOPE = "map-role-composite";
+
+ boolean isPermissionsEnabled(RoleModel role);
+ void setPermissionsEnabled(RoleModel role, boolean enable);
+
+ Map<String, String> getPermissions(RoleModel role);
+
+ Policy mapRolePermission(RoleModel role);
+
+ Policy mapCompositePermission(RoleModel role);
+
+ Policy mapClientScopePermission(RoleModel role);
+
+ Resource resource(RoleModel role);
+
+ ResourceServer resourceServer(RoleModel role);
+
+ Policy manageUsersPolicy(ResourceServer server);
+
+ Policy viewUsersPolicy(ResourceServer server);
+
+ Policy rolePolicy(ResourceServer server, RoleModel role);
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissions.java
new file mode 100644
index 0000000..d2531ec
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissions.java
@@ -0,0 +1,378 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.jboss.logging.Logger;
+import org.keycloak.authorization.AuthorizationProvider;
+import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.Resource;
+import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.authorization.model.Scope;
+import org.keycloak.authorization.store.ResourceStore;
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleContainerModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.services.ForbiddenException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+class RolePermissions implements RolePermissionEvaluator, RolePermissionManagement {
+ private static final Logger logger = Logger.getLogger(RolePermissions.class);
+ protected final KeycloakSession session;
+ protected final RealmModel realm;
+ protected final AuthorizationProvider authz;
+ protected final MgmtPermissions root;
+
+ public RolePermissions(KeycloakSession session, RealmModel realm, AuthorizationProvider authz, MgmtPermissions root) {
+ this.session = session;
+ this.realm = realm;
+ this.authz = authz;
+ this.root = root;
+ }
+
+ @Override
+ public boolean isPermissionsEnabled(RoleModel role) {
+ return mapRolePermission(role) != null;
+ }
+
+ @Override
+ public void setPermissionsEnabled(RoleModel role, boolean enable) {
+ if (enable) {
+ ResourceServer server = getResourceServer(role);
+ if (authz.getStoreFactory().getResourceStore().findByName(getRoleResourceName(role), server.getId()) != null) {
+ return;
+ }
+ createResource(role);
+ } else {
+ ResourceServer server = resourceServer(role);
+ if (server == null) return;
+ Resource resource = authz.getStoreFactory().getResourceStore().findByName(getRoleResourceName(role), server.getId());
+ if (resource != null) authz.getStoreFactory().getResourceStore().delete(resource.getId());
+ Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRolePermissionName(role), server.getId());
+ if (policy != null) authz.getStoreFactory().getPolicyStore().delete(policy.getId());
+ }
+ }
+
+ @Override
+ public Map<String, String> getPermissions(RoleModel role) {
+ Map<String, String> scopes = new HashMap<>();
+ scopes.put(RolePermissionManagement.MAP_ROLE_SCOPE, mapRolePermission(role).getId());
+ scopes.put(RolePermissionManagement.MAP_ROLE_CLIENT_SCOPE_SCOPE, mapClientScopePermission(role).getId());
+ scopes.put(RolePermissionManagement.MAP_ROLE_COMPOSITE_SCOPE, mapCompositePermission(role).getId());
+ return scopes;
+ }
+
+ @Override
+ public Policy mapRolePermission(RoleModel role) {
+ ResourceServer server = resourceServer(role);
+ if (server == null) return null;
+
+ Resource resource = authz.getStoreFactory().getResourceStore().findByName(getRoleResourceName(role), server.getId());
+ if (resource == null) return null;
+
+ return authz.getStoreFactory().getPolicyStore().findByName(getMapRolePermissionName(role), server.getId());
+ }
+
+ @Override
+ public Policy mapCompositePermission(RoleModel role) {
+ ResourceServer server = resourceServer(role);
+ if (server == null) return null;
+
+ Resource resource = authz.getStoreFactory().getResourceStore().findByName(getRoleResourceName(role), server.getId());
+ if (resource == null) return null;
+
+ return authz.getStoreFactory().getPolicyStore().findByName(getMapCompositePermissionName(role), server.getId());
+ }
+
+ @Override
+ public Policy mapClientScopePermission(RoleModel role) {
+ ResourceServer server = resourceServer(role);
+ if (server == null) return null;
+
+ Resource resource = authz.getStoreFactory().getResourceStore().findByName(getRoleResourceName(role), server.getId());
+ if (resource == null) return null;
+
+ return authz.getStoreFactory().getPolicyStore().findByName(getMapClientScopePermissionName(role), server.getId());
+ }
+
+ @Override
+ public Resource resource(RoleModel role) {
+ ResourceStore resourceStore = authz.getStoreFactory().getResourceStore();
+ ResourceServer server = resourceServer(role);
+ if (server == null) return null;
+ return resourceStore.findByName(getRoleResourceName(role), server.getId());
+ }
+
+ @Override
+ public ResourceServer resourceServer(RoleModel role) {
+ ClientModel client = getRoleClient(role);
+ return authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
+ }
+
+ /**
+ * Is admin allowed to map this role?
+ *
+ * @param role
+ * @return
+ */
+ @Override
+ public boolean canMapRole(RoleModel role) {
+ if (!root.isAdminSameRealm()) {
+ return root.users().canManage();
+ }
+ if (!isPermissionsEnabled(role)){
+ return root.users().canManage();
+ }
+
+ ResourceServer resourceServer = getResourceServer(role);
+ Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRolePermissionName(role), resourceServer.getId());
+ if (policy.getAssociatedPolicies().isEmpty()) {
+ return root.users().canManage(); // if no policies applied, just do default
+ }
+
+ Resource roleResource = resource(role);
+ Scope mapRoleScope = getMapRoleScope(resourceServer);
+ return root.evaluatePermission(roleResource, mapRoleScope, resourceServer);
+ }
+
+ @Override
+ public void requireMapRole(RoleModel role) {
+ if (!canMapRole(role)) {
+ throw new ForbiddenException();
+ }
+
+ }
+
+ @Override
+ public boolean canList(RoleContainerModel container) {
+ return root.hasAnyAdminRole();
+ }
+
+ @Override
+ public void requireList(RoleContainerModel container) {
+ if (!canList(container)) {
+ throw new ForbiddenException();
+ }
+
+ }
+
+ @Override
+ public boolean canMapComposite(RoleModel role) {
+ if (!root.isAdminSameRealm()) {
+ return canManage(role);
+ }
+ if (!isPermissionsEnabled(role)){
+ return canManage(role);
+ }
+
+ ResourceServer resourceServer = getResourceServer(role);
+ Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapCompositePermissionName(role), resourceServer.getId());
+ if (policy.getAssociatedPolicies().isEmpty()) {
+ return canManage(role);
+ }
+
+ Resource roleResource = resource(role);
+ Scope scope = getMapCompositeScope(resourceServer);
+ return root.evaluatePermission(roleResource, scope, resourceServer);
+ }
+
+ @Override
+ public void requireMapComposite(RoleModel role) {
+ if (!canMapComposite(role)) {
+ throw new ForbiddenException();
+ }
+
+ }
+
+
+ @Override
+ public boolean canMapClientScope(RoleModel role) {
+ if (!root.isAdminSameRealm()) {
+ return root.clients().canManage();
+ }
+ if (!isPermissionsEnabled(role)){
+ return root.clients().canManage();
+ }
+
+ ResourceServer resourceServer = getResourceServer(role);
+ Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapClientScopePermissionName(role), resourceServer.getId());
+ if (policy.getAssociatedPolicies().isEmpty()) {
+ return root.clients().canManage();
+ }
+
+ Resource roleResource = resource(role);
+ Scope scope = getMapClientScope(resourceServer);
+ return root.evaluatePermission(roleResource, scope, resourceServer);
+ }
+
+ @Override
+ public void requireMapClientScope(RoleModel role) {
+ if (!canMapClientScope(role)) {
+ throw new ForbiddenException();
+ }
+ }
+
+
+ @Override
+ public boolean canManage(RoleModel role) {
+ if (role.getContainer() instanceof RealmModel) {
+ return root.realm().canManageRealm();
+ } else if (role.getContainer() instanceof ClientModel) {
+ ClientModel client = (ClientModel)role.getContainer();
+ return root.clients().canManage(client);
+ }
+ return false;
+ }
+
+ @Override
+ public void requireManage(RoleModel role) {
+ if (!canManage(role)) {
+ throw new ForbiddenException();
+ }
+
+ }
+
+ @Override
+ public boolean canView(RoleModel role) {
+ if (role.getContainer() instanceof RealmModel) {
+ return root.realm().canViewRealm();
+ } else if (role.getContainer() instanceof ClientModel) {
+ ClientModel client = (ClientModel)role.getContainer();
+ return root.clients().canView(client);
+ }
+ return false;
+ }
+
+ @Override
+ public void requireView(RoleModel role) {
+ if (!canView(role)) {
+ throw new ForbiddenException();
+ }
+
+ }
+
+ private ClientModel getRoleClient(RoleModel role) {
+ ClientModel client = null;
+ if (role.getContainer() instanceof ClientModel) {
+ client = (ClientModel)role.getContainer();
+ } else {
+ client = root.getRealmManagementClient();
+ }
+ return client;
+ }
+
+ @Override
+ public Policy manageUsersPolicy(ResourceServer server) {
+ RoleModel role = root.getRealmManagementClient().getRole(AdminRoles.MANAGE_USERS);
+ return rolePolicy(server, role);
+ }
+
+ @Override
+ public Policy viewUsersPolicy(ResourceServer server) {
+ RoleModel role = root.getRealmManagementClient().getRole(AdminRoles.VIEW_USERS);
+ return rolePolicy(server, role);
+ }
+
+ @Override
+ public Policy rolePolicy(ResourceServer server, RoleModel role) {
+ String policyName = Helper.getRolePolicyName(role);
+ Policy policy = authz.getStoreFactory().getPolicyStore().findByName(policyName, server.getId());
+ if (policy != null) return policy;
+ return Helper.createRolePolicy(authz, server, role, policyName);
+ }
+
+ private Scope getMapRoleScope(ResourceServer server) {
+ Scope scope = authz.getStoreFactory().getScopeStore().findByName(MAP_ROLE_SCOPE, server.getId());
+ if (scope == null) {
+ scope = authz.getStoreFactory().getScopeStore().create(MAP_ROLE_SCOPE, server);
+ }
+ return scope;
+ }
+
+ private Scope getMapClientScope(ResourceServer server) {
+ Scope scope = authz.getStoreFactory().getScopeStore().findByName(MAP_ROLE_CLIENT_SCOPE_SCOPE, server.getId());
+ if (scope == null) {
+ scope = authz.getStoreFactory().getScopeStore().create(MAP_ROLE_CLIENT_SCOPE_SCOPE, server);
+ }
+ return scope;
+ }
+
+ private Scope getMapCompositeScope(ResourceServer server) {
+ Scope scope = authz.getStoreFactory().getScopeStore().findByName(MAP_ROLE_COMPOSITE_SCOPE, server.getId());
+ if (scope == null) {
+ scope = authz.getStoreFactory().getScopeStore().create(MAP_ROLE_COMPOSITE_SCOPE, server);
+ }
+ return scope;
+ }
+
+
+ private Resource createResource(RoleModel role) {
+ ResourceServer server = getResourceServer(role);
+ Resource resource = authz.getStoreFactory().getResourceStore().create(getRoleResourceName(role), server, server.getClientId());
+ resource.setType("Role");
+ Scope mapRoleScope = getMapRoleScope(server);
+ Policy policy = manageUsersPolicy(server);
+ Helper.addScopePermission(authz, server, getMapRolePermissionName(role), resource, mapRoleScope, policy);
+
+ Scope mapClientScope = getMapClientScope(server);
+ RoleModel mngClients = root.getRealmManagementClient().getRole(AdminRoles.MANAGE_CLIENTS);
+ Policy mngClientsPolicy = rolePolicy(server, mngClients);
+ Helper.addScopePermission(authz, server, getMapClientScopePermissionName(role), resource, mapClientScope, mngClientsPolicy);
+
+ Scope mapCompositeScope = getMapCompositeScope(server);
+ if (role.getContainer() instanceof RealmModel) {
+ RoleModel mngRealm = root.getRealmManagementClient().getRole(AdminRoles.MANAGE_REALM);
+ policy = rolePolicy(server, mngRealm);
+ } else {
+ policy = mngClientsPolicy;
+
+ }
+ Helper.addScopePermission(authz, server, getMapCompositePermissionName(role), resource, mapCompositeScope, policy);
+ return resource;
+ }
+
+ private String getMapRolePermissionName(RoleModel role) {
+ return MAP_ROLE_SCOPE + ".permission." + role.getName();
+ }
+
+ private String getMapClientScopePermissionName(RoleModel role) {
+ return MAP_ROLE_CLIENT_SCOPE_SCOPE + ".permission." + role.getName();
+ }
+
+ private String getMapCompositePermissionName(RoleModel role) {
+ return MAP_ROLE_CLIENT_SCOPE_SCOPE + ".permission." + role.getName();
+ }
+
+ private ResourceServer getResourceServer(RoleModel role) {
+ ClientModel client = getRoleClient(role);
+ return root.findOrCreateResourceServer(client);
+ }
+
+ private static String getRoleResourceName(RoleModel role) {
+ return "role.resource." + role.getName();
+ }
+
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java
new file mode 100644
index 0000000..488825b
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.keycloak.models.UserModel;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface UserPermissionEvaluator {
+ boolean canManage();
+
+ void requireManage();
+
+ boolean canManage(UserModel user);
+ void requireManage(UserModel user);
+
+ boolean canQuery();
+
+ void requireQuery();
+
+ boolean canView();
+ boolean canView(UserModel user);
+ void requireView(UserModel user);
+
+ void requireView();
+
+ boolean canImpersonate(UserModel user);
+
+ void requireImpersonate(UserModel user);
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionManagement.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionManagement.java
new file mode 100644
index 0000000..b57b710
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionManagement.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.Resource;
+import org.keycloak.models.RoleModel;
+
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface UserPermissionManagement {
+ boolean isPermissionsEnabled();
+
+ void setPermissionsEnabled(boolean enable);
+
+ Map<String, String> getPermissions();
+
+ Resource resource();
+
+ Policy managePermission();
+
+ Policy viewPermission();
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java
new file mode 100644
index 0000000..a0a7281
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java
@@ -0,0 +1,382 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.services.resources.admin.permissions;
+
+import org.jboss.logging.Logger;
+import org.keycloak.authorization.AuthorizationProvider;
+import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.Resource;
+import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.authorization.model.Scope;
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.GroupModel;
+import org.keycloak.models.ImpersonationConstants;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.services.ForbiddenException;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Manages default policies for all users.
+ *
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+class UserPermissions implements UserPermissionEvaluator, UserPermissionManagement {
+ private static final Logger logger = Logger.getLogger(UserPermissions.class);
+ public static final String MANAGE_PERMISSION_USERS = "manage.permission.users";
+ public static final String VIEW_PERMISSION_USERS = "view.permission.users";
+ public static final String USERS_RESOURCE = "Users";
+ protected final KeycloakSession session;
+ protected final RealmModel realm;
+ protected final AuthorizationProvider authz;
+ protected final MgmtPermissions root;
+
+ public UserPermissions(KeycloakSession session, RealmModel realm, AuthorizationProvider authz, MgmtPermissions root) {
+ this.session = session;
+ this.realm = realm;
+ this.authz = authz;
+ this.root = root;
+ }
+
+
+ private void initialize() {
+ root.initializeRealmResourceServer();
+ root.initializeRealmDefaultScopes();
+ ResourceServer server = root.realmResourceServer();
+ Scope manageScope = root.realmManageScope();
+ Scope viewScope = root.realmViewScope();
+
+ Resource usersResource = authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId());
+ if (usersResource == null) {
+ usersResource = authz.getStoreFactory().getResourceStore().create(USERS_RESOURCE, server, server.getClientId());
+ Set<Scope> scopeset = new HashSet<>();
+ scopeset.add(manageScope);
+ scopeset.add(viewScope);
+ usersResource.updateScopes(scopeset);
+ }
+ Policy managePermission = authz.getStoreFactory().getPolicyStore().findByName(MANAGE_PERMISSION_USERS, server.getId());
+ if (managePermission == null) {
+ Policy manageUsersPolicy = root.roles().manageUsersPolicy(server);
+ Helper.addScopePermission(authz, server, MANAGE_PERMISSION_USERS, usersResource, manageScope, manageUsersPolicy);
+ }
+ Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(VIEW_PERMISSION_USERS, server.getId());
+ if (viewPermission == null) {
+ Policy viewUsersPolicy = root.roles().viewUsersPolicy(server);
+ Helper.addScopePermission(authz, server, VIEW_PERMISSION_USERS, usersResource, viewScope, viewUsersPolicy);
+ }
+ }
+
+ @Override
+ public Map<String, String> getPermissions() {
+ Map<String, String> scopes = new HashMap<>();
+ scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermission().getId());
+ scopes.put(AdminPermissionManagement.VIEW_SCOPE, viewPermission().getId());
+ return scopes;
+ }
+
+ @Override
+ public boolean isPermissionsEnabled() {
+ ResourceServer server = root.realmResourceServer();
+ if (server == null) return false;
+
+ Resource resource = authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId());
+ if (resource == null) return false;
+
+ Policy policy = authz.getStoreFactory().getPolicyStore().findByName(MANAGE_PERMISSION_USERS, server.getId());
+
+ return policy != null;
+ }
+
+ @Override
+ public void setPermissionsEnabled(boolean enable) {
+ ClientModel client = root.getRealmManagementClient();
+ if (enable) {
+ initialize();
+ } else {
+ ResourceServer server = authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
+ if (server == null) return;
+ Policy policy = authz.getStoreFactory().getPolicyStore().findByName(MANAGE_PERMISSION_USERS, server.getId());
+ if (policy == null) {
+ authz.getStoreFactory().getPolicyStore().delete(policy.getId());
+
+ }
+ Resource usersResource = authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId());
+ if (usersResource == null) {
+ authz.getStoreFactory().getResourceStore().delete(usersResource.getId());
+ }
+ }
+ }
+
+ public boolean canManageDefault() {
+ return root.hasOneAdminRole(AdminRoles.MANAGE_USERS);
+ }
+
+ @Override
+ public Resource resource() {
+ ResourceServer server = root.realmResourceServer();
+ if (server == null) return null;
+
+ return authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId());
+ }
+
+ @Override
+ public Policy managePermission() {
+ ResourceServer server = root.realmResourceServer();
+ return authz.getStoreFactory().getPolicyStore().findByName(MANAGE_PERMISSION_USERS, server.getId());
+ }
+
+ @Override
+ public Policy viewPermission() {
+ ResourceServer server = root.realmResourceServer();
+ return authz.getStoreFactory().getPolicyStore().findByName(VIEW_PERMISSION_USERS, server.getId());
+ }
+
+
+
+ /**
+ * Is admin allowed to manage all users? In Authz terms, does the admin have the "manage" scope for the Users Authz resource?
+ *
+ * This method will follow the old default behavior (does the admin have the manage-users role) if any of these conditions
+ * are met.:
+ * - The admin is from the master realm managing a different realm
+ * - If the Authz objects are not set up correctly for the Users resource in Authz
+ * - The "manage" permission for the Users resource has an empty associatedPolicy list.
+ *
+ * Otherwise, it will use the Authz policy engine to resolve this answer.
+ *
+ * @return
+ */
+ @Override
+ public boolean canManage() {
+ if (!root.isAdminSameRealm()) {
+ return canManageDefault();
+ }
+
+ ResourceServer server = root.realmResourceServer();
+ if (server == null) return canManageDefault();
+
+ Resource resource = authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId());
+ if (resource == null) return canManageDefault();
+
+ Policy policy = authz.getStoreFactory().getPolicyStore().findByName(MANAGE_PERMISSION_USERS, server.getId());
+ if (policy == null) {
+ return canManageDefault();
+ }
+
+ Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
+ // if no policies attached to permission then just do default behavior
+ if (associatedPolicies == null || associatedPolicies.isEmpty()) {
+ return canManageDefault();
+ }
+
+ Scope scope = root.realmManageScope();
+ return root.evaluatePermission(resource, scope, server);
+
+ }
+
+ @Override
+ public void requireManage() {
+ if (!canManage()) {
+ throw new ForbiddenException();
+ }
+ }
+
+
+ /**
+ * Does current admin have manage permissions for this particular user?
+ *
+ * @param user
+ * @return
+ */
+ @Override
+ public boolean canManage(UserModel user) {
+ return canManage() || canManageByGroup(user);
+ }
+
+ @Override
+ public void requireManage(UserModel user) {
+ if (!canManage(user)) {
+ throw new ForbiddenException();
+ }
+ }
+
+ private interface EvaluateGroup {
+ boolean evaluate(GroupModel group);
+ }
+
+ private boolean evaluateGroups(UserModel user, EvaluateGroup eval) {
+ for (GroupModel group : user.getGroups()) {
+ if (eval.evaluate(group)) return true;
+ }
+ return false;
+ }
+
+ private boolean evaluateHierarchy(UserModel user, EvaluateGroup eval) {
+ Set<GroupModel> visited = new HashSet<>();
+ for (GroupModel group : user.getGroups()) {
+ if (evaluateHierarchy(eval, group, visited)) return true;
+ }
+ return false;
+ }
+
+ private boolean evaluateHierarchy(EvaluateGroup eval, GroupModel group, Set<GroupModel> visited) {
+ if (visited.contains(group)) return false;
+ if (eval.evaluate(group)) {
+ return true;
+ }
+ visited.add(group);
+ if (group.getParent() == null) return false;
+ return evaluateHierarchy(eval, group.getParent(), visited);
+ }
+
+ private boolean canManageByGroup(UserModel user) {
+ /* no inheritance
+ return evaluateGroups(user,
+ (group) -> root.groups().canViewMembers(group)
+ );
+ */
+
+ /* inheritance
+ */
+ return evaluateHierarchy(user, (group) -> root.groups().canManageMembers(group));
+
+ }
+ private boolean canViewByGroup(UserModel user) {
+ /* no inheritance
+ return evaluateGroups(user,
+ (group) -> root.groups().canViewMembers(group)
+ );
+ */
+
+ /* inheritance
+ */
+ return evaluateHierarchy(user, (group) -> root.groups().canViewMembers(group));
+ }
+
+ public boolean canViewDefault() {
+ return root.hasOneAdminRole(AdminRoles.MANAGE_USERS, AdminRoles.VIEW_USERS);
+ }
+
+ @Override
+ public boolean canQuery() {
+ return canViewDefault();
+ }
+
+ @Override
+ public void requireQuery() {
+ if (!canQuery()) {
+ throw new ForbiddenException();
+ }
+ }
+
+
+
+ /**
+ * Is admin allowed to view all users? In Authz terms, does the admin have the "view" scope for the Users Authz resource?
+ *
+ * This method will follow the old default behavior (does the admin have the view-users role) if any of these conditions
+ * are met.:
+ * - The admin is from the master realm managing a different realm
+ * - If the Authz objects are not set up correctly for the Users resource in Authz
+ * - The "view" permission for the Users resource has an empty associatedPolicy list.
+ *
+ * Otherwise, it will use the Authz policy engine to resolve this answer.
+ *
+ * @return
+ */
+ @Override
+ public boolean canView() {
+ if (!root.isAdminSameRealm()) {
+ return canViewDefault();
+ }
+
+ ResourceServer server = root.realmResourceServer();
+ if (server == null) return canViewDefault();
+
+ Resource resource = authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId());
+ if (resource == null) return canViewDefault();
+
+ Policy policy = authz.getStoreFactory().getPolicyStore().findByName(VIEW_PERMISSION_USERS, server.getId());
+ if (policy == null) {
+ return canViewDefault();
+ }
+
+ Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
+ // if no policies attached to permission then just do default behavior
+ if (associatedPolicies == null || associatedPolicies.isEmpty()) {
+ return canViewDefault();
+ }
+
+ Scope scope = root.realmViewScope();
+ return root.evaluatePermission(resource, scope, server);
+ }
+
+ /**
+ * Does current admin have view permissions for this particular user?
+ *
+ * Evaluates in this order. If any true, return true:
+ * - canViewUsers
+ * - canManageUsers
+ *
+ *
+ * @param user
+ * @return
+ */
+ @Override
+ public boolean canView(UserModel user) {
+ return canView() || canManage() || canViewByGroup(user) || canManageByGroup(user);
+ }
+
+ @Override
+ public void requireView(UserModel user) {
+ if (!canView(user)) {
+ throw new ForbiddenException();
+ }
+ }
+
+ @Override
+ public void requireView() {
+ if (!(canView() || canManage())) {
+ throw new ForbiddenException();
+ }
+ }
+
+ @Override
+ public boolean canImpersonate(UserModel user) {
+ return root.hasOneAdminRole(ImpersonationConstants.IMPERSONATION_ROLE);
+ }
+
+ @Override
+ public void requireImpersonate(UserModel user) {
+ if (!canImpersonate(user)) {
+ throw new ForbiddenException();
+ }
+ }
+
+
+
+
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
index ad473b9..3aac331 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
@@ -33,7 +33,7 @@ import org.keycloak.protocol.ProtocolMapperConfigException;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.services.ErrorResponse;
import org.keycloak.services.ErrorResponseException;
-import org.keycloak.services.resources.admin.RealmAuth.Resource;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@@ -66,7 +66,9 @@ public class ProtocolMappersResource {
protected ProtocolMapperContainerModel client;
- protected RealmAuth auth;
+ protected AdminPermissionEvaluator auth;
+ protected AdminPermissionEvaluator.RequirePermissionCheck managePermission;
+ protected AdminPermissionEvaluator.RequirePermissionCheck viewPermission;
protected AdminEventBuilder adminEvent;
@@ -76,13 +78,17 @@ public class ProtocolMappersResource {
@Context
protected KeycloakSession session;
- public ProtocolMappersResource(RealmModel realm, ProtocolMapperContainerModel client, RealmAuth auth, AdminEventBuilder adminEvent) {
+ public ProtocolMappersResource(RealmModel realm, ProtocolMapperContainerModel client, AdminPermissionEvaluator auth,
+ AdminEventBuilder adminEvent,
+ AdminPermissionEvaluator.RequirePermissionCheck managePermission,
+ AdminPermissionEvaluator.RequirePermissionCheck viewPermission) {
this.realm = realm;
this.auth = auth;
this.client = client;
this.adminEvent = adminEvent.resource(ResourceType.PROTOCOL_MAPPER);
+ this.managePermission = managePermission;
+ this.viewPermission = viewPermission;
- auth.init(Resource.CLIENT);
}
/**
@@ -96,11 +102,7 @@ public class ProtocolMappersResource {
@Path("protocol/{protocol}")
@Produces(MediaType.APPLICATION_JSON)
public List<ProtocolMapperRepresentation> getMappersPerProtocol(@PathParam("protocol") String protocol) {
- auth.requireAny();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ viewPermission.require();
List<ProtocolMapperRepresentation> mappers = new LinkedList<ProtocolMapperRepresentation>();
for (ProtocolMapperModel mapper : client.getProtocolMappers()) {
@@ -119,11 +121,7 @@ public class ProtocolMappersResource {
@NoCache
@Consumes(MediaType.APPLICATION_JSON)
public Response createMapper(ProtocolMapperRepresentation rep) {
- auth.requireManage();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ managePermission.require();
ProtocolMapperModel model = null;
try {
@@ -147,11 +145,7 @@ public class ProtocolMappersResource {
@NoCache
@Consumes(MediaType.APPLICATION_JSON)
public void createMapper(List<ProtocolMapperRepresentation> reps) {
- auth.requireManage();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ managePermission.require();
ProtocolMapperModel model = null;
for (ProtocolMapperRepresentation rep : reps) {
@@ -172,11 +166,7 @@ public class ProtocolMappersResource {
@Path("models")
@Produces(MediaType.APPLICATION_JSON)
public List<ProtocolMapperRepresentation> getMappers() {
- auth.requireAny();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ viewPermission.require();
List<ProtocolMapperRepresentation> mappers = new LinkedList<ProtocolMapperRepresentation>();
for (ProtocolMapperModel mapper : client.getProtocolMappers()) {
@@ -196,11 +186,7 @@ public class ProtocolMappersResource {
@Path("models/{id}")
@Produces(MediaType.APPLICATION_JSON)
public ProtocolMapperRepresentation getMapperById(@PathParam("id") String id) {
- auth.requireAny();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ viewPermission.require();
ProtocolMapperModel model = client.getProtocolMapperById(id);
if (model == null) throw new NotFoundException("Model not found");
@@ -218,11 +204,7 @@ public class ProtocolMappersResource {
@Path("models/{id}")
@Consumes(MediaType.APPLICATION_JSON)
public void update(@PathParam("id") String id, ProtocolMapperRepresentation rep) {
- auth.requireManage();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ managePermission.require();
ProtocolMapperModel model = client.getProtocolMapperById(id);
if (model == null) throw new NotFoundException("Model not found");
@@ -243,11 +225,7 @@ public class ProtocolMappersResource {
@NoCache
@Path("models/{id}")
public void delete(@PathParam("id") String id) {
- auth.requireManage();
-
- if (client == null) {
- throw new NotFoundException("Could not find client");
- }
+ managePermission.require();
ProtocolMapperModel model = client.getProtocolMapperById(id);
if (model == null) throw new NotFoundException("Model not found");
@@ -264,7 +242,7 @@ public class ProtocolMappersResource {
}
} catch (ProtocolMapperConfigException ex) {
logger.error(ex.getMessage());
- Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
+ Properties messages = AdminRoot.getMessages(session, realm, auth.adminAuth().getToken().getLocale());
throw new ErrorResponseException(ex.getMessage(), MessageFormat.format(messages.getProperty(ex.getMessageKey(), ex.getMessage()), ex.getParameters()),
Response.Status.BAD_REQUEST);
}
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 510a605..0a84001 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -23,9 +23,9 @@ import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.Config;
import org.keycloak.KeyPairVerifier;
-import org.keycloak.authorization.admin.permissions.MgmtPermissions;
-import org.keycloak.authorization.admin.permissions.RoleMgmtPermissions;
-import org.keycloak.authorization.admin.permissions.UsersPermissions;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionManagement;
+import org.keycloak.services.resources.admin.permissions.AdminPermissions;
import org.keycloak.common.ClientConnection;
import org.keycloak.common.VerificationException;
import org.keycloak.common.util.PemUtils;
@@ -48,7 +48,6 @@ import org.keycloak.models.LDAPConstants;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.ModelException;
import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.cache.CacheRealmProvider;
import org.keycloak.models.cache.UserCache;
@@ -63,7 +62,6 @@ import org.keycloak.representations.adapters.action.GlobalRequestResult;
import org.keycloak.representations.idm.AdminEventRepresentation;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ComponentRepresentation;
-import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.EventRepresentation;
import org.keycloak.representations.idm.GroupRepresentation;
import org.keycloak.representations.idm.ManagementPermissionReference;
@@ -76,7 +74,6 @@ import org.keycloak.services.managers.LDAPConnectionTestManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.ResourceAdminManager;
import org.keycloak.services.managers.UserStorageSyncManager;
-import org.keycloak.services.resources.admin.RealmAuth.Resource;
import org.keycloak.storage.UserStorageProviderModel;
import javax.ws.rs.Consumes;
@@ -114,7 +111,7 @@ import java.util.regex.PatternSyntaxException;
*/
public class RealmAdminResource {
protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
- protected RealmAuth auth;
+ protected AdminPermissionEvaluator auth;
protected RealmModel realm;
private TokenManager tokenManager;
private AdminEventBuilder adminEvent;
@@ -131,13 +128,11 @@ public class RealmAdminResource {
@Context
protected HttpHeaders headers;
- public RealmAdminResource(RealmAuth auth, RealmModel realm, TokenManager tokenManager, AdminEventBuilder adminEvent) {
+ public RealmAdminResource(AdminPermissionEvaluator auth, RealmModel realm, TokenManager tokenManager, AdminEventBuilder adminEvent) {
this.auth = auth;
this.realm = realm;
this.tokenManager = tokenManager;
this.adminEvent = adminEvent.realm(realm).resource(ResourceType.REALM);
-
- auth.init(RealmAuth.Resource.REALM);
}
/**
@@ -150,7 +145,7 @@ public class RealmAdminResource {
@POST
@Produces(MediaType.APPLICATION_JSON)
public ClientRepresentation convertClientDescription(String description) {
- auth.init(Resource.CLIENT).requireManage();
+ auth.clients().requireManage();
if (realm == null) {
throw new NotFoundException("Realm not found.");
@@ -239,7 +234,9 @@ public class RealmAdminResource {
*/
@Path("roles")
public RoleContainerResource getRoleContainerResource() {
- return new RoleContainerResource(session, uriInfo, realm, auth, realm, adminEvent);
+ AdminPermissionEvaluator.RequirePermissionCheck manageCheck = () -> auth.realm().requireManageRealm();
+ AdminPermissionEvaluator.RequirePermissionCheck viewCheck = () -> auth.realm().requireViewRealm();
+ return new RoleContainerResource(session, uriInfo, realm, auth, realm, adminEvent, manageCheck, viewCheck);
}
/**
@@ -253,15 +250,15 @@ public class RealmAdminResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public RealmRepresentation getRealm() {
- if (auth.hasView()) {
+ if (auth.realm().canViewRealm()) {
return ModelToRepresentation.toRepresentation(realm, false);
} else {
- auth.requireAny();
+ auth.realm().requireViewRealmNameList();
RealmRepresentation rep = new RealmRepresentation();
rep.setRealm(realm.getName());
- if (auth.init(Resource.IDENTITY_PROVIDER).hasView()) {
+ if (auth.realm().canViewIdentityProviders()) {
RealmRepresentation r = ModelToRepresentation.toRepresentation(realm, false);
rep.setIdentityProviders(r.getIdentityProviders());
rep.setIdentityProviderMappers(r.getIdentityProviderMappers());
@@ -283,7 +280,7 @@ public class RealmAdminResource {
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public Response updateRealm(final RealmRepresentation rep) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
logger.debug("updating realm: " + realm.getName());
@@ -347,7 +344,7 @@ public class RealmAdminResource {
*/
@DELETE
public void deleteRealm() {
- auth.requireManage();
+ auth.realm().requireManageRealm();
if (!new RealmManager(session).removeRealm(realm)) {
throw new NotFoundException("Realm doesn't exist");
@@ -372,9 +369,9 @@ public class RealmAdminResource {
@Produces(MediaType.APPLICATION_JSON)
@Path("users-management-permissions")
public ManagementPermissionReference getUserMgmtPermissions() {
- auth.requireView();
+ auth.realm().requireViewRealm();
- MgmtPermissions permissions = new MgmtPermissions(session, realm);
+ AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
if (permissions.users().isPermissionsEnabled()) {
return toUsersMgmtRef(permissions);
} else {
@@ -389,9 +386,9 @@ public class RealmAdminResource {
@NoCache
@Path("users-management-permissions")
public ManagementPermissionReference setUsersManagementPermissionsEnabled(ManagementPermissionReference ref) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
- MgmtPermissions permissions = new MgmtPermissions(session, realm);
+ AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
permissions.users().setPermissionsEnabled(ref.isEnabled());
if (ref.isEnabled()) {
return toUsersMgmtRef(permissions);
@@ -401,12 +398,11 @@ public class RealmAdminResource {
}
- public static ManagementPermissionReference toUsersMgmtRef(MgmtPermissions permissions) {
+ public static ManagementPermissionReference toUsersMgmtRef(AdminPermissionManagement permissions) {
ManagementPermissionReference ref = new ManagementPermissionReference();
ref.setEnabled(true);
ref.setResource(permissions.users().resource().getId());
- Map<String, String> scopes = new HashMap<>();
- scopes.put(MgmtPermissions.MANAGE_SCOPE, permissions.users().managePermission().getId());
+ Map<String, String> scopes = permissions.users().getPermissions();
ref.setScopePermissions(scopes);
return ref;
}
@@ -436,7 +432,7 @@ public class RealmAdminResource {
*/
@Path("roles-by-id")
public RoleByIdResource rolesById() {
- RoleByIdResource resource = new RoleByIdResource(realm, auth, adminEvent);
+ RoleByIdResource resource = new RoleByIdResource(realm, auth, adminEvent);
ResteasyProviderFactory.getInstance().injectProperties(resource);
//resourceContext.initResource(resource);
return resource;
@@ -449,7 +445,7 @@ public class RealmAdminResource {
@Path("push-revocation")
@POST
public GlobalRequestResult pushRevocation() {
- auth.requireManage();
+ auth.realm().requireManageRealm();
GlobalRequestResult result = new ResourceAdminManager(session).pushRealmRevocationPolicy(uriInfo.getRequestUri(), realm);
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).representation(result).success();
@@ -464,7 +460,7 @@ public class RealmAdminResource {
@Path("logout-all")
@POST
public GlobalRequestResult logoutAll() {
- auth.init(RealmAuth.Resource.USER).requireManage();
+ auth.users().requireManage();
session.sessions().removeUserSessions(realm);
GlobalRequestResult result = new ResourceAdminManager(session).logoutAll(uriInfo.getRequestUri(), realm);
@@ -481,7 +477,7 @@ public class RealmAdminResource {
@Path("sessions/{session}")
@DELETE
public void deleteSession(@PathParam("session") String sessionId) {
- auth.init(RealmAuth.Resource.USER).requireManage();
+ auth.users().requireManage();
UserSessionModel userSession = session.sessions().getUserSession(realm, sessionId);
if (userSession == null) throw new NotFoundException("Sesssion not found");
@@ -503,7 +499,7 @@ public class RealmAdminResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<Map<String, String>> getClientSessionStats() {
- auth.requireView();
+ auth.realm().requireViewRealm();
List<Map<String, String>> data = new LinkedList<Map<String, String>>();
for (ClientModel client : realm.getClients()) {
@@ -530,7 +526,7 @@ public class RealmAdminResource {
@Path("events/config")
@Produces(MediaType.APPLICATION_JSON)
public RealmEventsConfigRepresentation getRealmEventsConfig() {
- auth.init(RealmAuth.Resource.EVENTS).requireView();
+ auth.realm().requireViewEvents();
RealmEventsConfigRepresentation config = ModelToRepresentation.toEventsConfigReprensetation(realm);
if (config.getEnabledEventTypes() == null || config.getEnabledEventTypes().isEmpty()) {
@@ -555,7 +551,7 @@ public class RealmAdminResource {
@Path("events/config")
@Consumes(MediaType.APPLICATION_JSON)
public void updateRealmEventsConfig(final RealmEventsConfigRepresentation rep) {
- auth.init(RealmAuth.Resource.EVENTS).requireManage();
+ auth.realm().requireManageEvents();
logger.debug("updating realm events config: " + realm.getName());
new RealmManager(session).updateRealmEventsConfig(rep, realm);
@@ -584,7 +580,7 @@ public class RealmAdminResource {
@QueryParam("user") String user, @QueryParam("dateFrom") String dateFrom, @QueryParam("dateTo") String dateTo,
@QueryParam("ipAddress") String ipAddress, @QueryParam("first") Integer firstResult,
@QueryParam("max") Integer maxResults) {
- auth.init(RealmAuth.Resource.EVENTS).requireView();
+ auth.realm().requireViewEvents();
EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class);
@@ -677,7 +673,7 @@ public class RealmAdminResource {
@QueryParam("dateTo") String dateTo, @QueryParam("first") Integer firstResult,
@QueryParam("max") Integer maxResults,
@QueryParam("resourceTypes") List<String> resourceTypes) {
- auth.init(RealmAuth.Resource.EVENTS).requireView();
+ auth.realm().requireViewEvents();
EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class);
AdminEventQuery query = eventStore.createAdminQuery().realm(realm.getId());;
@@ -770,7 +766,7 @@ public class RealmAdminResource {
@Path("events")
@DELETE
public void clearEvents() {
- auth.init(RealmAuth.Resource.EVENTS).requireManage();
+ auth.realm().requireManageEvents();
EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class);
eventStore.clear(realm.getId());
@@ -783,7 +779,7 @@ public class RealmAdminResource {
@Path("admin-events")
@DELETE
public void clearAdminEvents() {
- auth.init(RealmAuth.Resource.EVENTS).requireManage();
+ auth.realm().requireManageEvents();
EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class);
eventStore.clearAdmin(realm.getId());
@@ -805,7 +801,7 @@ public class RealmAdminResource {
@QueryParam("bindDn") String bindDn, @QueryParam("bindCredential") String bindCredential,
@QueryParam("useTruststoreSpi") String useTruststoreSpi, @QueryParam("connectionTimeout") String connectionTimeout,
@QueryParam("componentId") String componentId) {
- auth.init(RealmAuth.Resource.REALM).requireManage();
+ auth.realm().requireManageRealm();
if (componentId != null && bindCredential.equals(ComponentRepresentation.SECRET_VALUE)) {
bindCredential = realm.getComponent(componentId).getConfig().getFirst(LDAPConstants.BIND_CREDENTIAL);
@@ -830,7 +826,7 @@ public class RealmAdminResource {
@Produces(MediaType.APPLICATION_JSON)
@Path("default-groups")
public List<GroupRepresentation> getDefaultGroups() {
- auth.requireView();
+ auth.realm().requireViewRealm();
List<GroupRepresentation> defaults = new LinkedList<>();
for (GroupModel group : realm.getDefaultGroups()) {
@@ -842,7 +838,7 @@ public class RealmAdminResource {
@NoCache
@Path("default-groups/{groupId}")
public void addDefaultGroup(@PathParam("groupId") String groupId) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
GroupModel group = realm.getGroupById(groupId);
if (group == null) {
@@ -857,7 +853,7 @@ public class RealmAdminResource {
@NoCache
@Path("default-groups/{groupId}")
public void removeDefaultGroup(@PathParam("groupId") String groupId) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
GroupModel group = realm.getGroupById(groupId);
if (group == null) {
@@ -882,13 +878,12 @@ public class RealmAdminResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public GroupRepresentation getGroupByPath(@PathParam("path") String path) {
- auth.requireView();
-
GroupModel found = KeycloakModelUtils.findGroupByPath(realm, path);
if (found == null) {
throw new NotFoundException("Group path does not exist");
}
+ auth.groups().requireView(found);
return ModelToRepresentation.toGroupHierarchy(found, true);
}
@@ -902,7 +897,7 @@ public class RealmAdminResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response partialImport(PartialImportRepresentation rep) {
- auth.requireManage();
+ auth.realm().requireManageRealm();
PartialImportManager partialImport = new PartialImportManager(rep, session, realm, adminEvent);
return partialImport.saveResources();
@@ -915,7 +910,7 @@ public class RealmAdminResource {
@Path("clear-realm-cache")
@POST
public void clearRealmCache() {
- auth.requireManage();
+ auth.realm().requireManageRealm();
CacheRealmProvider cache = session.getProvider(CacheRealmProvider.class);
if (cache != null) {
@@ -932,7 +927,7 @@ public class RealmAdminResource {
@Path("clear-user-cache")
@POST
public void clearUserCache() {
- auth.requireManage();
+ auth.realm().requireManageRealm();
UserCache cache = session.getProvider(UserCache.class);
if (cache != null) {
@@ -949,7 +944,7 @@ public class RealmAdminResource {
@Path("clear-keys-cache")
@POST
public void clearKeysCache() {
- auth.requireManage();
+ auth.realm().requireManageRealm();
PublicKeyStorageProvider cache = session.getProvider(PublicKeyStorageProvider.class);
if (cache != null) {
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 7a948d9..9e0a89e 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
@@ -34,6 +34,8 @@ import org.keycloak.services.ErrorResponse;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.KeycloakApplication;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
+import org.keycloak.services.resources.admin.permissions.AdminPermissions;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@@ -191,13 +193,7 @@ public class RealmsAdminResource {
&& !auth.getRealm().equals(realm)) {
throw new ForbiddenException();
}
- RealmAuth realmAuth;
-
- if (auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
- realmAuth = new RealmAuth(auth, realm.getMasterAdminClient());
- } else {
- realmAuth = new RealmAuth(auth, realm.getClientByClientId(realmManager.getRealmAdminClientId(auth.getRealm())));
- }
+ AdminPermissionEvaluator realmAuth = AdminPermissions.evaluator(session, realm, auth);
AdminEventBuilder adminEvent = new AdminEventBuilder(realm, auth, session, clientConnection);
session.getContext().setRealm(realm);
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 9d3e100..b2ae6ad 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
@@ -19,8 +19,10 @@ package org.keycloak.services.resources.admin;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.authorization.admin.permissions.MgmtPermissions;
-import org.keycloak.authorization.admin.permissions.RoleMgmtPermissions;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionManagement;
+import org.keycloak.services.resources.admin.permissions.AdminPermissions;
+import org.keycloak.services.resources.admin.permissions.RolePermissionManagement;
import org.keycloak.events.admin.OperationType;
import org.keycloak.events.admin.ResourceType;
import org.keycloak.models.ClientModel;
@@ -57,7 +59,7 @@ import java.util.Set;
public class RoleByIdResource extends RoleResource {
protected static final Logger logger = Logger.getLogger(RoleByIdResource.class);
private final RealmModel realm;
- private final RealmAuth auth;
+ private AdminPermissionEvaluator auth;
private AdminEventBuilder adminEvent;
@Context
@@ -66,7 +68,7 @@ public class RoleByIdResource extends RoleResource {
@Context
private UriInfo uriInfo;
- public RoleByIdResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
+ public RoleByIdResource(RealmModel realm, AdminPermissionEvaluator auth, AdminEventBuilder adminEvent) {
super(realm);
this.realm = realm;
@@ -85,9 +87,9 @@ public class RoleByIdResource extends RoleResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public RoleRepresentation getRole(final @PathParam("role-id") String id) {
- auth.requireAny();
RoleModel roleModel = getRoleModel(id);
+ auth.roles().requireView(roleModel);
return getRole(roleModel);
}
@@ -96,17 +98,7 @@ public class RoleByIdResource extends RoleResource {
if (roleModel == null) {
throw new NotFoundException("Could not find role with id");
}
-
- RealmAuth.Resource r = null;
- if (roleModel.getContainer() instanceof RealmModel) {
- r = RealmAuth.Resource.REALM;
- } else if (roleModel.getContainer() instanceof ClientModel) {
- r = RealmAuth.Resource.CLIENT;
- } else if (roleModel.getContainer() instanceof UserModel) {
- r = RealmAuth.Resource.USER;
- }
- auth.init(r);
- return roleModel;
+ return roleModel;
}
/**
@@ -118,9 +110,8 @@ public class RoleByIdResource extends RoleResource {
@DELETE
@NoCache
public void deleteRole(final @PathParam("role-id") String id) {
- auth.requireManage();
-
RoleModel role = getRoleModel(id);
+ auth.roles().requireManage(role);
deleteRole(role);
if (role.isClientRole()) {
@@ -142,9 +133,8 @@ public class RoleByIdResource extends RoleResource {
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public void updateRole(final @PathParam("role-id") String id, final RoleRepresentation rep) {
- auth.requireManage();
-
RoleModel role = getRoleModel(id);
+ auth.roles().requireManage(role);
updateRole(rep, role);
if (role.isClientRole()) {
@@ -166,10 +156,9 @@ public class RoleByIdResource extends RoleResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public void addComposites(final @PathParam("role-id") String id, List<RoleRepresentation> roles) {
- auth.requireManage();
-
RoleModel role = getRoleModel(id);
- addComposites(adminEvent, uriInfo, roles, role);
+ auth.roles().requireManage(role);
+ addComposites(auth, adminEvent, uriInfo, roles, role);
}
/**
@@ -185,11 +174,10 @@ public class RoleByIdResource extends RoleResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public Set<RoleRepresentation> getRoleComposites(final @PathParam("role-id") String id) {
- auth.requireAny();
if (logger.isDebugEnabled()) logger.debug("*** getRoleComposites: '" + id + "'");
RoleModel role = getRoleModel(id);
- auth.requireView();
+ auth.roles().requireView(role);
return getRoleComposites(role);
}
@@ -204,9 +192,9 @@ public class RoleByIdResource extends RoleResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public Set<RoleRepresentation> getRealmRoleComposites(final @PathParam("role-id") String id) {
- auth.requireAny();
-
RoleModel role = getRoleModel(id);
+ auth.roles().requireView(role);
+ auth.roles().requireView(role);
return getRealmRoleComposites(role);
}
@@ -223,9 +211,9 @@ public class RoleByIdResource extends RoleResource {
@Produces(MediaType.APPLICATION_JSON)
public Set<RoleRepresentation> getClientRoleComposites(final @PathParam("role-id") String id,
final @PathParam("client") String client) {
- auth.requireAny();
RoleModel role = getRoleModel(id);
+ auth.roles().requireView(role);
ClientModel clientModel = realm.getClientById(client);
if (clientModel == null) {
throw new NotFoundException("Could not find client");
@@ -243,9 +231,8 @@ public class RoleByIdResource extends RoleResource {
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
public void deleteComposites(final @PathParam("role-id") String id, List<RoleRepresentation> roles) {
- auth.requireManage();
-
RoleModel role = getRoleModel(id);
+ auth.roles().requireManage(role);
deleteComposites(adminEvent, uriInfo, roles, role);
}
@@ -261,24 +248,21 @@ public class RoleByIdResource extends RoleResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public ManagementPermissionReference getManagementPermissions(final @PathParam("role-id") String id) {
- auth.requireView();
-
RoleModel role = getRoleModel(id);
+ auth.roles().requireView(role);
- MgmtPermissions permissions = new MgmtPermissions(session, realm);
+ AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
if (!permissions.roles().isPermissionsEnabled(role)) {
return new ManagementPermissionReference();
}
return toMgmtRef(role, permissions);
}
- public static ManagementPermissionReference toMgmtRef(RoleModel role, MgmtPermissions permissions) {
+ public static ManagementPermissionReference toMgmtRef(RoleModel role, AdminPermissionManagement permissions) {
ManagementPermissionReference ref = new ManagementPermissionReference();
ref.setEnabled(true);
ref.setResource(permissions.roles().resource(role).getId());
- Map<String, String> scopes = new HashMap<>();
- scopes.put(RoleMgmtPermissions.MAP_ROLE_SCOPE, permissions.roles().mapRolePermission(role).getId());
- ref.setScopePermissions(scopes);
+ ref.setScopePermissions(permissions.roles().getPermissions(role));
return ref;
}
@@ -295,11 +279,10 @@ public class RoleByIdResource extends RoleResource {
@Consumes(MediaType.APPLICATION_JSON)
@NoCache
public ManagementPermissionReference setManagementPermissionsEnabled(final @PathParam("role-id") String id, ManagementPermissionReference ref) {
- auth.requireManage();
-
RoleModel role = getRoleModel(id);
+ auth.roles().requireManage(role);
- MgmtPermissions permissions = new MgmtPermissions(session, realm);
+ AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
permissions.roles().setPermissionsEnabled(role, ref.isEnabled());
if (ref.isEnabled()) {
return toMgmtRef(role, permissions);
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 94e4def..7f4d495 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
@@ -19,8 +19,9 @@ package org.keycloak.services.resources.admin;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.authorization.admin.permissions.MgmtPermissions;
-import org.keycloak.authorization.admin.permissions.RoleMgmtPermissions;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionManagement;
+import org.keycloak.services.resources.admin.permissions.AdminPermissions;
import org.keycloak.events.admin.OperationType;
import org.keycloak.events.admin.ResourceType;
import org.keycloak.models.ClientModel;
@@ -37,20 +38,20 @@ import org.keycloak.services.ErrorResponse;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
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.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.Set;
/**
@@ -60,13 +61,19 @@ import java.util.Set;
*/
public class RoleContainerResource extends RoleResource {
private final RealmModel realm;
- private final RealmAuth auth;
+ protected AdminPermissionEvaluator auth;
+ protected AdminPermissionEvaluator.RequirePermissionCheck managePermission;
+ protected AdminPermissionEvaluator.RequirePermissionCheck viewPermission;
+
protected RoleContainerModel roleContainer;
private AdminEventBuilder adminEvent;
private UriInfo uriInfo;
private KeycloakSession session;
- public RoleContainerResource(KeycloakSession session, UriInfo uriInfo, RealmModel realm, RealmAuth auth, RoleContainerModel roleContainer, AdminEventBuilder adminEvent) {
+ public RoleContainerResource(KeycloakSession session, UriInfo uriInfo, RealmModel realm,
+ AdminPermissionEvaluator auth, RoleContainerModel roleContainer, AdminEventBuilder adminEvent,
+ AdminPermissionEvaluator.RequirePermissionCheck managePermission,
+ AdminPermissionEvaluator.RequirePermissionCheck viewPermission) {
super(realm);
this.uriInfo = uriInfo;
this.realm = realm;
@@ -74,6 +81,8 @@ public class RoleContainerResource extends RoleResource {
this.roleContainer = roleContainer;
this.adminEvent = adminEvent;
this.session = session;
+ this.managePermission = managePermission;
+ this.viewPermission = viewPermission;
}
/**
@@ -85,11 +94,7 @@ public class RoleContainerResource extends RoleResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<RoleRepresentation> getRoles() {
- auth.requireAny();
-
- if (roleContainer == null) {
- throw new NotFoundException("Could not find client");
- }
+ auth.roles().requireList(roleContainer);
Set<RoleModel> roleModels = roleContainer.getRoles();
List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
@@ -108,11 +113,7 @@ public class RoleContainerResource extends RoleResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response createRole(final RoleRepresentation rep) {
- auth.requireManage();
-
- if (roleContainer == null) {
- throw new NotFoundException("Could not find client");
- }
+ managePermission.require();
if (rep.getName() == null) {
throw new BadRequestException();
@@ -151,16 +152,12 @@ public class RoleContainerResource extends RoleResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public RoleRepresentation getRole(final @PathParam("role-name") String roleName) {
- auth.requireView();
-
- if (roleContainer == null) {
- throw new NotFoundException("Could not find client");
- }
RoleModel roleModel = roleContainer.getRole(roleName);
if (roleModel == null) {
throw new NotFoundException("Could not find role");
}
+ auth.roles().requireView(roleModel);
return getRole(roleModel);
}
@@ -174,16 +171,11 @@ public class RoleContainerResource extends RoleResource {
@DELETE
@NoCache
public void deleteRole(final @PathParam("role-name") String roleName) {
- auth.requireManage();
-
- if (roleContainer == null) {
- throw new NotFoundException("Could not find client");
- }
-
RoleModel role = roleContainer.getRole(roleName);
if (role == null) {
throw new NotFoundException("Could not find role");
}
+ auth.roles().requireManage(role);
deleteRole(role);
if (role.isClientRole()) {
@@ -207,16 +199,11 @@ public class RoleContainerResource extends RoleResource {
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public Response updateRole(final @PathParam("role-name") String roleName, final RoleRepresentation rep) {
- auth.requireManage();
-
- if (roleContainer == null) {
- throw new NotFoundException("Could not find client");
- }
-
RoleModel role = roleContainer.getRole(roleName);
if (role == null) {
throw new NotFoundException("Could not find role");
}
+ auth.roles().requireManage(role);
try {
updateRole(rep, role);
@@ -244,17 +231,12 @@ public class RoleContainerResource extends RoleResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public void addComposites(final @PathParam("role-name") String roleName, List<RoleRepresentation> roles) {
- auth.requireManage();
-
- if (roleContainer == null) {
- throw new NotFoundException("Could not find client");
- }
-
- RoleModel role = roleContainer.getRole(roleName);
+ RoleModel role = roleContainer.getRole(roleName);
if (role == null) {
throw new NotFoundException("Could not find role");
}
- addComposites(adminEvent, uriInfo, roles, role);
+ auth.roles().requireManage(role);
+ addComposites(auth, adminEvent, uriInfo, roles, role);
}
/**
@@ -268,16 +250,11 @@ public class RoleContainerResource extends RoleResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public Set<RoleRepresentation> getRoleComposites(final @PathParam("role-name") String roleName) {
- auth.requireView();
-
- if (roleContainer == null) {
- throw new NotFoundException("Could not find client");
- }
-
RoleModel role = roleContainer.getRole(roleName);
if (role == null) {
throw new NotFoundException("Could not find role");
}
+ auth.roles().requireView(role);
return getRoleComposites(role);
}
@@ -292,16 +269,11 @@ public class RoleContainerResource extends RoleResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public Set<RoleRepresentation> getRealmRoleComposites(final @PathParam("role-name") String roleName) {
- auth.requireView();
-
- if (roleContainer == null) {
- throw new NotFoundException("Could not find client");
- }
-
RoleModel role = roleContainer.getRole(roleName);
if (role == null) {
throw new NotFoundException("Could not find role");
}
+ auth.roles().requireView(role);
return getRealmRoleComposites(role);
}
@@ -319,16 +291,11 @@ public class RoleContainerResource extends RoleResource {
public Set<RoleRepresentation> getClientRoleComposites(@Context final UriInfo uriInfo,
final @PathParam("role-name") String roleName,
final @PathParam("client") String client) {
- auth.requireView();
-
- if (roleContainer == null) {
- throw new NotFoundException("Could not find client");
- }
-
RoleModel role = roleContainer.getRole(roleName);
if (role == null) {
throw new NotFoundException("Could not find role");
}
+ auth.roles().requireView(role);
ClientModel clientModel = realm.getClientById(client);
if (client == null) {
throw new NotFoundException("Could not find client");
@@ -350,16 +317,12 @@ public class RoleContainerResource extends RoleResource {
public void deleteComposites(
final @PathParam("role-name") String roleName,
List<RoleRepresentation> roles) {
- auth.requireManage();
-
- if (roleContainer == null) {
- throw new NotFoundException("Could not find client");
- }
RoleModel role = roleContainer.getRole(roleName);
if (role == null) {
throw new NotFoundException("Could not find role");
}
+ auth.roles().requireManage(role);
deleteComposites(adminEvent, uriInfo, roles, role);
}
@@ -375,18 +338,13 @@ public class RoleContainerResource extends RoleResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public ManagementPermissionReference getManagementPermissions(final @PathParam("role-name") String roleName) {
- auth.requireView();
-
- if (roleContainer == null) {
- throw new NotFoundException("Could not find client");
- }
-
RoleModel role = roleContainer.getRole(roleName);
if (role == null) {
throw new NotFoundException("Could not find role");
}
+ auth.roles().requireView(role);
- MgmtPermissions permissions = new MgmtPermissions(session, realm);
+ AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
if (!permissions.roles().isPermissionsEnabled(role)) {
return new ManagementPermissionReference();
}
@@ -406,19 +364,14 @@ public class RoleContainerResource extends RoleResource {
@Consumes(MediaType.APPLICATION_JSON)
@NoCache
public ManagementPermissionReference setManagementPermissionsEnabled(final @PathParam("role-name") String roleName, ManagementPermissionReference ref) {
- auth.requireManage();
-
- if (roleContainer == null) {
- throw new NotFoundException("Could not find client");
- }
-
RoleModel role = roleContainer.getRole(roleName);
if (role == null) {
throw new NotFoundException("Could not find role");
}
+ auth.roles().requireManage(role);
if (ref.isEnabled()) {
- MgmtPermissions permissions = new MgmtPermissions(session, realm);
+ AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
permissions.roles().setPermissionsEnabled(role, ref.isEnabled());
return RoleByIdResource.toMgmtRef(role, permissions);
} else {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleMapperResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleMapperResource.java
index 93d4cb6..8db0591 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleMapperResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleMapperResource.java
@@ -19,7 +19,7 @@ package org.keycloak.services.resources.admin;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.authorization.admin.permissions.MgmtPermissions;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.common.ClientConnection;
import org.keycloak.events.admin.OperationType;
import org.keycloak.events.admin.ResourceType;
@@ -52,7 +52,6 @@ import javax.ws.rs.core.UriInfo;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -69,27 +68,17 @@ import java.util.stream.Collectors;
*/
public class RoleMapperResource {
- /**
- * RoleMapperResource is reused bewteen GroupResource and UserResource to manage role mappings.
- * We don't know what type of resource we're managing here (user or group), so we don't know how to query the policy engine to determine
- * if an action is allowed.
- *
- */
- public interface ManageResourcePermissionCheck {
- boolean canManage();
- }
-
protected static final Logger logger = Logger.getLogger(RoleMapperResource.class);
protected RealmModel realm;
- private RealmAuth auth;
-
private RoleMapperModel roleMapper;
private AdminEventBuilder adminEvent;
- private ManageResourcePermissionCheck manageResourcePermissionCheck;
+ protected AdminPermissionEvaluator.RequirePermissionCheck managePermission;
+ protected AdminPermissionEvaluator.RequirePermissionCheck viewPermission;
+ private AdminPermissionEvaluator auth;
@Context
protected ClientConnection clientConnection;
@@ -103,18 +92,21 @@ public class RoleMapperResource {
@Context
protected HttpHeaders headers;
- public RoleMapperResource(RealmModel realm, RealmAuth auth, RoleMapperModel roleMapper, AdminEventBuilder adminEvent) {
+ public RoleMapperResource(RealmModel realm,
+ AdminPermissionEvaluator auth,
+ RoleMapperModel roleMapper,
+ AdminEventBuilder adminEvent,
+ AdminPermissionEvaluator.RequirePermissionCheck manageCheck,
+ AdminPermissionEvaluator.RequirePermissionCheck viewCheck) {
this.auth = auth;
this.realm = realm;
this.adminEvent = adminEvent.resource(ResourceType.REALM_ROLE_MAPPING);
this.roleMapper = roleMapper;
+ this.managePermission = manageCheck;
+ this.viewPermission = viewCheck;
}
- public void setManageCheck(ManageResourcePermissionCheck mapperPermissions) {
- this.manageResourcePermissionCheck = mapperPermissions;
- }
-
/**
* Get role mappings
*
@@ -124,11 +116,7 @@ public class RoleMapperResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public MappingsRepresentation getRoleMappings() {
- auth.requireView();
-
- if (roleMapper == null) {
- throw new NotFoundException("User not found");
- }
+ viewPermission.require();
MappingsRepresentation all = new MappingsRepresentation();
Set<RoleModel> realmMappings = roleMapper.getRealmRoleMappings();
@@ -173,11 +161,7 @@ public class RoleMapperResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getRealmRoleMappings() {
- auth.requireView();
-
- if (roleMapper == null) {
- throw new NotFoundException("User not found");
- }
+ viewPermission.require();
Set<RoleModel> realmMappings = roleMapper.getRealmRoleMappings();
List<RoleRepresentation> realmMappingsRep = new ArrayList<RoleRepresentation>();
@@ -199,11 +183,7 @@ public class RoleMapperResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getCompositeRealmRoleMappings() {
- auth.requireView();
-
- if (roleMapper == null) {
- throw new NotFoundException("User not found");
- }
+ viewPermission.require();
Set<RoleModel> roles = realm.getRoles();
List<RoleRepresentation> realmMappingsRep = new ArrayList<RoleRepresentation>();
@@ -225,11 +205,7 @@ public class RoleMapperResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getAvailableRealmRoleMappings() {
- auth.requireView();
-
- if (roleMapper == null) {
- throw new NotFoundException("User not found");
- }
+ viewPermission.require();
Set<RoleModel> available = realm.getRoles();
Set<RoleModel> set = available.stream().filter(r ->
@@ -247,11 +223,7 @@ public class RoleMapperResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public void addRealmRoleMappings(List<RoleRepresentation> roles) {
- checkManagePermission();
-
- if (roleMapper == null) {
- throw new NotFoundException("User not found");
- }
+ managePermission.require();
logger.debugv("** addRealmRoleMappings: {0}", roles);
@@ -267,16 +239,6 @@ public class RoleMapperResource {
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(roles).success();
}
- private void checkManagePermission() {
- if (manageResourcePermissionCheck == null) {
- auth.requireManage();
- } else {
- if (!manageResourcePermissionCheck.canManage()) {
- throw new ForbiddenException();
- }
- }
- }
-
/**
* Delete realm-level role mappings
*
@@ -286,11 +248,7 @@ public class RoleMapperResource {
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
public void deleteRealmRoleMappings(List<RoleRepresentation> roles) {
- checkManagePermission();
-
- if (roleMapper == null) {
- throw new NotFoundException("User not found");
- }
+ managePermission.require();
logger.debug("deleteRealmRoleMappings");
if (roles == null) {
@@ -313,7 +271,7 @@ public class RoleMapperResource {
try {
roleMapper.deleteRoleMapping(roleModel);
} catch (ModelException me) {
- Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
+ Properties messages = AdminRoot.getMessages(session, realm, auth.adminAuth().getToken().getLocale());
throw new ErrorResponseException(me.getMessage(), MessageFormat.format(messages.getProperty(me.getMessage(), me.getMessage()), me.getParameters()),
Response.Status.BAD_REQUEST);
}
@@ -332,16 +290,18 @@ public class RoleMapperResource {
}
private boolean canMapRole(RoleModel roleModel) {
- return new MgmtPermissions(session, realm, auth.getAuth()).roles().canMapRole(roleModel);
+ return auth.roles().canMapRole(roleModel);
}
@Path("clients/{client}")
public ClientRoleMappingsResource getUserClientRoleMappingsResource(@PathParam("client") String client) {
ClientModel clientModel = realm.getClientById(client);
- ClientRoleMappingsResource resource = new ClientRoleMappingsResource(uriInfo, session, realm, auth, roleMapper, clientModel, adminEvent);
- resource.setManageCheck(() -> {
- return new MgmtPermissions(session, realm, auth.getAuth()).users().canManage();
- });
+ if (clientModel == null) {
+ throw new NotFoundException("Client not found");
+ }
+ ClientRoleMappingsResource resource = new ClientRoleMappingsResource(uriInfo, session, realm, auth, roleMapper,
+ clientModel, adminEvent,
+ managePermission, viewPermission);
return resource;
}
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 5fb1d34..cdd9cd7 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
@@ -25,6 +25,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import javax.ws.rs.core.UriInfo;
import java.util.Collections;
@@ -60,12 +61,13 @@ public abstract class RoleResource {
if (rep.isScopeParamRequired() != null) role.setScopeParamRequired(rep.isScopeParamRequired());
}
- protected void addComposites(AdminEventBuilder adminEvent, UriInfo uriInfo, List<RoleRepresentation> roles, RoleModel role) {
+ protected void addComposites(AdminPermissionEvaluator auth, AdminEventBuilder adminEvent, UriInfo uriInfo, List<RoleRepresentation> roles, RoleModel role) {
for (RoleRepresentation rep : roles) {
RoleModel composite = realm.getRoleById(rep.getId());
if (composite == null) {
throw new NotFoundException("Could not find composite role");
}
+ auth.roles().requireManage(composite);
role.addCompositeRole(composite);
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedClientResource.java
index 431e97c..4f7b5dc 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedClientResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedClientResource.java
@@ -29,6 +29,7 @@ import org.keycloak.models.ScopeContainerModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@@ -49,19 +50,25 @@ import java.util.Set;
*/
public class ScopeMappedClientResource {
protected RealmModel realm;
- private RealmAuth auth;
+ protected AdminPermissionEvaluator auth;
+ protected AdminPermissionEvaluator.RequirePermissionCheck managePermission;
+ protected AdminPermissionEvaluator.RequirePermissionCheck viewPermission;
protected ScopeContainerModel scopeContainer;
protected KeycloakSession session;
protected ClientModel scopedClient;
protected AdminEventBuilder adminEvent;
- public ScopeMappedClientResource(RealmModel realm, RealmAuth auth, ScopeContainerModel scopeContainer, KeycloakSession session, ClientModel scopedClient, AdminEventBuilder adminEvent) {
+ public ScopeMappedClientResource(RealmModel realm, AdminPermissionEvaluator auth, ScopeContainerModel scopeContainer, KeycloakSession session, ClientModel scopedClient, AdminEventBuilder adminEvent,
+ AdminPermissionEvaluator.RequirePermissionCheck managePermission,
+ AdminPermissionEvaluator.RequirePermissionCheck viewPermission) {
this.realm = realm;
this.auth = auth;
this.scopeContainer = scopeContainer;
this.session = session;
this.scopedClient = scopedClient;
this.adminEvent = adminEvent.resource(ResourceType.CLIENT_SCOPE_MAPPING);
+ this.managePermission = managePermission;
+ this.viewPermission = viewPermission;
}
/**
@@ -75,11 +82,7 @@ public class ScopeMappedClientResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getClientScopeMappings() {
- auth.requireView();
-
- if (scopeContainer == null) {
- throw new NotFoundException("Could not find client");
- }
+ viewPermission.require();
Set<RoleModel> mappings = KeycloakModelUtils.getClientScopeMappings(scopedClient, scopeContainer); //scopedClient.getClientScopeMappings(client);
List<RoleRepresentation> mapRep = new ArrayList<RoleRepresentation>();
@@ -101,14 +104,10 @@ public class ScopeMappedClientResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getAvailableClientScopeMappings() {
- auth.requireView();
-
- if (scopeContainer == null) {
- throw new NotFoundException("Could not find client");
- }
+ viewPermission.require();
Set<RoleModel> roles = scopedClient.getRoles();
- return ScopeMappedResource.getAvailable(scopeContainer, roles);
+ return ScopeMappedResource.getAvailable(auth, scopeContainer, roles);
}
/**
@@ -123,11 +122,7 @@ public class ScopeMappedClientResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getCompositeClientScopeMappings() {
- auth.requireView();
-
- if (scopeContainer == null) {
- throw new NotFoundException("Could not find client");
- }
+ viewPermission.require();
Set<RoleModel> roles = scopedClient.getRoles();
return ScopeMappedResource.getComposite(scopeContainer, roles);
@@ -141,11 +136,7 @@ public class ScopeMappedClientResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public void addClientScopeMapping(List<RoleRepresentation> roles) {
- auth.requireManage();
-
- if (scopeContainer == null) {
- throw new NotFoundException("Could not find client");
- }
+ managePermission.require();
for (RoleRepresentation role : roles) {
RoleModel roleModel = scopedClient.getRole(role.getName());
@@ -166,11 +157,7 @@ public class ScopeMappedClientResource {
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
public void deleteClientScopeMapping(List<RoleRepresentation> roles) {
- auth.requireManage();
-
- if (scopeContainer == null) {
- throw new NotFoundException("Could not find client");
- }
+ managePermission.require();
if (roles == null) {
Set<RoleModel> roleModels = KeycloakModelUtils.getClientScopeMappings(scopedClient, scopeContainer);//scopedClient.getClientScopeMappings(client);
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 19a32f9..286e22b 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
@@ -31,6 +31,7 @@ import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.representations.idm.ClientMappingsRepresentation;
import org.keycloak.representations.idm.MappingsRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@@ -56,17 +57,25 @@ import java.util.Set;
*/
public class ScopeMappedResource {
protected RealmModel realm;
- private RealmAuth auth;
+ protected AdminPermissionEvaluator auth;
+ protected AdminPermissionEvaluator.RequirePermissionCheck managePermission;
+ protected AdminPermissionEvaluator.RequirePermissionCheck viewPermission;
+
protected ScopeContainerModel scopeContainer;
protected KeycloakSession session;
protected AdminEventBuilder adminEvent;
- public ScopeMappedResource(RealmModel realm, RealmAuth auth, ScopeContainerModel scopeContainer, KeycloakSession session, AdminEventBuilder adminEvent) {
+ public ScopeMappedResource(RealmModel realm, AdminPermissionEvaluator auth, ScopeContainerModel scopeContainer,
+ KeycloakSession session, AdminEventBuilder adminEvent,
+ AdminPermissionEvaluator.RequirePermissionCheck managePermission,
+ AdminPermissionEvaluator.RequirePermissionCheck viewPermission) {
this.realm = realm;
this.auth = auth;
this.scopeContainer = scopeContainer;
this.session = session;
this.adminEvent = adminEvent.resource(ResourceType.REALM_SCOPE_MAPPING);
+ this.managePermission = managePermission;
+ this.viewPermission = viewPermission;
}
/**
@@ -78,7 +87,7 @@ public class ScopeMappedResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public MappingsRepresentation getScopeMappings() {
- auth.requireView();
+ viewPermission.require();
if (scopeContainer == null) {
throw new NotFoundException("Could not find client");
@@ -126,7 +135,7 @@ public class ScopeMappedResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getRealmScopeMappings() {
- auth.requireView();
+ viewPermission.require();
if (scopeContainer == null) {
throw new NotFoundException("Could not find client");
@@ -150,20 +159,21 @@ public class ScopeMappedResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getAvailableRealmScopeMappings() {
- auth.requireView();
+ viewPermission.require();
if (scopeContainer == null) {
throw new NotFoundException("Could not find client");
}
Set<RoleModel> roles = realm.getRoles();
- return getAvailable(scopeContainer, roles);
+ return getAvailable(auth, scopeContainer, roles);
}
- public static List<RoleRepresentation> getAvailable(ScopeContainerModel client, Set<RoleModel> roles) {
+ public static List<RoleRepresentation> getAvailable(AdminPermissionEvaluator auth, ScopeContainerModel client, Set<RoleModel> roles) {
List<RoleRepresentation> available = new ArrayList<RoleRepresentation>();
for (RoleModel roleModel : roles) {
if (client.hasScope(roleModel)) continue;
+ if (!auth.roles().canMapClientScope(roleModel)) continue;
available.add(ModelToRepresentation.toRepresentation(roleModel));
}
return available;
@@ -183,7 +193,7 @@ public class ScopeMappedResource {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getCompositeRealmScopeMappings() {
- auth.requireView();
+ viewPermission.require();
if (scopeContainer == null) {
throw new NotFoundException("Could not find client");
@@ -210,7 +220,7 @@ public class ScopeMappedResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public void addRealmScopeMappings(List<RoleRepresentation> roles) {
- auth.requireManage();
+ managePermission.require();
if (scopeContainer == null) {
throw new NotFoundException("Could not find client");
@@ -236,7 +246,7 @@ public class ScopeMappedResource {
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
public void deleteRealmScopeMappings(List<RoleRepresentation> roles) {
- auth.requireManage();
+ managePermission.require();
if (scopeContainer == null) {
throw new NotFoundException("Could not find client");
@@ -268,6 +278,9 @@ public class ScopeMappedResource {
@Path("clients/{client}")
public ScopeMappedClientResource getClientByIdScopeMappings(@PathParam("client") String client) {
ClientModel clientModel = realm.getClientById(client);
- return new ScopeMappedClientResource(realm, auth, this.scopeContainer, session, clientModel, adminEvent);
+ if (clientModel == null) {
+ throw new NotFoundException("Could not find client");
+ }
+ return new ScopeMappedClientResource(realm, auth, this.scopeContainer, session, clientModel, adminEvent, managePermission, viewPermission);
}
}
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 2685e8e..502fbe3 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
@@ -22,8 +22,8 @@ import org.jboss.resteasy.spi.BadRequestException;
import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.authentication.RequiredActionProvider;
-import org.keycloak.authorization.admin.permissions.MgmtPermissions;
import org.keycloak.authentication.actiontoken.execactions.ExecuteActionsActionToken;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.common.ClientConnection;
import org.keycloak.common.Profile;
import org.keycloak.common.util.Time;
@@ -36,7 +36,6 @@ import org.keycloak.events.EventType;
import org.keycloak.events.admin.OperationType;
import org.keycloak.events.admin.ResourceType;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.Constants;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.GroupModel;
@@ -116,7 +115,7 @@ public class UsersResource {
protected RealmModel realm;
- private RealmAuth auth;
+ private AdminPermissionEvaluator auth;
private AdminEventBuilder adminEvent;
@@ -132,12 +131,10 @@ public class UsersResource {
@Context
protected HttpHeaders headers;
- public UsersResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
+ public UsersResource(RealmModel realm, AdminPermissionEvaluator auth, AdminEventBuilder adminEvent) {
this.auth = auth;
this.realm = realm;
this.adminEvent = adminEvent.resource(ResourceType.USER);
-
- auth.init(RealmAuth.Resource.USER);
}
/**
@@ -151,13 +148,13 @@ public class UsersResource {
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public Response updateUser(final @PathParam("id") String id, final UserRepresentation rep) {
- auth.requireManage();
try {
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
return Response.status(Status.NOT_FOUND).build();
}
+ auth.users().requireManage(user);
Set<String> attrsToRemove;
if (rep.getAttributes() != null) {
@@ -188,6 +185,8 @@ public class UsersResource {
} catch (ModelException me) {
logger.warn("Could not update user!", me);
return ErrorResponse.exists("Could not update user!");
+ } catch (ForbiddenException fe) {
+ throw fe;
} catch (Exception me) { // JPA
logger.warn("Could not update user!", me);// may be committed by JTA which can't
return ErrorResponse.exists("Could not update user!");
@@ -206,7 +205,7 @@ public class UsersResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response createUser(final @Context UriInfo uriInfo, final UserRepresentation rep) {
- auth.requireManage();
+ auth.users().requireManage();
// Double-check duplicated username and email here due to federation
if (session.users().getUserByUsername(rep.getUsername(), realm) != null) {
@@ -291,13 +290,13 @@ public class UsersResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public UserRepresentation getUser(final @PathParam("id") String id) {
- auth.requireView();
-
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
+ auth.users().requireView(user);
+
UserRepresentation rep = ModelToRepresentation.toRepresentation(session, realm, user);
if (realm.isIdentityFederationEnabled()) {
@@ -325,19 +324,17 @@ public class UsersResource {
public Map<String, Object> impersonate(final @PathParam("id") String id) {
ProfileHelper.requireFeature(Profile.Feature.IMPERSONATION);
- auth.init(RealmAuth.Resource.IMPERSONATION);
- auth.requireManage();
-
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
- RealmModel authenticatedRealm = auth.getAuth().getRealm();
+ auth.users().requireImpersonate(user);
+ RealmModel authenticatedRealm = auth.adminAuth().getRealm();
// if same realm logout before impersonation
boolean sameRealm = false;
if (authenticatedRealm.getId().equals(realm.getId())) {
sameRealm = true;
- UserSessionModel userSession = session.sessions().getUserSession(authenticatedRealm, auth.getAuth().getToken().getSessionState());
+ UserSessionModel userSession = session.sessions().getUserSession(authenticatedRealm, auth.adminAuth().getToken().getSessionState());
AuthenticationManager.expireIdentityCookie(realm, uriInfo, clientConnection);
AuthenticationManager.expireRememberMeCookie(realm, uriInfo, clientConnection);
AuthenticationManager.backchannelLogout(session, authenticatedRealm, userSession, uriInfo, clientConnection, headers, true);
@@ -355,7 +352,7 @@ public class UsersResource {
.session(userSession)
.user(user)
.detail(Details.IMPERSONATOR_REALM,authenticatedRealm.getName())
- .detail(Details.IMPERSONATOR, auth.getAuth().getUser().getUsername()).success();
+ .detail(Details.IMPERSONATOR, auth.adminAuth().getUser().getUsername()).success();
return result;
}
@@ -372,12 +369,11 @@ public class UsersResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<UserSessionRepresentation> getSessions(final @PathParam("id") String id) {
- auth.requireView();
-
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
+ auth.users().requireView(user);
List<UserSessionModel> sessions = session.sessions().getUserSessions(realm, user);
List<UserSessionRepresentation> reps = new ArrayList<UserSessionRepresentation>();
for (UserSessionModel session : sessions) {
@@ -398,12 +394,11 @@ public class UsersResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<UserSessionRepresentation> getOfflineSessions(final @PathParam("id") String id, final @PathParam("clientId") String clientId) {
- auth.requireView();
-
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
+ auth.users().requireView(user);
ClientModel client = realm.getClientById(clientId);
if (client == null) {
throw new NotFoundException("Client not found");
@@ -439,12 +434,11 @@ public class UsersResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<FederatedIdentityRepresentation> getFederatedIdentity(final @PathParam("id") String id) {
- auth.requireView();
-
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
+ auth.users().requireView(user);
return getFederatedIdentities(user);
}
@@ -476,12 +470,12 @@ public class UsersResource {
@POST
@NoCache
public Response addFederatedIdentity(final @PathParam("id") String id, final @PathParam("provider") String provider, FederatedIdentityRepresentation rep) {
- auth.requireManage();
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
+ auth.users().requireManage(user);
if (session.users().getFederatedIdentity(user, provider, realm) != null) {
return ErrorResponse.exists("User is already linked with provider");
}
@@ -502,12 +496,11 @@ public class UsersResource {
@DELETE
@NoCache
public void removeFederatedIdentity(final @PathParam("id") String id, final @PathParam("provider") String provider) {
- auth.requireManage();
-
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
+ auth.users().requireManage(user);
if (!session.users().removeFederatedIdentity(realm, user, provider)) {
throw new NotFoundException("Link not found");
}
@@ -525,13 +518,11 @@ public class UsersResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<Map<String, Object>> getConsents(final @PathParam("id") String id) {
- auth.requireView();
-
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
-
+ auth.users().requireView(user);
List<Map<String, Object>> result = new LinkedList<>();
Set<ClientModel> offlineClients = new UserSessionManager(session).findClientsWithOfflineToken(realm, user);
@@ -580,14 +571,16 @@ public class UsersResource {
@DELETE
@NoCache
public void revokeConsent(final @PathParam("id") String id, final @PathParam("client") String clientId) {
- auth.requireManage();
-
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
+ auth.users().requireManage(user);
ClientModel client = realm.getClientByClientId(clientId);
+ if (client == null) {
+ throw new NotFoundException("Client not found");
+ }
boolean revokedConsent = session.users().revokeConsentForClient(realm, user.getId(), client.getId());
boolean revokedOfflineToken = new UserSessionManager(session).revokeOfflineToken(user, client);
@@ -612,12 +605,11 @@ public class UsersResource {
@Path("{id}/logout")
@POST
public void logout(final @PathParam("id") String id) {
- auth.requireManage();
-
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
+ auth.users().requireManage(user);
List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
for (UserSessionModel userSession : userSessions) {
@@ -635,12 +627,11 @@ public class UsersResource {
@DELETE
@NoCache
public Response deleteUser(final @PathParam("id") String id) {
- auth.requireManage();
-
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
+ auth.users().requireManage(user);
boolean removed = new UserManager(session).removeUser(realm, user);
if (removed) {
@@ -675,7 +666,7 @@ public class UsersResource {
@QueryParam("username") String username,
@QueryParam("first") Integer firstResult,
@QueryParam("max") Integer maxResults) {
- auth.requireView();
+ auth.users().requireQuery();
firstResult = firstResult != null ? firstResult : -1;
maxResults = maxResults != null ? maxResults : Constants.DEFAULT_MAX_RESULTS;
@@ -703,7 +694,9 @@ public class UsersResource {
userModels = session.users().getUsers(realm, firstResult, maxResults, false);
}
+ boolean canViewGlobal = auth.users().canView();
for (UserModel user : userModels) {
+ if (!canViewGlobal && !auth.users().canView(user)) continue;
results.add(ModelToRepresentation.toRepresentation(session, realm, user));
}
return results;
@@ -714,21 +707,23 @@ public class UsersResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public Integer getUsersCount() {
- auth.requireView();
+ auth.users().requireView();
return session.users().getUsersCount(realm);
}
@Path("{id}/role-mappings")
public RoleMapperResource getRoleMappings(@PathParam("id") String id) {
- auth.init(RealmAuth.Resource.USER);
UserModel user = session.users().getUserById(id, realm);
- RoleMapperResource resource = new RoleMapperResource(realm, auth, user, adminEvent);
- resource.setManageCheck(() -> {
- return new MgmtPermissions(session, realm, auth.getAuth()).users().canManage();
- });
+ if (user == null) {
+ throw new NotFoundException("User not found");
+ }
+
+ AdminPermissionEvaluator.RequirePermissionCheck manageCheck = () -> auth.users().requireManage(user);
+ AdminPermissionEvaluator.RequirePermissionCheck viewCheck = () -> auth.users().requireView(user);
+ RoleMapperResource resource = new RoleMapperResource(realm, auth, user, adminEvent, manageCheck, viewCheck);
ResteasyProviderFactory.getInstance().injectProperties(resource);
return resource;
@@ -744,12 +739,12 @@ public class UsersResource {
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public void disableCredentialType(@PathParam("id") String id, List<String> credentialTypes) {
- auth.requireManage();
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
+ auth.users().requireManage(user);
if (credentialTypes == null) return;
for (String type : credentialTypes) {
session.userCredentialManager().disableCredentialType(realm, user, type);
@@ -771,12 +766,12 @@ public class UsersResource {
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public void resetPassword(@PathParam("id") String id, CredentialRepresentation pass) {
- auth.requireManage();
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
+ auth.users().requireManage(user);
if (pass == null || pass.getValue() == null || !CredentialRepresentation.PASSWORD.equals(pass.getType())) {
throw new BadRequestException("No password provided");
}
@@ -792,7 +787,7 @@ public class UsersResource {
} catch (ReadOnlyException mre) {
throw new BadRequestException("Can't reset password as account is read only");
} catch (ModelException e) {
- Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
+ Properties messages = AdminRoot.getMessages(session, realm, auth.adminAuth().getToken().getLocale());
throw new ErrorResponseException(e.getMessage(), MessageFormat.format(messages.getProperty(e.getMessage(), e.getMessage()), e.getParameters()),
Status.BAD_REQUEST);
}
@@ -810,13 +805,15 @@ public class UsersResource {
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public void removeTotp(@PathParam("id") String id) {
- auth.requireManage();
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
+ auth.users().requireManage(user);
+
+
session.userCredentialManager().disableCredentialType(realm, user, CredentialModel.OTP);
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
}
@@ -870,12 +867,12 @@ public class UsersResource {
@QueryParam(OIDCLoginProtocol.CLIENT_ID_PARAM) String clientId,
@QueryParam("lifespan") Integer lifespan,
List<String> actions) {
- auth.requireManage();
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
return ErrorResponse.error("User not found", Response.Status.NOT_FOUND);
}
+ auth.users().requireManage(user);
if (user.getEmail() == null) {
return ErrorResponse.error("User email missing", Response.Status.BAD_REQUEST);
@@ -964,12 +961,12 @@ public class UsersResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<GroupRepresentation> groupMembership(@PathParam("id") String id) {
- auth.requireView();
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
+ auth.users().requireView(user);
List<GroupRepresentation> memberships = new LinkedList<>();
for (GroupModel group : user.getGroups()) {
memberships.add(ModelToRepresentation.toRepresentation(group, false));
@@ -981,12 +978,13 @@ public class UsersResource {
@Path("{id}/groups/{groupId}")
@NoCache
public void removeMembership(@PathParam("id") String id, @PathParam("groupId") String groupId) {
- auth.requireManage();
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
+ auth.users().requireManage(user);
+
GroupModel group = session.realms().getGroupById(groupId, realm);
if (group == null) {
throw new NotFoundException("Group not found");
@@ -998,7 +996,7 @@ public class UsersResource {
adminEvent.operation(OperationType.DELETE).resource(ResourceType.GROUP_MEMBERSHIP).representation(ModelToRepresentation.toRepresentation(group, true)).resourcePath(uriInfo).success();
}
} catch (ModelException me) {
- Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
+ Properties messages = AdminRoot.getMessages(session, realm, auth.adminAuth().getToken().getLocale());
throw new ErrorResponseException(me.getMessage(), MessageFormat.format(messages.getProperty(me.getMessage(), me.getMessage()), me.getParameters()),
Response.Status.BAD_REQUEST);
}
@@ -1008,12 +1006,12 @@ public class UsersResource {
@Path("{id}/groups/{groupId}")
@NoCache
public void joinGroup(@PathParam("id") String id, @PathParam("groupId") String groupId) {
- auth.requireManage();
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
throw new NotFoundException("User not found");
}
+ auth.users().requireManage(user);
GroupModel group = session.realms().getGroupById(groupId, realm);
if (group == null) {
throw new NotFoundException("Group not found");
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserStorageProviderResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserStorageProviderResource.java
index 4ffcf86..638f57b 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/UserStorageProviderResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UserStorageProviderResource.java
@@ -26,6 +26,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.managers.UserStorageSyncManager;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.ldap.LDAPStorageProvider;
@@ -55,7 +56,7 @@ public class UserStorageProviderResource {
protected RealmModel realm;
- protected RealmAuth auth;
+ protected AdminPermissionEvaluator auth;
protected AdminEventBuilder adminEvent;
@@ -71,12 +72,10 @@ public class UserStorageProviderResource {
@Context
protected HttpHeaders headers;
- public UserStorageProviderResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
+ public UserStorageProviderResource(RealmModel realm, AdminPermissionEvaluator auth, AdminEventBuilder adminEvent) {
this.auth = auth;
this.realm = realm;
this.adminEvent = adminEvent;
-
- auth.init(RealmAuth.Resource.USER);
}
/**
@@ -94,7 +93,7 @@ public class UserStorageProviderResource {
@Produces(MediaType.APPLICATION_JSON)
public SynchronizationResult syncUsers(@PathParam("id") String id,
@QueryParam("action") String action) {
- auth.requireManage();
+ auth.users().requireManage();
ComponentModel model = realm.getComponent(id);
if (model == null) {
@@ -139,7 +138,7 @@ public class UserStorageProviderResource {
@Path("{id}/remove-imported-users")
@NoCache
public void removeImportedUsers(@PathParam("id") String id) {
- auth.requireManage();
+ auth.users().requireManage();
ComponentModel model = realm.getComponent(id);
if (model == null) {
@@ -162,7 +161,7 @@ public class UserStorageProviderResource {
@Path("{id}/unlink-users")
@NoCache
public void unlinkUsers(@PathParam("id") String id) {
- auth.requireManage();
+ auth.users().requireManage();
ComponentModel model = realm.getComponent(id);
if (model == null) {
@@ -187,7 +186,7 @@ public class UserStorageProviderResource {
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public SynchronizationResult syncMapperData(@PathParam("parentId") String parentId, @PathParam("id") String mapperId, @QueryParam("direction") String direction) {
- auth.requireManage();
+ auth.users().requireManage();
ComponentModel parentModel = realm.getComponent(parentId);
if (parentModel == null) throw new NotFoundException("Parent model not found");
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java
index e001f60..b6bdc4c 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java
@@ -19,8 +19,9 @@ package org.keycloak.testsuite.admin;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.admin.client.Keycloak;
-import org.keycloak.admin.client.resource.RealmResource;
-import org.keycloak.authorization.admin.permissions.MgmtPermissions;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionManagement;
+import org.keycloak.services.resources.admin.permissions.AdminPermissions;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.models.AdminRoles;
@@ -35,24 +36,14 @@ import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
-import org.keycloak.representations.idm.authorization.DecisionEffect;
import org.keycloak.representations.idm.authorization.DecisionStrategy;
-import org.keycloak.representations.idm.authorization.PolicyEvaluationRequest;
-import org.keycloak.representations.idm.authorization.PolicyEvaluationResponse;
import org.keycloak.testsuite.AbstractKeycloakTest;
-import org.keycloak.testsuite.arquillian.AuthServerTestEnricher;
import org.keycloak.testsuite.util.AdminClientUtil;
import javax.ws.rs.ClientErrorException;
-import javax.ws.rs.ForbiddenException;
-import javax.ws.rs.core.Response;
-import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
-import java.util.Set;
-import static org.keycloak.testsuite.auth.page.AuthRealm.ADMIN;
-import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER;
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
/**
@@ -73,7 +64,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
public static void setupPolices(KeycloakSession session) {
RealmModel realm = session.realms().getRealmByName(TEST);
- MgmtPermissions permissions = new MgmtPermissions(session, realm);
+ AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
RoleModel realmRole = realm.addRole("realm-role");
RoleModel realmRole2 = realm.addRole("realm-role2");
ClientModel client1 = realm.addClient("role-namespace");
@@ -110,7 +101,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
// setup Users manage policies
{
permissions.users().setPermissionsEnabled(true);
- ResourceServer server = permissions.users().resourceServer();
+ ResourceServer server = permissions.realmResourceServer();
Policy managerPolicy = permissions.roles().rolePolicy(server, managerRole);
Policy permission = permissions.users().managePermission();
permission.addAssociatedPolicy(managerPolicy);
@@ -177,9 +168,8 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
// test authorized
{
UserModel user = session.users().getUserByUsername("authorized", realm);
- MgmtPermissions permissionsForAdmin = new MgmtPermissions(session, realm);
- permissionsForAdmin.setIdentity(user);
- Assert.assertTrue(permissionsForAdmin.users().canManage(user));
+ AdminPermissionEvaluator permissionsForAdmin = AdminPermissions.evaluator(session, realm, realm, user);
+ Assert.assertTrue(permissionsForAdmin.users().canManage());
Assert.assertTrue(permissionsForAdmin.roles().canMapRole(realmRole));
Assert.assertTrue(permissionsForAdmin.roles().canMapRole(realmRole2));
Assert.assertTrue(permissionsForAdmin.roles().canMapRole(clientRole));
@@ -187,9 +177,8 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
// test composite role
{
UserModel user = session.users().getUserByUsername("authorizedComposite", realm);
- MgmtPermissions permissionsForAdmin = new MgmtPermissions(session, realm);
- permissionsForAdmin.setIdentity(user);
- Assert.assertTrue(permissionsForAdmin.users().canManage(user));
+ AdminPermissionEvaluator permissionsForAdmin = AdminPermissions.evaluator(session, realm, realm, user);
+ Assert.assertTrue(permissionsForAdmin.users().canManage());
Assert.assertTrue(permissionsForAdmin.roles().canMapRole(realmRole));
Assert.assertTrue(permissionsForAdmin.roles().canMapRole(realmRole2));
Assert.assertTrue(permissionsForAdmin.roles().canMapRole(clientRole));
@@ -198,9 +187,8 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
// test unauthorized
{
UserModel user = session.users().getUserByUsername("unauthorized", realm);
- MgmtPermissions permissionsForAdmin = new MgmtPermissions(session, realm);
- permissionsForAdmin.setIdentity(user);
- Assert.assertFalse(permissionsForAdmin.users().canManage(user));
+ AdminPermissionEvaluator permissionsForAdmin = AdminPermissions.evaluator(session, realm, realm, user);
+ Assert.assertFalse(permissionsForAdmin.users().canManage());
Assert.assertFalse(permissionsForAdmin.roles().canMapRole(realmRole));
Assert.assertFalse(permissionsForAdmin.roles().canMapRole(clientRole));
@@ -210,9 +198,8 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
// test unauthorized mapper
{
UserModel user = session.users().getUserByUsername("unauthorizedMapper", realm);
- MgmtPermissions permissionsForAdmin = new MgmtPermissions(session, realm);
- permissionsForAdmin.setIdentity(user);
- Assert.assertTrue(permissionsForAdmin.users().canManage(user));
+ AdminPermissionEvaluator permissionsForAdmin = AdminPermissions.evaluator(session, realm, realm, user);
+ Assert.assertTrue(permissionsForAdmin.users().canManage());
Assert.assertFalse(permissionsForAdmin.roles().canMapRole(realmRole));
Assert.assertFalse(permissionsForAdmin.roles().canMapRole(clientRole));
// will result to true because realmRole2 does not have any policies attached to this permission
@@ -391,6 +378,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
}
// testRestEvaluationMasterRealm
// testRestEvaluationMasterAdminTestRealm
+ // test role deletion that it cleans up authz objects
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/PermissionsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/PermissionsTest.java
index 531157d..e502ffa 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/PermissionsTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/PermissionsTest.java
@@ -51,7 +51,7 @@ import org.keycloak.representations.idm.authorization.PolicyRepresentation;
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
-import org.keycloak.services.resources.admin.RealmAuth.Resource;
+import org.keycloak.services.resources.admin.AdminAuth.Resource;
import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.arquillian.AuthServerTestEnricher;
@@ -77,8 +77,8 @@ import java.util.concurrent.atomic.AtomicReference;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
-import static org.keycloak.services.resources.admin.RealmAuth.Resource.AUTHORIZATION;
-import static org.keycloak.services.resources.admin.RealmAuth.Resource.CLIENT;
+import static org.keycloak.services.resources.admin.AdminAuth.Resource.AUTHORIZATION;
+import static org.keycloak.services.resources.admin.AdminAuth.Resource.CLIENT;
import org.keycloak.testsuite.ProfileAssume;
/**
@@ -313,11 +313,18 @@ public class PermissionsTest extends AbstractKeycloakTest {
realm.removeDefaultGroup("nosuch");
}
}, Resource.REALM, true);
+ GroupRepresentation newGroup = new GroupRepresentation();
+ newGroup.setName("sample");
+ adminClient.realm(REALM_NAME).groups().add(newGroup);
+ GroupRepresentation group = adminClient.realms().realm(REALM_NAME).getGroupByPath("sample");
+
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.getGroupByPath("nosuch");
+ realm.getGroupByPath("sample");
}
- }, Resource.REALM, false);
+ }, Resource.USER, false);
+
+ adminClient.realms().realm(REALM_NAME).groups().group(group.getId()).remove();
invoke(new InvocationWithResponse() {
public void invoke(RealmResource realm, AtomicReference<Response> response) {
@@ -954,6 +961,10 @@ public class PermissionsTest extends AbstractKeycloakTest {
@Test
public void roles() {
+ RoleRepresentation newRole = new RoleRepresentation();
+ newRole.setName("sample-role");
+ adminClient.realm(REALM_NAME).roles().create(newRole);
+
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.roles().list();
@@ -961,12 +972,12 @@ public class PermissionsTest extends AbstractKeycloakTest {
}, Resource.REALM, false, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.roles().get("nosuch").toRepresentation();
+ realm.roles().get("sample-role").toRepresentation();
}
}, Resource.REALM, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.roles().get("nosuch").update(new RoleRepresentation());
+ realm.roles().get("sample-role").update(newRole);
}
}, Resource.REALM, true);
invoke(new Invocation() {
@@ -976,39 +987,42 @@ public class PermissionsTest extends AbstractKeycloakTest {
}, Resource.REALM, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.roles().deleteRole("nosuch");
+ realm.roles().deleteRole("sample-role");
+ // need to recreate for other tests
+ realm.roles().create(newRole);
}
}, Resource.REALM, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.roles().get("nosuch").getRoleComposites();
+ realm.roles().get("sample-role").getRoleComposites();
}
}, Resource.REALM, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.roles().get("nosuch").addComposites(Collections.<RoleRepresentation>emptyList());
+ realm.roles().get("sample-role").addComposites(Collections.<RoleRepresentation>emptyList());
}
}, Resource.REALM, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.roles().get("nosuch").deleteComposites(Collections.<RoleRepresentation>emptyList());
+ realm.roles().get("sample-role").deleteComposites(Collections.<RoleRepresentation>emptyList());
}
}, Resource.REALM, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.roles().get("nosuch").getRoleComposites();
+ realm.roles().get("sample-role").getRoleComposites();
}
}, Resource.REALM, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.roles().get("nosuch").getRealmRoleComposites();
+ realm.roles().get("sample-role").getRealmRoleComposites();
}
}, Resource.REALM, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.roles().get("nosuch").getClientRoleComposites("nosuch");
+ realm.roles().get("sample-role").getClientRoleComposites("nosuch");
}
}, Resource.REALM, false);
+ adminClient.realms().realm(REALM_NAME).roles().deleteRole("sample-role");
}
@Test
@@ -1175,51 +1189,61 @@ public class PermissionsTest extends AbstractKeycloakTest {
@Test
public void rolesById() {
+ RoleRepresentation newRole = new RoleRepresentation();
+ newRole.setName("role-by-id");
+ adminClient.realm(REALM_NAME).roles().create(newRole);
+ RoleRepresentation role = adminClient.realm(REALM_NAME).roles().get("role-by-id").toRepresentation();
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.rolesById().getRole("nosuch");
+ realm.rolesById().getRole(role.getId());
}
}, Resource.REALM, false, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.rolesById().updateRole("nosuch", new RoleRepresentation());
+ realm.rolesById().updateRole(role.getId(), role);
}
}, Resource.REALM, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.rolesById().deleteRole("nosuch");
+ realm.rolesById().deleteRole(role.getId());
+ // need to recreate for other tests
+ realm.roles().create(newRole);
+ RoleRepresentation temp = realm.roles().get("role-by-id").toRepresentation();
+ role.setId(temp.getId());
}
}, Resource.REALM, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.rolesById().getRoleComposites("nosuch");
+ realm.rolesById().getRoleComposites(role.getId());
}
}, Resource.REALM, false, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.rolesById().addComposites("nosuch", Collections.<RoleRepresentation>emptyList());
+ realm.rolesById().addComposites(role.getId(), Collections.<RoleRepresentation>emptyList());
}
}, Resource.REALM, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.rolesById().deleteComposites("nosuch", Collections.<RoleRepresentation>emptyList());
+ realm.rolesById().deleteComposites(role.getId(), Collections.<RoleRepresentation>emptyList());
}
}, Resource.REALM, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.rolesById().getRoleComposites("nosuch");
+ realm.rolesById().getRoleComposites(role.getId());
}
}, Resource.REALM, false, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.rolesById().getRealmRoleComposites("nosuch");
+ realm.rolesById().getRealmRoleComposites(role.getId());
}
}, Resource.REALM, false, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.rolesById().getClientRoleComposites("nosuch", "nosuch");
+ realm.rolesById().getClientRoleComposites(role.getId(), "nosuch");
}
}, Resource.REALM, false, true);
+
+ adminClient.realm(REALM_NAME).roles().deleteRole("role-by-id");
}
@Test
@@ -1237,85 +1261,95 @@ public class PermissionsTest extends AbstractKeycloakTest {
}
}, Resource.USER, true);
+ GroupRepresentation group = adminClient.realms().realm(REALM_NAME).getGroupByPath("mygroup");
+ ClientRepresentation realmAccessClient = adminClient.realms().realm(REALM_NAME).clients().findByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID).get(0);
+
+
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.groups().group("nosuch").toRepresentation();
+ realm.groups().group(group.getId()).toRepresentation();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.groups().group("nosuch").update(new GroupRepresentation());
+ realm.groups().group(group.getId()).update(group);
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.groups().group("nosuch").remove();
- }
- }, Resource.USER, true);
- invoke(new Invocation() {
- public void invoke(RealmResource realm) {
- realm.groups().group("nosuch").members(0, 100);
+ realm.groups().group(group.getId()).members(0, 100);
}
}, Resource.USER, false);
invoke(new InvocationWithResponse() {
public void invoke(RealmResource realm, AtomicReference<Response> response) {
- response.set(realm.groups().group("nosuch").subGroup(new GroupRepresentation()));
+ GroupRepresentation subgroup = new GroupRepresentation();
+ subgroup.setName("sub");
+ response.set(realm.groups().group(group.getId()).subGroup(subgroup));
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.groups().group("nosuch").roles().getAll();
+ realm.groups().group(group.getId()).roles().getAll();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.groups().group("nosuch").roles().realmLevel().listAll();
+ realm.groups().group(group.getId()).roles().realmLevel().listAll();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.groups().group("nosuch").roles().realmLevel().listEffective();
+ realm.groups().group(group.getId()).roles().realmLevel().listEffective();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.groups().group("nosuch").roles().realmLevel().listAvailable();
+ realm.groups().group(group.getId()).roles().realmLevel().listAvailable();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.groups().group("nosuch").roles().realmLevel().add(Collections.<RoleRepresentation>emptyList());
+ realm.groups().group(group.getId()).roles().realmLevel().add(Collections.<RoleRepresentation>emptyList());
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.groups().group("nosuch").roles().realmLevel().remove(Collections.<RoleRepresentation>emptyList());
+ realm.groups().group(group.getId()).roles().realmLevel().remove(Collections.<RoleRepresentation>emptyList());
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.groups().group("nosuch").roles().clientLevel("nosuch").listAll();
+ realm.groups().group(group.getId()).roles().clientLevel(realmAccessClient.getId()).listAll();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.groups().group("nosuch").roles().clientLevel("nosuch").listEffective();
+ realm.groups().group(group.getId()).roles().clientLevel(realmAccessClient.getId()).listEffective();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.groups().group("nosuch").roles().clientLevel("nosuch").listAvailable();
+ realm.groups().group(group.getId()).roles().clientLevel(realmAccessClient.getId()).listAvailable();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.groups().group("nosuch").roles().clientLevel("nosuch").add(Collections.<RoleRepresentation>emptyList());
+ realm.groups().group(group.getId()).roles().clientLevel(realmAccessClient.getId()).add(Collections.<RoleRepresentation>emptyList());
+ }
+ }, Resource.USER, true);
+ invoke(new Invocation() {
+ public void invoke(RealmResource realm) {
+ realm.groups().group(group.getId()).roles().clientLevel(realmAccessClient.getId()).remove(Collections.<RoleRepresentation>emptyList());
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.groups().group("nosuch").roles().clientLevel("nosuch").remove(Collections.<RoleRepresentation>emptyList());
+ realm.groups().group(group.getId()).remove();
+ group.setId(null);
+ realm.groups().add(group);
+ GroupRepresentation temp = realm.getGroupByPath("mygroup");
+ group.setId(temp.getId());
}
}, Resource.USER, true);
}
@@ -1323,176 +1357,181 @@ public class PermissionsTest extends AbstractKeycloakTest {
// Permissions for impersonation tested in ImpersonationTest
@Test
public void users() {
- invoke(new Invocation() {
- public void invoke(RealmResource realm) {
- realm.users().get("nosuch").toRepresentation();
- }
- }, Resource.USER, false);
invoke(new InvocationWithResponse() {
public void invoke(RealmResource realm, AtomicReference<Response> response) {
response.set(realm.users().create(UserBuilder.create().username("testuser").build()));
}
}, Resource.USER, true);
+ UserRepresentation user = adminClient.realms().realm(REALM_NAME).users().search("testUser").get(0);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").update(UserBuilder.create().enabled(true).build());
+ realm.users().get(user.getId()).remove();
+ realm.users().create(user);
+ UserRepresentation temp = realm.users().search("testUser").get(0);
+ user.setId(temp.getId());
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().search("foo", 0, 1);
+ realm.users().get(user.getId()).toRepresentation();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
+ realm.users().get(user.getId()).update(user);
+ }
+ }, Resource.USER, true);
+ invoke(new Invocation() {
+ public void invoke(RealmResource realm) {
realm.users().count();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").getUserSessions();
+ realm.users().get(user.getId()).getUserSessions();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").getOfflineSessions("nosuch");
+ realm.users().get(user.getId()).getOfflineSessions("nosuch");
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").getFederatedIdentity();
+ realm.users().get(user.getId()).getFederatedIdentity();
}
}, Resource.USER, false);
invoke(new InvocationWithResponse() {
public void invoke(RealmResource realm, AtomicReference<Response> response) {
response.set(realm.users()
- .get("nosuch")
+ .get(user.getId())
.addFederatedIdentity("nosuch",
FederatedIdentityBuilder.create().identityProvider("nosuch").userId("nosuch").userName("nosuch").build()));
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").removeFederatedIdentity("nosuch");
+ realm.users().get(user.getId()).removeFederatedIdentity("nosuch");
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").getConsents();
+ realm.users().get(user.getId()).getConsents();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").revokeConsent("testclient");
+ realm.users().get(user.getId()).revokeConsent("testclient");
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").logout();
+ realm.users().get(user.getId()).logout();
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").remove();
+ realm.users().get(user.getId()).resetPassword(CredentialBuilder.create().password("password").build());
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").resetPassword(CredentialBuilder.create().password("password").build());
+ realm.users().get(user.getId()).removeTotp();
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").removeTotp();
+ realm.users().get(user.getId()).resetPasswordEmail();
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").resetPasswordEmail();
+ realm.users().get(user.getId()).executeActionsEmail(Collections.<String>emptyList());
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").executeActionsEmail(Collections.<String>emptyList());
+ realm.users().get(user.getId()).sendVerifyEmail();
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").sendVerifyEmail();
- }
- }, Resource.USER, true);
- invoke(new Invocation() {
- public void invoke(RealmResource realm) {
- realm.users().get("nosuch").groups();
+ realm.users().get(user.getId()).groups();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").leaveGroup("nosuch");
+ realm.users().get(user.getId()).leaveGroup("nosuch");
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").joinGroup("nosuch");
+ realm.users().get(user.getId()).joinGroup("nosuch");
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").roles().getAll();
+ realm.users().get(user.getId()).roles().getAll();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").roles().realmLevel().listAll();
+ realm.users().get(user.getId()).roles().realmLevel().listAll();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").roles().realmLevel().listAvailable();
+ realm.users().get(user.getId()).roles().realmLevel().listAvailable();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").roles().realmLevel().listEffective();
+ realm.users().get(user.getId()).roles().realmLevel().listEffective();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").roles().realmLevel().add(Collections.<RoleRepresentation>emptyList());
+ realm.users().get(user.getId()).roles().realmLevel().add(Collections.<RoleRepresentation>emptyList());
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").roles().realmLevel().remove(Collections.<RoleRepresentation>emptyList());
+ realm.users().get(user.getId()).roles().realmLevel().remove(Collections.<RoleRepresentation>emptyList());
}
}, Resource.USER, true);
+ ClientRepresentation realmAccessClient = adminClient.realms().realm(REALM_NAME).clients().findByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID).get(0);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").roles().clientLevel("nosuch").listAll();
+ realm.users().get(user.getId()).roles().clientLevel(realmAccessClient.getId()).listAll();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").roles().clientLevel("nosuch").listAvailable();
+ realm.users().get(user.getId()).roles().clientLevel(realmAccessClient.getId()).listAvailable();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").roles().clientLevel("nosuch").listEffective();
+ realm.users().get(user.getId()).roles().clientLevel(realmAccessClient.getId()).listEffective();
}
}, Resource.USER, false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").roles().clientLevel("nosuch").add(Collections.<RoleRepresentation>emptyList());
+ realm.users().get(user.getId()).roles().clientLevel(realmAccessClient.getId()).add(Collections.<RoleRepresentation>emptyList());
}
}, Resource.USER, true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
- realm.users().get("nosuch").roles().clientLevel("nosuch").remove(Collections.<RoleRepresentation>emptyList());
+ realm.users().get(user.getId()).roles().clientLevel(realmAccessClient.getId()).remove(Collections.<RoleRepresentation>emptyList());
}
}, Resource.USER, true);
+ invoke(new Invocation() {
+ public void invoke(RealmResource realm) {
+ realm.users().search("foo", 0, 1);
+ }
+ }, Resource.USER, false);
}
@Test