mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-10 15:32:05 -03:30
feat(FGAPv2): introduce RESET_PASSWORD scope and evaluation
- Add RESET_PASSWORD to AdminPermissionsSchema.USERS - Require RESET_PASSWORD in UserResource.resetPassword() - Expose canResetPassword()/requireResetPassword() - Implement FGAP v2 deny-overrides + secure-by-default + optional fallback - Include access.resetPassword for Admin Console Closes #41901 Co-authored-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Bagautdino <336373@edu.itmo.ru>
This commit is contained in:
parent
28d3b2dd29
commit
d225bce21f
@ -68,6 +68,8 @@ set of scopes:
|
||||
| *manage-group-membership* | Defines if a realm administrator can assign or unassign users to/from groups. | None
|
||||
| *map-roles* | Defines if a realm administrator can assign or unassign roles to/from users. | None
|
||||
| *impersonate* | Defines if a realm administrator can impersonate other users. | `impersonate-members`
|
||||
| *reset-password* | Defines if a realm administrator can reset user passwords. By default, this scope falls | None
|
||||
back to `manage` scope behavior (configurable via `fgap.v2.resetPassword.fallbackToManageUsers`).
|
||||
|===
|
||||
|
||||
The user resource type has a strong relationship with some of the permissions you can set to groups. Most of the time,
|
||||
|
||||
@ -4,7 +4,22 @@
|
||||
Breaking changes are identified as requiring changes from existing users to their configurations.
|
||||
In minor or patch releases we will only do breaking changes to fix bugs.
|
||||
|
||||
=== <TODO>
|
||||
=== Fine-grained admin permissions: RESET_PASSWORD scope for Users
|
||||
|
||||
A new `reset-password` scope has been added to the Users resource type in Fine-Grained Admin Permissions v2. This scope allows administrators to grant password reset permissions independently from the broader `manage` scope.
|
||||
|
||||
By default, the behavior remains compatible with previous versions through the `fallbackToManageUsers` configuration option, which is set to `true` by default. When this fallback is enabled, password reset permissions will use the existing `manage` scope behavior.
|
||||
|
||||
To enable the new granular password reset permissions, set the configuration option:
|
||||
|
||||
[source]
|
||||
----
|
||||
fgap.v2.resetPassword.fallbackToManageUsers=false
|
||||
----
|
||||
|
||||
When the fallback is disabled, only explicit `reset-password` scope permissions will allow password reset operations, providing more fine-grained control over administrative access.
|
||||
|
||||
For more information about fine-grained admin permissions, see the link:{adminguide_finegrained_link}[{adminguide_finegrained_name}] chapter in the {adminguide_name}.
|
||||
|
||||
// ------------------------ Notable changes ------------------------ //
|
||||
== Notable changes
|
||||
|
||||
@ -42,4 +42,14 @@ public interface Decision<D extends Evaluation> {
|
||||
|
||||
default void onComplete(ResourcePermission permission) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given {@code scope} is associated with any policy processed in this decision.
|
||||
*
|
||||
* @param scope the scope name
|
||||
* @return {@code true} if the scope is associated with a policy. Otherwise, {@code false}.
|
||||
*/
|
||||
default boolean isEvaluated(String scope) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,13 +95,14 @@ public class AdminPermissionsSchema extends AuthorizationSchema {
|
||||
|
||||
// user specific scopes
|
||||
public static final String IMPERSONATE = "impersonate";
|
||||
public static final String RESET_PASSWORD = "reset-password";
|
||||
|
||||
public static final String MANAGE_GROUP_MEMBERSHIP = "manage-group-membership";
|
||||
|
||||
public static final ResourceType CLIENTS = new ResourceType(CLIENTS_RESOURCE_TYPE, Set.of(MANAGE, MAP_ROLES, MAP_ROLES_CLIENT_SCOPE, MAP_ROLES_COMPOSITE, VIEW));
|
||||
public static final ResourceType GROUPS = new ResourceType(GROUPS_RESOURCE_TYPE, Set.of(MANAGE, VIEW, MANAGE_MEMBERSHIP, MANAGE_MEMBERS, VIEW_MEMBERS, IMPERSONATE_MEMBERS));
|
||||
public static final ResourceType ROLES = new ResourceType(ROLES_RESOURCE_TYPE, Set.of(MAP_ROLE, MAP_ROLE_CLIENT_SCOPE, MAP_ROLE_COMPOSITE));
|
||||
public static final ResourceType USERS = new ResourceType(USERS_RESOURCE_TYPE, Set.of(MANAGE, VIEW, IMPERSONATE, MAP_ROLES, MANAGE_GROUP_MEMBERSHIP), Map.of(VIEW, Set.of(VIEW_MEMBERS), MANAGE, Set.of(MANAGE_MEMBERS), IMPERSONATE, Set.of(IMPERSONATE_MEMBERS)), GROUPS.getType());
|
||||
public static final ResourceType USERS = new ResourceType(USERS_RESOURCE_TYPE, Set.of(MANAGE, VIEW, IMPERSONATE, MAP_ROLES, MANAGE_GROUP_MEMBERSHIP, RESET_PASSWORD), Map.of(VIEW, Set.of(VIEW_MEMBERS), MANAGE, Set.of(MANAGE_MEMBERS), IMPERSONATE, Set.of(IMPERSONATE_MEMBERS)), GROUPS.getType());
|
||||
private static final String SKIP_EVALUATION = "kc.authz.fgap.skip";
|
||||
public static final AdminPermissionsSchema SCHEMA = new AdminPermissionsSchema();
|
||||
|
||||
@ -531,4 +532,4 @@ public class AdminPermissionsSchema extends AuthorizationSchema {
|
||||
|
||||
return Boolean.parseBoolean(session.getAttributeOrDefault(SKIP_EVALUATION, Boolean.FALSE.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -55,4 +55,9 @@ class FGAPDecision implements Decision<Evaluation> {
|
||||
public void onComplete(ResourcePermission permission) {
|
||||
decision.onComplete(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEvaluated(String scope) {
|
||||
return decision.isEvaluated(scope);
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,10 +88,16 @@ class IterablePermissionEvaluator implements PermissionEvaluator {
|
||||
|
||||
@Override
|
||||
public Collection<Permission> evaluate(ResourceServer resourceServer, AuthorizationRequest request) {
|
||||
DecisionPermissionCollector decision = getDecision(resourceServer, request, DecisionPermissionCollector.class);
|
||||
return decision.results();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <D extends Decision<?>> D getDecision(ResourceServer resourceServer, AuthorizationRequest request, Class<D> decisionType) {
|
||||
DecisionPermissionCollector decision = new DecisionPermissionCollector(authorizationProvider, resourceServer, request);
|
||||
|
||||
evaluate(decision);
|
||||
|
||||
return decision.results();
|
||||
return decisionType.cast(decision);
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,4 +34,5 @@ public interface PermissionEvaluator {
|
||||
|
||||
<D extends Decision> D evaluate(D decision);
|
||||
Collection<Permission> evaluate(ResourceServer resourceServer, AuthorizationRequest request);
|
||||
<D extends Decision<?>> D getDecision(ResourceServer resourceServer, AuthorizationRequest request, Class<D> decisionType);
|
||||
}
|
||||
|
||||
@ -60,10 +60,16 @@ public class UnboundedPermissionEvaluator implements PermissionEvaluator {
|
||||
|
||||
@Override
|
||||
public Collection<Permission> evaluate(ResourceServer resourceServer, AuthorizationRequest request) {
|
||||
DecisionPermissionCollector decision = getDecision(resourceServer, request, DecisionPermissionCollector.class);
|
||||
return decision.results();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <D extends Decision<?>> D getDecision(ResourceServer resourceServer, AuthorizationRequest request, Class<D> decisionType) {
|
||||
DecisionPermissionCollector decision = new DecisionPermissionCollector(authorizationProvider, resourceServer, request);
|
||||
|
||||
evaluate(decision);
|
||||
|
||||
return decision.results();
|
||||
return decisionType.cast(decision);
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ package org.keycloak.authorization.policy.evaluation;
|
||||
import org.keycloak.authorization.Decision;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.permission.ResourcePermission;
|
||||
import org.keycloak.authorization.policy.evaluation.Result.PolicyResult;
|
||||
import org.keycloak.representations.idm.authorization.DecisionStrategy;
|
||||
|
||||
import java.util.Collection;
|
||||
@ -129,4 +130,19 @@ public abstract class AbstractDecisionCollector implements Decision<Evaluation>
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEvaluated(String scope) {
|
||||
for (Result result : results.values()) {
|
||||
for (PolicyResult policyResult : result.getResults()) {
|
||||
Policy policy = policyResult.getPolicy();
|
||||
|
||||
if (policy.getScopes().stream().anyMatch(s -> s.getName().equals(scope))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -760,7 +760,7 @@ public class UserResource {
|
||||
@APIResponse(responseCode = "500", description = "Internal Server Error", content = @Content(schema = @Schema(implementation = ErrorRepresentation.class)))
|
||||
})
|
||||
public void resetPassword(@Parameter(description = "The representation must contain a rawPassword with the plain-text password") CredentialRepresentation cred) {
|
||||
auth.users().requireManage(user);
|
||||
auth.users().requireResetPassword(user);
|
||||
if (cred == null || cred.getValue() == null) {
|
||||
throw new BadRequestException("No password provided");
|
||||
}
|
||||
@ -1324,4 +1324,4 @@ public class UserResource {
|
||||
this.lifespan = lifespan;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -21,6 +21,7 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.keycloak.authorization.fgap.AdminPermissionsSchema;
|
||||
@ -29,6 +30,7 @@ import org.keycloak.authorization.model.Resource;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.model.ResourceWrapper;
|
||||
import org.keycloak.authorization.permission.ResourcePermission;
|
||||
import org.keycloak.authorization.policy.evaluation.DecisionPermissionCollector;
|
||||
import org.keycloak.authorization.policy.evaluation.EvaluationContext;
|
||||
import org.keycloak.authorization.store.PolicyStore;
|
||||
import org.keycloak.authorization.store.ResourceStore;
|
||||
@ -52,7 +54,37 @@ class FineGrainedAdminPermissionEvaluator {
|
||||
return hasPermission(model.getId(), model.getResourceType(), context, scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there are permissions granted for the given {@code model} and {@code scope}. If
|
||||
* the given {@code scope} is not associated with any permission, the value returned by {@code defaultValue} will
|
||||
* be returned.
|
||||
*
|
||||
* @param model the model
|
||||
* @param context the context
|
||||
* @param scope the scope
|
||||
* @param defaultValue the default value
|
||||
* @return
|
||||
*/
|
||||
boolean hasPermission(ModelRecord model, EvaluationContext context, String scope, Supplier<Boolean> defaultValue) {
|
||||
return hasPermission(model.getId(), model.getResourceType(), context, scope, defaultValue);
|
||||
}
|
||||
|
||||
boolean hasPermission(String modelId, String resourceType, EvaluationContext context, String scope) {
|
||||
return hasPermission(modelId, resourceType, context, scope, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there are permissions granted for the given {@code modelId} and {@code scope}. If
|
||||
* the given {@code scope} is not associated with any permission, the value returned by {@code defaultValue} will
|
||||
* be returned.
|
||||
*
|
||||
* @param modelId the model id
|
||||
* @param context the context
|
||||
* @param scope the scope
|
||||
* @param defaultValue the default value
|
||||
* @return
|
||||
*/
|
||||
boolean hasPermission(String modelId, String resourceType, EvaluationContext context, String scope, Supplier<Boolean> defaultValue) {
|
||||
if (!root.isAdminSameRealm()) {
|
||||
return false;
|
||||
}
|
||||
@ -70,9 +102,10 @@ class FineGrainedAdminPermissionEvaluator {
|
||||
resource = new ResourceWrapper(modelId, modelId, new HashSet<>(resourceTypeResource.getScopes()), server);
|
||||
}
|
||||
|
||||
Collection<Permission> permissions = (context == null) ?
|
||||
root.evaluatePermission(new ResourcePermission(resourceType, resource, resource.getScopes(), server), server) :
|
||||
root.evaluatePermission(new ResourcePermission(resourceType, resource, resource.getScopes(), server), server, context);
|
||||
DecisionPermissionCollector decision = (context == null) ?
|
||||
root.getDecision(new ResourcePermission(resourceType, resource, resource.getScopes(), server), server) :
|
||||
root.getDecision(new ResourcePermission(resourceType, resource, resource.getScopes(), server), server, context);
|
||||
Collection<Permission> permissions = decision.results();
|
||||
|
||||
for (Permission permission : permissions) {
|
||||
if (permission.getResourceId().equals(resource.getId())) {
|
||||
@ -82,6 +115,12 @@ class FineGrainedAdminPermissionEvaluator {
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultValue != null) {
|
||||
if (!decision.isEvaluated(scope)) {
|
||||
return defaultValue.get();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -27,6 +27,7 @@ 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.policy.evaluation.DecisionPermissionCollector;
|
||||
import org.keycloak.authorization.policy.evaluation.EvaluationContext;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.models.AdminRoles;
|
||||
@ -323,11 +324,15 @@ class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManage
|
||||
return evaluatePermission(permission, resourceServer, new DefaultEvaluationContext(identity, session));
|
||||
}
|
||||
|
||||
public Collection<Permission> evaluatePermission(List<ResourcePermission> permission, ResourceServer resourceServer) {
|
||||
return evaluatePermission(permission, resourceServer, new DefaultEvaluationContext(identity, session));
|
||||
public DecisionPermissionCollector getDecision(ResourcePermission permission, ResourceServer resourceServer) {
|
||||
return evaluatePermission(List.of(permission), resourceServer, new DefaultEvaluationContext(identity, session));
|
||||
}
|
||||
|
||||
public Collection<Permission> evaluatePermission(ResourcePermission permission, ResourceServer resourceServer, EvaluationContext context) {
|
||||
return evaluatePermission(Arrays.asList(permission), resourceServer, context).results();
|
||||
}
|
||||
|
||||
public DecisionPermissionCollector getDecision(ResourcePermission permission, ResourceServer resourceServer, EvaluationContext context) {
|
||||
return evaluatePermission(Arrays.asList(permission), resourceServer, context);
|
||||
}
|
||||
|
||||
@ -337,14 +342,14 @@ class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManage
|
||||
}
|
||||
|
||||
public boolean evaluatePermission(Resource resource, ResourceServer resourceServer, EvaluationContext context, Scope... scope) {
|
||||
return !evaluatePermission(Arrays.asList(new ResourcePermission(resource, Arrays.asList(scope), resourceServer)), resourceServer, context).isEmpty();
|
||||
return !evaluatePermission(Arrays.asList(new ResourcePermission(resource, Arrays.asList(scope), resourceServer)), resourceServer, context).results().isEmpty();
|
||||
}
|
||||
|
||||
public Collection<Permission> evaluatePermission(List<ResourcePermission> permissions, ResourceServer resourceServer, EvaluationContext context) {
|
||||
public DecisionPermissionCollector evaluatePermission(List<ResourcePermission> permissions, ResourceServer resourceServer, EvaluationContext context) {
|
||||
RealmModel oldRealm = session.getContext().getRealm();
|
||||
try {
|
||||
session.getContext().setRealm(realm);
|
||||
return authz.evaluators().from(permissions, resourceServer, context).evaluate(resourceServer, null);
|
||||
return authz.evaluators().from(permissions, resourceServer, context).getDecision(resourceServer, null, DecisionPermissionCollector.class);
|
||||
} finally {
|
||||
session.getContext().setRealm(oldRealm);
|
||||
}
|
||||
|
||||
@ -57,6 +57,23 @@ public interface UserPermissionEvaluator {
|
||||
*/
|
||||
boolean canManage(UserModel user);
|
||||
|
||||
/**
|
||||
* Throws ForbiddenException if {@link #canResetPassword(UserModel)} returns {@code false}.
|
||||
*/
|
||||
default void requireResetPassword(UserModel user) {
|
||||
if (!canResetPassword(user)) {
|
||||
throw new jakarta.ws.rs.ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the caller has permission to {@link org.keycloak.authorization.fgap.AdminPermissionsSchema#RESET_PASSWORD}
|
||||
* for the given user. Default implementation falls back to {@link #canManage(UserModel)} for backward compatibility.
|
||||
*/
|
||||
default boolean canResetPassword(UserModel user) {
|
||||
return canManage(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws ForbiddenException if {@link #canQuery()} returns {@code false}.
|
||||
*/
|
||||
@ -158,4 +175,4 @@ public interface UserPermissionEvaluator {
|
||||
boolean isImpersonatable(UserModel user, ClientModel requester);
|
||||
@Deprecated
|
||||
void grantIfNoPermission(boolean grantIfNoPermission);
|
||||
}
|
||||
}
|
||||
@ -434,6 +434,7 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
|
||||
map.put("mapRoles", canMapRoles(user));
|
||||
map.put("manageGroupMembership", canManageGroupMembership(user));
|
||||
map.put("impersonate", canImpersonate(user));
|
||||
map.put("resetPassword", ((UserPermissionEvaluator)this).canResetPassword(user));
|
||||
return map;
|
||||
}
|
||||
|
||||
@ -592,4 +593,4 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
|
||||
if (authz == null) return false;
|
||||
return evaluateHierarchy(user, root.groups()::canViewMembers);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -147,6 +147,24 @@ class UserPermissionsV2 extends UserPermissions {
|
||||
return eval.hasPermission(new UserModelRecord(user), null, AdminPermissionsSchema.MANAGE_GROUP_MEMBERSHIP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canResetPassword(UserModel user) {
|
||||
// admin roles has the precedence over permissions
|
||||
if (root.hasOneAdminRole(AdminRoles.MANAGE_USERS)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return eval.hasPermission(new UserModelRecord(user), null, AdminPermissionsSchema.RESET_PASSWORD,
|
||||
() -> eval.hasPermission(new UserModelRecord(user), null, AdminPermissionsSchema.MANAGE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requireResetPassword(UserModel user) {
|
||||
if (!canResetPassword(user)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
// todo this method should be removed and replaced by canImpersonate(user, client); once V1 is removed
|
||||
@Override
|
||||
public boolean canClientImpersonate(ClientModel client, UserModel user) {
|
||||
|
||||
@ -27,6 +27,7 @@ import static org.keycloak.authorization.fgap.AdminPermissionsSchema.IMPERSONATE
|
||||
import static org.keycloak.authorization.fgap.AdminPermissionsSchema.MANAGE;
|
||||
import static org.keycloak.authorization.fgap.AdminPermissionsSchema.MANAGE_GROUP_MEMBERSHIP;
|
||||
import static org.keycloak.authorization.fgap.AdminPermissionsSchema.MAP_ROLES;
|
||||
import static org.keycloak.authorization.fgap.AdminPermissionsSchema.RESET_PASSWORD;
|
||||
import static org.keycloak.authorization.fgap.AdminPermissionsSchema.VIEW;
|
||||
|
||||
import java.util.List;
|
||||
@ -40,6 +41,7 @@ import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.admin.client.KeycloakBuilder;
|
||||
import org.keycloak.admin.client.resource.UsersResource;
|
||||
import org.keycloak.authorization.fgap.AdminPermissionsSchema;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.GroupRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
@ -424,4 +426,42 @@ public class UserResourceTypeEvaluationTest extends AbstractPermissionTest {
|
||||
fail("Expected Exception wasn't thrown.");
|
||||
} catch (ForbiddenException expected) {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResetPassword() {
|
||||
UserRepresentation myadmin = realm.admin().users().search("myadmin").get(0);
|
||||
UserPolicyRepresentation allowMyAdminPermission = createUserPolicy(realm, client, "Only My Admin User Policy", myadmin.getId());
|
||||
UserPolicyRepresentation notAllowMyAdminPermission = createUserPolicy(Logic.NEGATIVE, realm, client, "Not Allow My Admin User Policy", myadmin.getId());
|
||||
|
||||
// allow my admin to see alice only
|
||||
ScopePermissionRepresentation managePermission = createPermission(client, userAlice.admin().toRepresentation().getId(), usersType, Set.of(VIEW, MANAGE), allowMyAdminPermission);
|
||||
ScopePermissionRepresentation resetPasswordPermission = createPermission(client, userAlice.admin().toRepresentation().getId(), usersType, Set.of(RESET_PASSWORD), notAllowMyAdminPermission);
|
||||
List<UserRepresentation> search = realmAdminClient.realm(realm.getName()).users().search(null, -1, -1);
|
||||
assertEquals(1, search.size());
|
||||
assertEquals(userAlice.getUsername(), search.get(0).getUsername());
|
||||
|
||||
CredentialRepresentation credential = new CredentialRepresentation();
|
||||
credential.setType(CredentialRepresentation.PASSWORD);
|
||||
credential.setValue("password");
|
||||
|
||||
try {
|
||||
UsersResource users = realmAdminClient.realm(realm.getName()).users();
|
||||
users.get(search.get(0).getId()).resetPassword(credential);
|
||||
fail("Expected Exception wasn't thrown.");
|
||||
} catch (ForbiddenException expected) {
|
||||
}
|
||||
|
||||
String permissionId = getScopePermissionsResource(client).findByName(resetPasswordPermission.getName()).getId();
|
||||
getScopePermissionsResource(client).findById(permissionId).remove();
|
||||
createPermission(client, userAlice.admin().toRepresentation().getId(), usersType, Set.of(RESET_PASSWORD), allowMyAdminPermission);
|
||||
|
||||
UsersResource users = realmAdminClient.realm(realm.getName()).users();
|
||||
users.get(search.get(0).getId()).resetPassword(credential);
|
||||
|
||||
permissionId = getScopePermissionsResource(client).findByName(managePermission.getName()).getId();
|
||||
getScopePermissionsResource(client).findById(permissionId).remove();
|
||||
createPermission(client, userAlice.admin().toRepresentation().getId(), usersType, Set.of(VIEW), allowMyAdminPermission);
|
||||
|
||||
users.get(search.get(0).getId()).resetPassword(credential);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user