Skip to content

Authentication architecture: independent proposal and three-way comparison

Outcome in plain English

Keep permissions authoritative in SyRF. A browser session does not need to carry administrator rights. Whether SyRF also needs an OAuth server is a separate topology decision: cookies for browsers and tokens between services can coexist. Removing application-role claims does not require replacing the login system.

An independent agent first designed a solution from only these requirements: Angular, C#/.NET, MongoDB, secure multi-user sign-in, system administrators and project-level authorization. It did not inspect SyRF code, plans or this audit before completing its recommendation. Part A records that proposal in edited, condensed form; Part B applies source evidence afterward. Neither part is implementation approval. Logical collections, roles and timeout values in Part A are proposals, not existing SyRF schemas or defaults.

Read the companion as-built authority audit for the ownership matrix, lifecycle diagram, source-level gaps, role-claim consumer inventory and documentation map. Implementation evidence here uses the same pinned revision, 0026b56a80fe85f1aea0f690663b02663de6899e, not a claim about live deployment. No runtime, account or database changes were made.

The initial targeted client examples below are not the complete search. The subsequent systematic service/client inventory and end-to-end messaging model covers imports, study updates, Quartz, RabbitMQ, S3, email, Google Sheets, helpdesk, realtime delivery, tooling and gated/mothballed paths. It includes safe pinned GitOps evidence and distinguishes configured workloads from observed usage. Use it before deciding whether any OAuth boundary can be removed.

Scope clarification (28 September): the external machine/delegated API discussion was hypothetical and was explicitly withdrawn by Chris. It is not an accepted or planned requirement. The independent browser-only proposal remains the ideal-target recommendation for the actual first-party application scope. Existing real machine workflows and the current-client census remain migration/compatibility evidence, not a product mandate for a separate issuer. Chris subsequently noted potential eventual external systems authenticating as user accounts. That possibility is not committed scope; preserve secure-delegation options (not password sharing) and assess option cost before any irreversible issuer removal. The near-term plan retains developed Identity. See the design and phased implementation plan, plus the dated verification follow-up for runtime broker findings, bounded tests and remaining gaps.

Part A — independent requirements-first proposal

Minimum architecture and assumptions

For one first-party browser application and one API behind one HTTPS origin, use a server-side authentication session referenced by an HttpOnly cookie. Start with a modular ASP.NET Core application, not a separate identity microservice solely to authenticate that browser. Local ASP.NET Core Identity or an external OIDC provider can establish the session. Application-issued access tokens are unnecessary under this assumption. This is the independent architect's synthesis, not a universal prohibition on OAuth.

Microsoft's SPA Identity guidance supports browser cookie authentication and distinguishes its limited built-in bearer facility from a full identity/token service. The IETF's RFC 10017 §7.1 explains that common-domain applications can use cookie sessions without OAuth access tokens, while noting reasons to retain OAuth. Its BFF discussion keeps API tokens server-side; it does not claim to prevent malicious JavaScript from acting through an authenticated browser.

Publication correction: the independent report cited Internet-Draft revision 27. Verification on 27 September found the published RFC 10017, dated August 2026. This document cites that RFC, not the draft as current guidance. Its section heading must not be misread as prohibiting ordinary cookie sessions.

Option Appropriate use Tradeoff
Local Identity + server-side cookie session Default for one first-party application requiring local accounts Operate credential recovery, abuse controls and a compatible Mongo Identity store.
External OIDC login + local session Existing suitable provider or shared sign-in requirement Provider availability, explicit account linking and deprovisioning contracts.
OIDC/OAuth + BFF with server-held tokens Independent protected APIs or delegated downstream access Token storage/refresh, client credentials and additional failure modes; not necessarily a separate proxy deployment.
Browser-held bearer tokens Independent API clients whose requirements justify a public browser OAuth client More portable credentials exposed to JavaScript, plus CORS/storage/refresh concerns; not the default for the first-party app.
Self-contained protected authentication cookie Explicitly accepted invalidation bounds and simpler session operations Revocation/device management still needs deliberate state or validation; embedded mutable permissions become stale.

The assumptions to validate are one public origin, browser-only clients, no independent application SSO requirement, ordinary load and a small project capability matrix. Native/CLI clients, machine integrations, independent applications, required federation or separate API audiences can change the transport choice. Multiple internal processes alone do not prove that browser JavaScript needs access tokens.

flowchart LR
    B[Angular browser] -->|HTTPS session cookie and CSRF header| A[ASP.NET Core application]
    A --> S[Server authentication sessions]
    A --> I[Local Identity or external OIDC login]
    A --> Z[Current authorization policy]
    Z --> M[Mongo: users, status, roles, projects and membership]
    A -. only for independent API boundaries .-> T[Server-held OAuth tokens]
    T --> R[Resource service with its own authorization]

Sources of truth and logical MongoDB model

Keep authentication and application authorization separate responsibilities even if they share one Mongo deployment. Use an immutable application user ID, never email as a foreign key. An Identity ID may equal that ID in a new design; this is not a recommendation to rewrite SyRF's existing mapped IDs.

Logical collection Owner and authoritative fields Constraints
identityAccounts Identity manager: local password verifier, normalized login, verified contact, MFA/recovery, lockout and security/concurrency stamps Library-controlled; no credential copies in application profile or project data. External credentials stay at their provider.
externalIdentities Account-linking component: validated issuer + subject → application user ID Unique pair; authenticated explicit linking, not automatic email merging.
appUsers Application account service: profile, active/suspended/closed status, site roles, security generation and document version No client-controlled privilege/status fields; ordinary users need no administrator grant.
projects and projectMemberships Project service: project state/policy; user/project membership, role, active status and version Unique user/project membership; no competing membership authority. Embedding versus separate collections is a physical-design choice.
authSessions Session service: random ticket reference, user ID, captured security generation, assurance/time, idle/absolute expiry, revocation and device metadata Shared across replicas; protect stored tickets, index user/expiry, check expiry on each use.
securityAuditEvents Restricted append-only writer: actor, target, operation, result, time, reason and grant changes No credentials or session secrets; explicit retention.
Invitations and outbox, when needed Enrollment/delivery services: single-use invitation digest/expiry/proposed grant; versioned durable events Atomic consumption and idempotent delivery; not a second grant source.

OpenID Connect §5.7 identifies issuer and subject as stable identity keys, unlike mutable profile claims. Microsoft's custom-store guidance separates Identity managers from persistence; MongoDB needs a compatible store, not an assumed EF default. Verify normalized uniqueness, concurrent updates, security stamps, lockout counters, MFA and recovery in the chosen adapter. MongoDB unique indexes enforce uniqueness under races; TTL cleanup is asynchronous, so record expiry must be enforced independently of deletion.

Sign-in, policy and browser contract

  1. Local login uses maintained Identity credential/MFA/recovery facilities. External login uses validated OIDC middleware and explicit enrollment/linking. Authentication does not confer project membership.
  2. After admission checks, create a fresh server session bound to the user and security generation. Each authenticated operation checks session expiry/revocation, current application status and the applicable permission. Credential lockout, application suspension and token/session revocation are distinct.
  3. Resolve the resource's actual stored project, then authorize the operation. Constrain lists, counts, search and exports before disclosure; check every batch target. Recheck queued work before execution and delivery. Downloads need current checks or an explicitly bounded pre-signed-link exception.
  4. Site administration is separate from project access. Define membership/capability rules and any audited support exception explicitly. Do not give administrators unrestricted project content by accident.
  5. Use dedicated grant/revoke/status commands with validated DTOs, authorized grantors and audit. Bootstrap the first administrator through a controlled one-time procedure. Prevent ordinary profile writes from assigning roles; define last-admin/last-manager invariants only where product policy needs them.

These checks follow OWASP's authorization principles of least privilege, default denial and server-side checks on every request. ASP.NET Core's resource handlers can evaluate AuthorizeAsync(user, resource, operation) after loading the resource; a broad authentication attribute is insufficient. Centralize capability mapping instead of scattering role-name comparisons.

Expose current display capabilities through /api/me and project-specific responses, for example siteCapabilities: ["users.manage"] and project.capabilities: ["project.read"], with a policy revision where useful. Angular uses these for navigation and refreshes them after changes or refusals. The backend never accepts a posted capability list as proof. Use consistent 401/403 responses and deliberate 404 concealment, not unexpected HTML login redirects. Do not return every membership at login.

Freshness, concurrency and failure contract

Start with authoritative session/user/membership reads and request-scoped memoization only. Role grants are not trusted long-lived cookie or token claims. Read consistency and replica selection must support the promised cutoff; “no cache” alone does not prove immediate distributed revocation.

Independent proposal Qualification before adoption
30-minute idle and 12-hour absolute session expiry Proposed starting values, not framework defaults; background polling must not silently extend activity forever.
Strong authentication within 5 minutes for sensitive administration Product/risk decision; design recovery alongside MFA.
Revoke one session, or increment user security generation to invalidate all Distinguish device logout, account compromise and provider SSO logout; reject copied cookies.
Each newly authorized operation observes committed role removal/suspension Define consistency, ordering and in-flight work; cannot retract delivered bytes.
If later needed, up to 30-second positive cache for ordinary reads This relaxes immediate revocation and is not compatible with SyRF's accepted R1 without revisiting that decision. Privileged operations bypass it.
Conditional OAuth access tokens: proposed five-minute expiry Lifetime alone cannot meet immediate permission-removal requirements.
Realtime revalidation at most every 30 seconds Housekeeping bound only; protected delivery needs current checks if immediate cutoff is promised.

For sensitive writes that must serialize against revocation, use an authorization-version fence changed by both operations within the relevant transaction. A snapshot read alone is not a serialization guarantee. MongoDB atomicity guidance supports expected-value updates and multi-document transactions. Commit audit/outbox with security changes when losing those records would violate the contract. Restore procedures must invalidate restored sessions and prevent old grants silently returning.

Microsoft cookie guidance requires deliberate backend-change validation. A framework implementation can use CookieAuthenticationOptions.SessionStore and an ITicketStore; this is authentication state, not general ASP.NET session state. This is a proposed implementation seam, not a claim that SyRF's custom BFF store already uses that interface. SignalR caches the connection principal; recheck hub operations and protected delivery, and invalidate subscriptions when permissions change.

Session/authorization-store outages must deny protected operations with a controlled service error, not allow access from stale administrator claims. External-provider outage behavior depends on the chosen local-session reauthentication policy. Share protected Data Protection keys and session storage across replicas; test deployment, rotation and restore, as described in Microsoft's web-farm guidance. Measure indexed lookup cost before adding another cache or service. Mongo session storage is an option, not a reason to replace an already suitable Redis/Valkey store.

Security and conditional token contents

Use Secure, HttpOnly, host-only authentication cookies with a deliberate SameSite policy; a __Host- name is a candidate. Do not break OIDC correlation cookies through a blanket rewrite. HttpOnly reduces credential extraction, not authenticated actions from XSS. See OWASP session guidance. Validate framework antiforgery tokens on unsafe cookie-authenticated operations, including applicable login/logout flows. The readable XSRF-TOKEN cookie is distinct from the secret authentication cookie; Angular sends the request header and the server validates it. Follow Microsoft antiforgery guidance and Angular security guidance. Retain sanitization/CSP and avoid unsafe trust bypasses. Same-origin is simplest; if needed, CORS allows exact trusted origins and is not authorization. Keep credentials out of URLs, logs and analytics.

For local passwords, rate-limit login/recovery/verification, support password managers and block compromised passwords. Recommend strong, preferably phishing-resistant administrator authentication and designed recovery; do not claim a mandatory NIST assurance level. NIST SP 800-63B-4 distinguishes password controls and phishing resistance from generic MFA.

If OAuth is justified, use code + PKCE, exact redirects and validated issuer/state/nonce; avoid implicit and password grants, following RFC 9700. Validate intended token type, issuer, audience, signature and expiry. Keep required profile-specific subject/client/time/scope claims and necessary authentication evidence; do not add app roles by default. Never include authenticators, unnecessary personal data or an unbounded project-membership list. ID tokens are not API access tokens. Scopes limit what a client may attempt; current application permission and resource state still restrict the action. Machine principals require explicit machine grants, not a fabricated human administrator role.

Part B — comparison after inspecting SyRF

Where the independent assumptions differ from the repository

The existing migration strategy explicitly places the BFF inside the API, not in a new proxy, and selects Auth0-backed BFF before native OpenIddict. Source has separate Identity and PM endpoints, existing native credential/account lifecycles and token-based internal calls. This is a real compatibility boundary, not proof that every separation is forever necessary. Avoid circular justification: Identity-to-PM provisioning and API-to-Identity administration are consequences of the architecture under evaluation. They show migration work, not independent requirements for keeping Identity separate. Domain workflows unrelated to identity provide a better test:

Domain workflow, independently of login architecture Verified path and selected mechanism What this does and does not justify
Bulk-PDF object release, quarantine and cleanup reconciliation Scheduled reconciler:284 composes the worker/API client; :148–214 calls notifier release/binding/cleanup/hold routes with bearer authentication. Shared request:16 limits scopes to release reads and cleanup writes. A supported bulk-PDF pipeline needs narrowly authenticated machine operations even without a separate Identity service. OAuth is the selected mechanism, not the only possible one. Repository guidance marks activation gated; this is executable source, not proof of deployed usage.
Mothballed risk-of-bias AI-review prototype — excluded from requirements RobAiService:35 and MapsGroupHttpClient:26 remain in source, including API-key headers and /submit. Chris clarified on 27 September 2026: this was a proof of concept, is not used, was not carried forward and is not planned for use. It supplies no active service boundary, future requirement or architectural constraint. Code presence does not override that owner clarification; no cleanup is included.

The bulk-PDF workflow does not require browser access tokens, human administrator claims, or a particular OAuth issuer. If service authentication changes, evaluate issuer-backed credentials, workload/platform identities or other appropriate mechanisms against the actual trust boundary; this audit does not approve a replacement. No configured credential values were read.

Verified source at the pinned revision Consequence for the independent proposal
Identity PM provisioner:38, :146: scoped bearer call using client credentials; client registration:261 separates the provisioner credential Removing all OAuth needs an approved replacement for this service boundary. It does not require human role claims.
API service client:214 has introspection and admin:users; the as-built audit traces the management adapter Machine administration scope is not a user's application administrator role. Retain separate trust boundaries if changing browser authentication.
Swagger client:359 is public code + PKCE; notifier clients are conditional at :295 Browser-only Angular is not the only configured client. Swagger is developer tooling, not evidence of public third-party/native-client demand; conditional code is not proof of activation.
API Program:215 registers antiforgery; :368 registers Redis sessions; BFF validator:151 checks non-isolated configuration Do not repeat old “missing CSRF/in-memory only” prose as current fact. The independent Mongo session option does not establish a need to replace this store. These registrations are not complete browser/production acceptance.

This audit did not establish current external-client usage, required cross-application SSO, actual ingress origins, load or a production provider inventory. Those remain evidence to collect before choosing a no-OAuth migration. Do not infer their absence from the limited initial requirements, or their necessity merely from existing code. Preserve existing account recovery, linking, MFA/passkey and migration guarantees in any simplification; replacing mature flows is not a small documentation follow-up.

Three-way gap matrix

“Plan” combines the migration documents and separately recorded #3335 decisions; they are not one approved replacement design. Detailed current-code references E1–E16 are in the as-built audit.

Dimension Independent ideal under its assumptions Existing plan / owner direction Current implementation and remaining gap
Browser authentication Server-side cookie session; OIDC login optional; no app access token required API-hosted BFF, then native Identity/OpenIddict migration BFF code and server-held tokens exist alongside bearer paths (E12). Choosing simpler transport is a separate decision, not needed to fix role authority.
Service authentication Add OAuth only for actual independent APIs/clients Native Identity plus separately scoped service clients Imports, scheduler jobs and notifications use broker/store authority; bulk-PDF reconciliation uses a narrow machine bearer grant. Mothballed AI is excluded. Identity-internal calls show compatibility cost, not independent necessity. See the systematic inventory.
Application roles One application-owned grant; backend lookup, no trusted role claims C1/C2: SyRF owns roles; approved explicit external mappings PM roles plus imported Identity groups plus session/token copies can independently allow (E2/E3/E6). No ongoing synchronization contract found.
Browser capabilities Effective backend capability response for UX #3335 shared explanations/effective policy target Angular admin selectors and reports depend on claims; /me exposes saved groups (E9/E14/E16). Consumer migration needed.
Project authority Current membership/resource policy; no implicit site-admin bypass A2: active membership except explicit audited support; project/stage redesign belongs to #3335 Existing policies mix application grants, membership and stage rules (E10). Preserve access until impact approval; broad bypass parity requires programme tests.
Removal and suspension New authorization sees committed changes; no cross-request positive cache initially R1: immediate denial of subsequent protected operations Additive role union, two-second repository cache, unchanged BFF role snapshots and saved subscription groups need an end-to-end contract (E6/E12/E15/E16).
Identity admission Credential checks distinct from application suspension; invalidate active sessions Migration preserves blocked/deactivated provenance; native security-generation revocation Import makes lockout, but custom admission does not continuously read PM deactivation; native revocation exists (E3/E7/E13). Define supported global disable/restore.
Identity mapping/profile Immutable app ID; validated issuer/subject links; application profile authority Stable Investigator mapping and explicit mailbox-proof rules; historical profile parity Strong mapping safeguards exist; callback can create a missing claimed-ID record and legacy Auth0 subject can miss native profile updates (E4/E8/E11). Do not rename IDs to fit the proposed schema.
Persistence Logical single authorities; physical schema chosen to fit access patterns Existing PM aggregates plus separate Identity collections No need to introduce appUsers/projectMemberships collections solely to match the proposal. Credentials and project grants already have distinct owners; role/status consistency is the problem.
Browser/operations security CSRF, secure shared sessions, strong admin auth, safe outages and restore Specialist security docs and gated migration acceptance Relevant code exists; this audit did not rerun browser, outage, restore or lifecycle suites. Do not relabel untested criteria as missing code or verified deployment.

Critical evaluation, separate from the proposal author

The source-audit evaluator assessed the independent report after its author had completed it. This is not an endorsement based on agreement alone. The labels below are recommendations for review, not approved implementation instructions: adopt the principle, adapt to SyRF, reject the stated shortcut, or leave pending until evidence/owner decisions resolve it.

Recommendation Evaluation Evidence, missing consideration or necessary qualification
Application-owned permissions, no trusted long-lived role snapshot Adopt Consistent with C2 and removes the verified stale/additive grant problem. Actual canonical mappings and removal behavior still require approval and tests (E2/E6/E12).
Remove application-role claims entirely Adapt Sound target candidate, but migrate all listed consumers, including impersonation and feature-flag administration. Neither a protocol requirement nor removing the field alone can solve the current compatibility dependency (E14/E16).
One modular application, no dedicated OAuth issuer Ideal-target recommendation for the actual first-party scope; migration pending Backend sign-in and server-side cookie sessions do not require a separate issuer. The external-client discussion was hypothetical and withdrawn. Preserve real machine-workflow compatibility while choosing its bounded authentication mechanism; Identity-created calls are not independent justification.
Cookies instead of browser-held bearer credentials Adapt Matches the BFF direction already chosen. SyRF's BFF is API-hosted, so the report's possible extra proxy hop is not an inherent cost here. Existing bearer/Swagger compatibility must be deliberately retained or retired.
Proposed collections and one shared Identity/application ID Reject as a required migration Logical responsibilities are useful; renaming collections, splitting project aggregates or equating IDs creates migration risk without an established authorization benefit. Preserve existing stable Investigator mappings (E1/E4/E10).
Mongo-backed sessions; avoid Redis by default Adapt Reasonable from a blank slate, but SyRF has a shared Redis/Valkey contract and environment isolation. Measure total availability/operations cost before moving session load onto Mongo; do not add a second session authority.
Authoritative reads on each operation Adopt, with consistency proof Fits R1 but needs cache bypass/invalidation, read consistency and transaction ordering across replicas. Existing two-second cache and connection snapshots do not meet the promise by themselves (E15/E16).
Optional 30-second permission cache Reject under current R1 The independent report offers it as a future tradeoff, not a requirement. It would relax an accepted immediate-operation guarantee. A 30-second realtime timer likewise cannot substitute for current protected-delivery checks.
Five-minute strong-authentication window Pending A risk proposal, not NIST or framework default. Existing emailed step-up is operation-bound link/unlink proof with configured MFA, not a general administrative assurance policy or new downstream authentication evidence. See step-up design.
Provider/local login selection as an open greenfield choice Adapt SyRF must preserve existing account/password-reset migration, Google linking, dormant-record claims, pending-claim recovery and anti-enumeration/abuse contracts. The simple option table does not price replacing these flows. See claim recovery and recovery protections.
Project roles and site administration separated Adopt the separation; adapt the model A2 already rules out implicit administrator content access. SyRF has project groups, stage grants and membership IDs, not merely viewer/contributor/manager labels (E10). The proposed labels are not sufficient policy coverage.
Replace authentication before fixing authority Reject as the first delivery sequence Neither the proposal's benefit nor the observed role problem requires a transport rewrite first. Preserve migration rollback and supported accounts while delivering one correct role-change path.

Omissions or under-specified areas in the independent report

These are largely consequences of its deliberately limited starting requirements, not proof the author ignored supplied facts. The report mentions the categories; it does not model SyRF-specific contracts:

  • Actual clients and topology: which service boundaries need independent credentials/audiences, which bearer clients are used, and whether origins/SSO require federation. Conditional notifier support is not live usage. No client census or deployment simplification cost was supplied to the author.
  • Migration and recovery continuity: account cohorts, legacy subjects, mailbox proof, mapping tombstones, staged provider fallback and rollback cannot be replaced by generic registration/linking commands. The Phase 5 context records reversibility and delayed decommission; use its dated corrections and validation ledger, not its historical starting-state statements as today's deployment facts.
  • Application policy depth and privacy: project groups, stages, individual membership grants, permission reports and explicitly bounded support impersonation need a complete capability mapping. Independent role examples do not settle those rules or approve administrator access to research.
  • Assurance and abuse: “strong within five minutes” needs accepted methods, recovery consequences and operation binding. Existing email retry/step-up and account-lockout protections must survive; email confirmation alone must not be silently promoted to phishing-resistant authentication.
  • Revocation economics: a session/user/membership read on every action is a reasonable baseline, not a measured latency/availability result. Indexing, read concern, live delivery, in-flight fences and shared session/key management need proof. Suggested timeouts and collection splits lack SyRF-specific evidence.

Omissions or unresolved contracts in the existing plan

  • Migration documents specify a PM-to-Identity role snapshot, but the inspected plan/source does not supply a general ongoing role writer, removal propagation or BFF snapshot refresh contract.
  • The migration and #3335 tracks do not yet form one executable transition from accepted application-owned roles to every current consumer. No-role claims versus derived projection remains a real design choice.
  • Global suspension/restore and profile precedence need clearer end-to-end ownership, failure and mixed-provider contracts; deleting an account or changing a flag is not an adequate substitute.
  • Historical documents contain closed “missing CSRF/session infrastructure” and claim-producer findings. The as-built audit's documentation map identifies them; they should not drive new work without verification.
  • The inspected material does not establish an approved case for removing all OAuth or replacing shared session storage. The subsequent repository-wide inventory expands the initial narrow search, but still does not establish live usage or all external client requirements.

Verified implementation issues, not merely differences from the ideal

The source audit separately establishes the missing ongoing role synchronization path, saved BFF roles surviving token refresh, claim-plus-PM enforcement versus claim-only consumers/reports, and raw runtime role-name matching. It also identifies the legacy-subject/native-profile endpoint mismatch and absence of continuous PM deactivation in inspected native admission checks. These are concrete consistency gaps or source-level risks with evidence E2–E16, not live exploit or affected-user-count claims. Migration administrator casing and shared userinfo claim production are already fixed and are not open defects. Different collection names, use of Redis, and having an OIDC server are not defects merely because the independent greenfield proposal chooses otherwise.

Recommendation and decisions

Ideal end goal for the actual scope: first-party Angular talks to its C# backend using a secure, server-side session referenced by an HttpOnly cookie, with CSRF protection. Backend sign-in establishes identity; SyRF reads its own current application/project permissions for protected operations. Do not carry mutable application-role claims as a second authority. A dedicated OAuth issuer is not required solely for this browser. Real workers still need narrowly scoped machine authentication, distinct from human permissions.

Concrete next step: implement one separately approved vertical slice that removes a selected application permission and proves immediate denial through an already-open browser session and both API replicas, without breaking current login/mappings. Include the role-claim-free evaluator, stale-claim/cache tests, protected-content administrator-nonmember assertion and explicit failure behavior. The verification test contract defines the missing fixture. Do not start by deleting Identity: inventory and replace any real issuer-dependent machine contracts, then simplify authentication topology in a later approved slice. Temporary compatibility is a migration constraint, not the ideal target or a requirement to retain today's services.

Recommended direction: retain application-owned authorization and evaluate the no-app-role-claims target first. During the transition, keep Identity responsible for authentication and stable mapping. This aligns the independent proposal with C2 without assuming a persistent projection. A compatibility projection is justified only by an identified remaining consumer and an explicit removal/freshness contract.

Recommended transition: address that authority boundary without first replacing the BFF or deleting OpenIddict. Preserving compatibility while alternatives are evaluated avoids breaking existing workflows; it is not evidence that Identity-created boundaries must be retained. Independently required machine workflows need authentication, but not necessarily OAuth or SyRF's issuer. This is a risk-based transition recommendation, not a conclusion that current topology is ideal or that tokens must remain forever. Browser session transport, app-role authority and service OAuth are three independently decidable concerns.

Owners still need to resolve:

  1. Actual required clients, API audiences, SSO and deployment origins: retain current OIDC/BFF, simplify only browser sessions, or approve a broader service-auth redesign? Cost account for existing flows.
  2. No application-role claims versus a specifically justified derived projection; then, only if needed, on-demand versus persisted projection. Approve exact existing-group mappings and access changes.
  3. Canonical application capabilities, grant authority, profile writer and global suspension/restore semantics. C2 ownership, R1 immediate operations and A2 no implicit project bypass are already decided.
  4. Precise consistency/in-flight semantics, assurance and session durations. Independent timing suggestions are not accepted SyRF policy; the 30-second positive-cache option conflicts with R1.
  5. Enrollment/recovery/provider deprovisioning requirements and operational acceptance, including outage, key rotation, restoration, audit retention and external-client compatibility.

Smallest usable implementation sequence — proposal only

The docs MVP is this comparison plus the source-pinned audit; no implementation is included. Subject to the existing programme owner's decisions, the shortest first implementation path is one audited role change → one authoritative backend decision → one existing-session grant/removal result:

  1. Confirm role vocabulary/mappings and present access-impact differences read-only; preserve existing grants until approved. Inventory remaining claim consumers and required nonbrowser clients.
  2. Deliver one thin vertical administrator capability: authorized grant/revoke, current authority lookup, server enforcement and matching UI capability, tested through direct API and an already-open BFF session. Include claim-only users, stored-only users, casing, failure and removal tests. Keep other capabilities unchanged; do not remove globally consumed claims during this first slice.
  3. Migrate the remaining consumers in bounded slices: direct controller checks/impersonation, reports, project policies and live/queued delivery. Every slice proves removal, not only grant. Remove role claims and Identity's persisted copy only when no authoritative consumer depends on them and rollback is safe.
  4. Deliver global suspension/restore as its own existing-session slice; preserve research and separate lockout/deletion semantics. Validate multi-replica ordering, failures and audit persistence.
  5. Consider transport/service consolidation only after the client/topology decision. Defer new role editors, schema rewrites, optional caches and broader polish unless required for correctness or security.

Acceptance checklist for the chosen target

  • One authority per credential, identity mapping, application status, site role and project membership; no silent second grant source. Email changes cannot transfer identity.
  • Non-admins cannot invoke administrator commands; project permissions and support exceptions are explicit. Cross-project ID substitution fails for individual/batch CRUD, search/counts, export/download and realtime.
  • Committed role removal and suspension meet the chosen bound across replicas, old cookies, direct tokens, refresh, live subscriptions and queued delivery. Copied revoked cookies fail; in-flight limits are explicit.
  • Concurrent grant/revoke, invitation acceptance and any last-manager rules preserve uniqueness and ordering. Sensitive writes cannot bypass authority via DTO assignment or stale transaction snapshots.
  • Cookie/CSRF/CORS/XSS behavior and supported browsers are tested. Capability responses are never credentials. Any remaining token validates issuer/audience/type/lifetime and cannot substitute scope for project access.
  • Mongo Identity concurrency, uniqueness, stamps, MFA and recovery are tested; session-store/provider outages, key rotation, rolling deployment and backup restore fail safely without silently resurrecting access.
  • Audit can reconstruct privilege changes without secrets; bootstrap and recovery remain controlled. Unmeasured performance and untested live deployment are reported as such, not asserted from source.

These are future verification gates, not claims of completed tests or authority to create accounts, change roles, activate flags, run a rehearsal or merge this documentation PR.