Skip to content

Email-based two-factor authentication #44

Description

@FireSquid6

Follow-up to #7, which added authentication and gave every user a required, unique email column (packages/fleet-bridge/src/auth/auth-database.ts). Nothing consumes that column yet — it exists so this can be built on top of it.

What this is

A second factor on POST /auth/login: after a username and password verify, the bridge emails a short-lived code and issues a session only once that code is returned.

Decisions this needs before implementation

Who is covered. Opt-in per user, enforced per role (all admins, say), or fleet-wide? Opt-in is friendlier; enforced-for-admins matches where the privilege actually is, now that registering a ship is admin-only.

Delivery. The bridge has no SMTP configuration and no outbound mail of any kind today, so this is new infrastructure: where the credentials live, what happens when sending fails, and whether a send failure is fail-open or fail-closed. Fail-closed on a broken mail server locks everyone out of their own fleet; fail-open makes the second factor advisory.

Where it slots in. AuthService.login currently returns { token, user } in one call. A second factor means a two-step exchange — a short-lived challenge, then the code — which changes the shape of POST /auth/login and therefore both clients (packages/fleet-client/src/data/auth.ts, apps/cli/src/session.ts).

Recovery codes. Without them, a lost mailbox is a lost fleet. With them, they are one more secret to store and hash.

Rate limiting. Deliberately out of scope in #7. A mailed numeric code is weak enough that it probably cannot ship without a throttle on both login attempts and code submissions.

Explicitly exempt

Machine credentials must not be covered: the ship, ship-agent, and workspace-agent tokens all authenticate processes with no human at a keyboard. Only the interactive user login gains a second factor.

Prior art in the repo

  • packages/fleet-bridge/src/auth/auth-service.ts — sessions, argon2id passwords, and the in-memory single-use WebSocket tickets, which are a reasonable model for a short-lived challenge.
  • packages/fleet-bridge/src/auth/bootstrap.ts — the env-vars-then-TTY-then-fail-fast pattern, worth mirroring for any new required configuration.
  • apps/docs/src/content/docs/guides/authentication.md — the current model, which this would extend.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions