{"record":{"id":"32fd625bcc35eeae","repo":"fullstackhero/dotnet-starter-kit","slug":"only-administrators-can-change-user-status","errorCode":null,"errorMessage":"Only administrators can change user status.","messagePattern":"Only administrators can change user status\\.","errorType":"exception","errorClass":"ForbiddenException","httpStatus":403,"severity":"error","filePath":"src/Modules/Identity/Modules.Identity/Services/UserStatusService.cs","lineNumber":81,"sourceCode":"            .FirstOrDefaultAsync(cancellationToken)\n            ?? throw new NotFoundException(\"User Not Found.\");\n\n        return new ToggleStatusContext(\n            ActorId: actorId,\n            Actor: actor,\n            TargetUser: targetUser,\n            ActivateUser: activateUser,\n            TenantId: multiTenantContextAccessor?.MultiTenantContext?.TenantInfo?.Id);\n    }\n\n    private async Task ValidateTogglePermissionsAsync(\n        ToggleStatusContext context,\n        CancellationToken cancellationToken)\n    {\n        if (!await userManager.IsInRoleAsync(context.Actor, RoleConstants.Admin))\n        {\n            await AuditPolicyFailureAsync(context, \"ActorNotAdmin\", cancellationToken);\n            throw new ForbiddenException(\"Only administrators can change user status.\");\n        }\n\n        if (!context.ActivateUser && context.ActorId.ToString() == context.TargetUser.Id)\n        {\n            await AuditPolicyFailureAsync(context, \"SelfDeactivationBlocked\", cancellationToken);\n            throw new CustomException(\"Users cannot deactivate themselves.\", Array.Empty<string>(), HttpStatusCode.BadRequest);\n        }\n\n        if (!context.ActivateUser && await userManager.IsInRoleAsync(context.TargetUser, RoleConstants.Admin))\n        {\n            await AuditPolicyFailureAsync(context, \"AdminDeactivationBlocked\", cancellationToken);\n            throw new CustomException(\"Administrators cannot be deactivated.\", Array.Empty<string>(), HttpStatusCode.BadRequest);\n        }\n\n        if (!context.ActivateUser)\n        {\n            await EnsureMinimumActiveAdminsAsync(context, cancellationToken);\n        }","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/fullstackhero/dotnet-starter-kit/blob/3f2959e683e9f83f13e55e1678c9119f63c7e8e5/src/Modules/Identity/Modules.Identity/Services/UserStatusService.cs#L63-L99","documentation":"UserStatusService.ValidateTogglePermissionsAsync throws ForbiddenException(\"Only administrators can change user status.\") when the authenticated actor is not a member of the Admin role. The failure is first recorded via AuditPolicyFailureAsync before the 403 is raised.","triggerScenarios":"Any non-admin user calling the toggle-user-status endpoint; an admin whose role assignment was removed before the call; a token issued before a role revocation still carrying the user through.","commonSituations":"Ordinary users hitting admin-only endpoints from a modified UI; permission config drift where the Admin role constant changed; users with custom roles assumed to have admin rights.","solutions":["Grant the actor the Admin role (assign via the identity module roles endpoint or seed) if they legitimately need this capability.","Sign in as a user with the Admin role instead.","Verify role assignment: check AspNetUserRoles/AspNetRoles for the actor and RoleConstants.Admin.","Re-login to refresh the JWT claims if the role was recently granted."],"exampleFix":"// before (acting as non-admin)\nawait mediator.Send(new ToggleUserStatusCommand { UserId = targetId });\n// after (assert first)\nif (!await userManager.IsInRoleAsync(currentUser, RoleConstants.Admin))\n    throw new ForbiddenException(\"Admin role required.\");\nawait mediator.Send(new ToggleUserStatusCommand { UserId = targetId });","handlingStrategy":"validation","validationCode":"var isAdmin = await userManager.IsInRoleAsync(actor, RoleConstants.Admin);\nif (!isAdmin) return Result.Forbidden(\"Admin role required.\");","typeGuard":null,"tryCatchPattern":"try { ... }\ncatch (ForbiddenException) { notifyUser(\"You need administrator rights for this action\"); }","preventionTips":["Gate the UI so the toggle action is only shown to admins (RouteGuard/permission check).","Mirror the permission in the frontend permissions catalog.","Test role changes with fresh tokens after granting/revoking roles.","Audit role assignments regularly in production tenants."],"tags":["authorization","rbac","identity","forbidden"],"backgroundTag":"permission-denied","analyzedSha":"3f2959e683e9f83f13e55e1678c9119f63c7e8e5","analyzedAt":"2026-09-15T22:20:53.684Z","contentChangedAt":"2026-09-15T22:20:53.684Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}