fix(portal-bff): align admin entra role name with Portal.Admin #145
Reference in New Issue
Block a user
Delete Branch "fix/portal-bff-portal-admin-role-name"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
The
AdminRoleGuardwas matching on the literal'admin', but the Entra app registration declares the admin app role withvalue: "Portal.Admin". End result: an authenticated user with the role assigned in Entra still landed withroles: []in their session (claim simply not present in the id token), and every request to/api/admin/auditand/api/admin/usersreturned a 403.Caught manually in the portal-admin SPA: login succeeded, sidebar links to "Audit log" / "User list" returned 403. The
/api/admin/auth/meself-test confirmed the missing claim was the cause.What lands
Constant value — single source of truth
apps/portal-bff/src/admin/admin-role.guard.ts:18:admin-role.guard.spec.tsalready importsADMIN_ROLEfrom the source rather than hardcoding the literal, so the guard contract spec rolls through unchanged. The fixtures elsewhere (auth.service.spec.ts,admin.controller.spec.ts,admin-auth.controller.spec.ts,require-mfa.guard.spec.ts) keeproles: ['admin']as fixture data — those tests exercise the extraction / serialization pipeline, which is role-value-agnostic; touching them would be incidental cleanup with no behaviour signal.Doc-comment refresh
Inline references to the role name updated so future readers don't grep
'admin'and find a phantom value:admin-role.guard.ts— class doc-block (3 mentions).admin.controller.ts— class doc-block + inline guard-contract comment.audit.service.ts—adminAccessDenieddoc-block (2 mentions).Documentation
docs/decisions/0020-portal-admin-app.md— 5 references to the role across §"How is admin access enforced", §"Auth — same Entra ID …", and the Consequences §.docs/architecture.md— note next to the C4 container diagram describing the admin entry gate.CLAUDE.md— "Admin application" project rule.Notes for the reviewer
Portal.Adminrather thanadmin? Operator's call on the Entra side. The<Application>.<Role>namespace is the conventional Entra App Role pattern when the directory may host roles for multiple applications, andadminalone is ambiguous in a directory shared across products.roles: [](claim absent) — they'll naturally pick up the correct value on next sign-in. No persisted data references the old value.Test plan
pnpm nx test portal-bff— 396 specs pass, unchanged frommain. TheAdminRoleGuardcontract spec (covers 401-on-no-session, 403-on-missing-role + audit emission, pass-through-on-role-present) importsADMIN_ROLEand re-exercises with the new value.pnpm exec nx affected -t format:check lint test build --base=origin/main— clean.value: "Portal.Admin"+ assignment to the test user. Once both exist: sign out + sign in on portal-admin, hit/api/admin/auth/meand confirmroles: ["Portal.Admin"], then click "Audit log" + "User list" and confirm both render. Anadmin.access_deniedrow inaudit.eventsis the negative-test signal (still emitted for any user without the role).