fix(account): tighten password reset and admin-role assignment - #8063
Merged
Merged
Conversation
Setting another account's password now requires a declared policy: an administrator, or a holder of users_update or device_users_update. Rules on the target then apply: an unknown address is refused, only user 1 may reset user 1, a non-administrator may not reset an administrator or their own account through this route, and a holder of device_users_update alone may reset only a property worker whose permissions are a subset of their own. A request without a principal is refused. The anonymous admin password reset is removed, together with its client route and component. Only an administrator may now create an administrator or promote an account to administrator, and a non-administrator editing their own account may no longer set a password or change their security group there. The Set password action on the users page is shown only to users who may update users. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014Wuv2gtqY9BLMLWBZiBM2Y
There was a problem hiding this comment.
🟡 Changes recommended
Two moderate authorization issues remain in AccountService and AdminService; an unused dependency also remains.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
This PR tightens password-reset and administrator-role authorization across the API and Angular client.
Changes:
- Adds policy- and target-based password-reset restrictions.
- Restricts administrator role assignment and self-account edits.
- Removes the anonymous admin reset flow and updates the UI, localization, and tests.
File summaries
| File | Summary |
|---|---|
eFormAPI/eFormAPI.Web/Startup.cs |
Registers worker account lookup. |
eFormAPI/eFormAPI.Web/Services/WorkerAccountLookup.cs |
Identifies active property workers. |
eFormAPI/eFormAPI.Web/Services/AdminService.cs |
Guards administrator-role assignment and self-edits. Moderate finding: multiple memberships can bypass the intended group-change guard. |
eFormAPI/eFormAPI.Web/Services/AccountService.cs |
Enforces password-reset target rules. Moderate finding: unauthenticated principals are not rejected reliably; nit: unused IDbOptions<ApplicationSettings> remains. |
eFormAPI/eFormAPI.Web/Resources/SharedResource.resx |
Adds English authorization messages. |
eFormAPI/eFormAPI.Web/Resources/SharedResource.da.resx |
Adds Danish authorization messages. |
eFormAPI/eFormAPI.Web/Hosting/Security/AuthServiceCollectionExtensions.cs |
Registers the password-reset policy. |
eFormAPI/eFormAPI.Web/Hosting/Security/AccountPolicies.cs |
Defines password-reset authorization rules. |
eFormAPI/eFormAPI.Web/Controllers/AccountController.cs |
Applies the policy and removes the anonymous reset route. |
eFormAPI/eFormAPI.Web/Abstractions/IWorkerAccountLookup.cs |
Adds the worker lookup abstraction. |
eFormAPI/eFormAPI.Web/Abstractions/IAccountService.cs |
Removes the deleted reset contract. |
eFormAPI/eFormAPI.Web.Integration.Tests/Services/AdminServiceRoleGuardTests.cs |
Tests role and self-edit guards. |
eFormAPI/eFormAPI.Web.Integration.Tests/Services/AccountServiceTests.cs |
Tests password-reset restrictions. |
eFormAPI/eFormAPI.Web.Integration.Tests/Security/AccountPoliciesTests.cs |
Tests policy registration and behavior. |
eform-client/src/app/modules/auth/components/index.ts |
Removes the deleted component export. |
eform-client/src/app/modules/auth/components/auth/reset-admin-password/reset-admin-password.component.ts |
Removes the obsolete component. |
eform-client/src/app/modules/auth/components/auth/reset-admin-password/reset-admin-password.component.html |
Removes the obsolete template. |
eform-client/src/app/modules/auth/components/auth/auth.component.ts |
Removes obsolete route handling. |
eform-client/src/app/modules/auth/auth.routing.ts |
Removes the obsolete client route. |
eform-client/src/app/modules/auth/auth.module.ts |
Removes the obsolete module declaration. |
eform-client/src/app/modules/account-management/components/users/users-page/users-page.component.html |
Restricts password-action visibility. |
eform-client/src/app/components/app.component.ts |
Removes the obsolete route exception. |
eform-client/src/app/common/services/auth/auth.service.ts |
Removes the obsolete API method. |
Review details
Suppressed comments (2)
eFormAPI/eFormAPI.Web/Services/AccountService.cs:72
- The anonymous reset method was the only consumer of
appSettings, but this constructor still injectsIDbOptions<ApplicationSettings>even thoughAccountServiceno longer uses it. Please remove this dependency (and its now-unused using) so the service does not retain an unnecessary coupling or an unread primary-constructor parameter.
IEmailService emailService,
IHttpContextAccessor httpContextAccessor,
IWorkerAccountLookup workerAccountLookup,
IClaimsService claimsService)
eFormAPI/eFormAPI.Web/Services/AccountService.cs:213
HttpContext.Useris normally a non-null anonymousClaimsPrincipaleven when the request has no authenticated identity. With this null-only check, a service call under such a context can reach the device-user branch and reset a live worker (especially if the target has no claims), so the fail-closed rule is not actually enforced. CheckIdentity?.IsAuthenticatedas well.
var caller = httpContextAccessor.HttpContext?.User;
if (caller == null)
{
- Files reviewed: 23/23 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+375
to
+376
| var changingGroup = userRegisterModel.GroupId.HasValue | ||
| && userRegisterModel.GroupId != currentGroupId; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tightens who can set another account's password and who can grant the admin role.
Changes
users_updateordevice_users_update. Then these rules apply to the target account:device_users_updatealone can reset only a property worker whose permissions are a subset of their own.Tests
AccountPoliciesTests,AccountServiceTestsandAdminServiceRoleGuardTests.🤖 Generated with Claude Code
https://claude.ai/code/session_014Wuv2gtqY9BLMLWBZiBM2Y