Auth + Consent Flow
A request from a browser to a PHI endpoint crosses four independent trust boundaries. Each boundary is enforced in code + tested explicitly.
Request lifecycle
Cookie contract (FR-008a)
Consent resolution order
When a PHI-route handler carries @ConsentScope("<scope>"), the ConsentGuard resolves in this strict order — short-circuit on first ALLOW:
This is implemented once in ConsentGuard — controllers never re-implement. Every allow path sets authSource on the audit event so forensic review can trace which branch permitted the access.
MFA flow (step-up)
MFA roles enforced (FR-009d): provider, coordinator, nurse, admin always require MFA. Patients opt in.
For Microsoft tokens MFA is verified via the amr JWT claim evaluated against AMR_ACCEPT. Google OIDC doesn't emit amr, so Google users always enforce the application-layer MFA (Spec 002).
Break-glass access
Break-glass access does NOT bypass ACL (FR-046-005) — consent-denied-at-ACL-level still denies. The break-glass branch only allows bypass of the standing-consent check.
Why 4 independent layers?
Principle III — Defense in Depth. If any single layer is accidentally weakened:
- CSRF compromised → RBAC still requires the right role
- RBAC misconfigured → ConsentGuard still requires a consent path
- ConsentGuard misconfigured →
@phi_repositorystill addspatient_idto the query filter (FR-013d) - Repo layer bypassed by direct Mongo access →
FieldEncryptionServicestill refuses plaintext PHI writes
See CLAUDE.md § Authentication & Session — DO / DON'T and § Authorization — DO / DON'T for the exact enforcement rules.