authentication-and-sessions

Authentication & Sessions

The YouTeacher web app is a browser-facing client that fronts a separate Auth service. It never owns identity itself; it drives the user through login, signup, and account-security flows, and forwards each step to the Auth service. What makes this subsystem interesting is that it supports several authentication factors at once — password, a time-based one-time-code second factor (TOTP), a device-bound passkey (WebAuthn), and social sign-in (Google, LinkedIn) — and lets one account mix them.

Factors as a stack

The design doc models the whole thing as a pushdown automaton: the set of factors a user has enabled behaves like a stack, and which transitions are legal depends on what is currently on it. A fresh password signup carries password + TOTP. A social-only account carries just its provider. A "full" account can hold password, TOTP, passkey, and both social providers together. Enrolling a factor pushes onto the stack; unlinking one pops it. This framing is why the same security screen offers different actions to different users — the available paths are read off the stack, not hard-coded per page.

The flows

  • Login — if the browser remembers that the user has a passkey, it opens a passkey-first prompt with a fallback to the password form; the password form also offers the social providers and a passkey button.
  • Signup — email is verified with a one-time code first, then the user sets a password, then chooses a second factor (authenticator app or passkey) and enrolls it. Social sign-up bypasses the password/MFA steps entirely.
  • Account security — a single hub for resetting the password, resetting the authenticator, adding a password to a social-only account, linking and unlinking providers, managing passkeys, listing and revoking sessions, and deleting the account.

Ports and adapters

The app follows a hexagonal layout. Use cases depend on gateway interfaces (ports), and concrete API-gateway adapters implement them against the Auth service. So the passkey use case talks to a passkey port; the session use case talks to a session port; the OAuth path talks to an OAuth port. This keeps the auth logic (what a flow does) separate from the wiring (how it reaches the backend), and lets the same flows run against a local mock Auth server during development.

Session adoption

When any flow authenticates successfully, the app adopts the new session locally after best-effort revoking whatever session was already current — if that revoke fails, it still adopts, so a stale prior session never blocks a fresh login. Session management elsewhere lets the user revoke one device, sign out all other devices, or end the current one.

Guards and privacy-preserving behavior

Several rules are deliberate, not incidental. A provider or passkey cannot be removed if it is the only way left to sign in. Email-existence and code-send steps proceed silently on failure so an outsider cannot probe which emails are registered. Wrong email and wrong password return the same generic error for the same reason. Sensitive operations are gated by a bot-check (reCAPTCHA) before they reach the backend.

Where identity lives across services

The Auth service is the source of identity and of a user's marketplace roles; verification and approval status live in the Profiles service instead, so those can change without re-issuing a token. When the web app calls another backend service on the user's behalf, it makes a service-to-service call carrying a service credential plus the user's context, and the downstream service trusts that context.

Inside this component

about this entry

One of sijie's wiki entries. The AI on this site is grounded in the same corpus and answers in sijie's voice, with citations back to entries like this one — answering costs sijie money, so it waits behind a code: enter an access code →