59 lines
3.4 KiB
Markdown
59 lines
3.4 KiB
Markdown
# SEC-004 canonical Microsoft identity verification
|
|
|
|
Date: 2026-08-02
|
|
|
|
Status: `IMPLEMENTED — NOT VERIFIED`. Repository implementation, synthetic controller tests,
|
|
frontend component tests, build, migration SQL and disposable SQLite upgrade checks pass. Real
|
|
Microsoft, browser, SMTP, MariaDB execution and production legacy inventory remain blocked.
|
|
|
|
## Implemented trust path
|
|
|
|
- Microsoft account ownership is the normalized GUID pair (`MicrosoftTenantId`,
|
|
`MicrosoftObjectId`) with a unique composite database index.
|
|
- Exchange and conflict lookup use only that pair. `MicrosoftSubject` is no longer written and
|
|
provider email is metadata only; a matching local email returns a safe conflict instead of a link.
|
|
- New Microsoft registration stores the pair immediately, leaves application email unconfirmed,
|
|
and obeys the verification-required 202/no-session gate.
|
|
- Explicit link requires the authenticated local user's current password. Link and unlink revoke
|
|
all sessions/trusted devices; passwordless unlink is refused as a last-credential guard.
|
|
- Legacy fields remain null-canonical evidence. A single eligible candidate receives a
|
|
purpose-bound proof at its confirmed application email. Confirmation requires that proof plus a
|
|
fresh Microsoft token for the exact same (`tid`, `oid`) pair. Multiple or unconfirmed candidates
|
|
require operator-assisted recovery.
|
|
- Frontend MSAL authority uses the same `AUTH_MICROSOFT_TENANT` value passed at build time.
|
|
|
|
## Evidence
|
|
|
|
- Focused auth controller tests: 34/34 passed.
|
|
- Full backend suite: 507/507 passed.
|
|
- Full frontend suite: 44 suites, 152/152 passed; production build passed.
|
|
- SQLite migration SQL uses two nullable `TEXT` columns and a unique composite index.
|
|
- MariaDB migration SQL uses two nullable `varchar(36)` columns and the same unique index.
|
|
- Disposable SQLite legacy rehearsal:
|
|
- two rows with duplicate legacy subject/email values remained unchanged and null-canonical;
|
|
- migration applied without backfill;
|
|
- first canonical pair assignment succeeded;
|
|
- duplicate pair assignment failed with SQLite unique-constraint exit 19.
|
|
- Production Compose interpolation includes the same tenant mode in backend configuration and the
|
|
frontend build argument.
|
|
|
|
## Blocked checks and residual risk
|
|
|
|
- No real Microsoft token/account was used. Issuer/tenant/signature behavior is covered by the
|
|
SEC-003 signed-token tests; exchange/link/recovery use mocked tenant-qualified principals.
|
|
- The existing browser policy blocker was not retried. No browser workflow, popup, accessibility,
|
|
mobile or screenshot claim is made.
|
|
- No SMTP sink was available, so the complete emailed recovery link was not exercised end to end.
|
|
- MariaDB SQL generation passed, but no disposable MariaDB execution environment was available.
|
|
- Production legacy counts and collision groups are unknown. Microsoft production enablement must
|
|
remain gated until the counts-only inventory in `deploy/README.md` and migration/version-skew
|
|
checks pass.
|
|
- Legacy rows with multiple candidates or unavailable/unconfirmed app email deliberately require
|
|
operator verification; no automated merge is attempted.
|
|
|
|
## Rollback
|
|
|
|
Disable Microsoft sign-in by clearing its client ID, roll back application binaries, and retain the
|
|
additive columns and legacy evidence. Do not restore subject-only or email auto-linking. The migration
|
|
`Down` is appropriate only before canonical pair data is relied upon.
|