Skip to content

Account switching

When one person controls multiple email-based accounts (e.g. a personal account and a company-email account from corporate onboarding), they can link them and switch without signing in again. Base path: /api/auth/linked-identities.

Linking (proof of ownership on both sides)

Section titled “Linking (proof of ownership on both sides)”
Method · RoutePurposeSource
POST /initiateSigned-in user A requests to link email B; emails B a single-use confirm link (15-min, rate-limited).LinkedIdentityEndpoints.cs:36
GET /confirm?token=B clicks the emailed link → creates the sealed LinkedIdentity (A↔B). Token-authenticated, no session.:89
GET /List the current user’s active links (for the account-switcher dropdown).:131
POST /{id}/revokeUnlink — append-only (Status=Revoked, soft-delete; never hard-deleted).:162

POST /switch (:185) re-issues the session as the linked identity and swaps the cookie — gated by a fresh passkey step-up of the current session owner:

  • A link must already exist between caller and target, else 404 not_linked.
  • A passkey assertion is required (403 step_up_required if absent).
  • The assertion must verify and belong to the caller’s own User (assertion.UserId == uid), so a stolen cookie + an attacker’s own passkey cannot pivot (403 step_up_failed).
  • On success, SwitchIdentityCommand issues the target session and CookieAuthWriter replaces the cookie.

Linking requires explicit proof of ownership of both accounts — accounts are never linked automatically.