September 12, 2026
SIGN-IN, SESSIONS, PASSWORDLESS, AND OAUTH WITHOUT THE MYSTIQUE

Lesson 47.1 separated "who are you?" from "what may you do?" This lesson owns the first question end to end: how a stranger becomes a verified identity, how the browser proves it on later requests, and how that proof ends. Get this flow right and authorization has something trustworthy to stand on. Get it wrong and every policy in your matrix is built on sand.
The lifecycle in one diagram
Strip away vendor names and there is exactly one shape:
person proves identity via trusted provider
→ application receives a signed result
→ browser holds a secure, time-limited session mechanism
→ backend verifies it on every protected request
→ logout or expiry ends it
Each arrow matters. The person never hands your application code a password to store in a table you designed. A trusted provider (or your framework's auth layer built on one) validates the proof and hands your backend a *signed result*: "this is usr_41, verified at this time, by this method." The browser then carries a session — typically an HTTP-only, secure cookie — that it presents automatically. Your backend verifies that session on each protected route, following the decision path from Lesson 47.1. Logout deletes it server-side and client-side; expiry kills it by clock.
Sessions are time-boxed by design. A session that never expires is a key copied forever: anyone who steals it owns the account until the user notices. Short lifetimes with safe renewal (rotation, idle timeout, absolute maximum) are standard practice, and they are exactly the kind of detail documented in OWASP Authentication Failures — read the session-management section before you approve any custom scheme.
Four ways to prove "it's me"
You will meet four methods. Teach the mechanism, not the marketing:
- Password login. The person knows a secret; the provider stores only a salted, slow hash of it — never the password itself — and compares hashes at sign-in. Add rate-limiting, breach-password screening, and a second factor for anything sensitive. Passwords are familiar but shift real burden onto recovery and abuse controls.
- Magic link. The person enters an email; the provider sends a single-use, short-lived link. Clicking it proves control of the inbox. No password to remember, but delivery depends on email, links must expire in minutes, and each link must work exactly once.
- Passkey. The person's device holds a private key; the site holds the public half. Sign-in is a cryptographic challenge answered by fingerprint, face, or PIN — phishing-resistant, with nothing reusable to steal on the server. Support is now broad, but you still need a fallback for lost devices.
- OAuth / "Continue with Google" (or GitHub, Apple). Identity is *delegated*. Google verifies the person and tells your app "this is Maya,
maya@example.com, verified now." Your application never receives her Google password — that is the entire point. Delegation simplifies your security surface but introduces consent screens and provider dependence.
For a first Research Desk or Neighborhood Events build, any one of password-plus-recovery, magic link, passkey, or a single OAuth provider is defensible. Offering all four on day one is not a feature; it is four recovery flows, four abuse surfaces, and four test suites.
Scopes: signing in is not permission to raid
OAuth adds one idea worth isolating: scopes. When Maya clicks "Continue with Google," the consent screen lists what your app requests. There are two very different asks:
- Sign-in identity: name, email, "are you the same person who returns tomorrow?" This is all most apps need.
- Data access: read her Drive files, calendar, contacts, post on her behalf. This is a far larger promise, with far larger consequences if your app is compromised.
Request the minimum. "Sign in with Google so we can identify your watchlist" needs basic profile scope, not calendar read-write. Every extra scope is extra liability, extra user suspicion, and an extra line in your privacy story. If a future feature genuinely needs calendar access, request it then, in context, with its own consent — not bundled into day-one sign-in because an AI scaffolded it that way.
State the rule in your spec: "We request scope X because feature Y needs it. Everything else is out of scope until a written decision adds it."
The managed-auth default
Here is the lesson's load-bearing rule:
Storing passwords, generating session tokens, rotating secrets, throttling brute force, handling recovery without leaking which accounts exist, detecting credential stuffing — each of these is a specialty with decades of known failure modes. OWASP's authentication guidance exists largely because teams rebuilt them badly.
That does not mean "never think about auth." It means your thinking moves up a level: you choose the method, configure session lifetimes, define protected routes, design recovery UX, and write the policy tests. The provider handles hashing, token signing, rotation, and rate-limit edge cases. When you prompt an AI, draw the boundary explicitly:
If an AI proposes md5(password), a hand-rolled JWT signer, or tokens in localStorage copied from a tutorial, that is a stop-and-redirect moment, not a style nit.
Authentication is a product flow, not a modal
Beginners picture a login box. Builders picture seven states, each with a designed screen:
1. New user: what do they consent to, what is created, where do they land? (Empty watchlist guidance, not a blank page.) 2. Returning user: fastest path back — remembered email, passkey prompt, or single OAuth click. 3. Expired session: "Your session expired. Sign in again — your saved items are still here." Never silently dump them on a form with unsaved work. 4. Wrong browser / wrong email: magic link opened on a different device, typo'd address. Explain what happened and offer resend, not "invalid token." 5. Account recovery: lost password, lost device, changed email. Who verifies, how long does it take, what cannot be self-served? 6. Consent declined: user cancels the Google screen. They return to a useful anonymous state, not a broken spinner. 7. Support path: locked out, suspected takeover, "was this email really from you?" Provide a human contact and a status page, not a dead end.
Design each state before you code. An auth flow with only a happy path teaches users that errors mean the product is broken — and teaches attackers exactly where the edges are unhandled.
Exercise: draft the sign-in specification
One page. Six sections. No cryptography invented.
1. Method: e.g. "Magic link plus Google OAuth; no passwords in v1." Justify in one line. 2. Data requested: exact scopes/fields (email, display name) and why each is needed. Explicit non-goals ("no calendar, no contacts"). 3. Session duration approach: e.g. "provider-managed session, 30-day absolute maximum, idle re-verification for destructive actions; organizers re-confirm before deleting a published event." Name logout behavior (all devices? this device?). 4. Protected routes/actions: map to the authorization matrix — which routes require a session, which require ownership, which are public. Example: GET /api/brief public; POST /api/watchlist requires session; DELETE /api/watchlist/:id requires session plus ownership. 5. Recovery: lost access, changed email, suspicious-login contact. Who does what, and what the user sees at each step. 6. Tests: signed-out request → 401; expired session → redirect to sign-in with return-to preserved; wrong-account access → 403; consent declined → clean anonymous state; logout → session invalid on next request; replayed magic link → single-use enforced.
Your finish line: an auth flow diagram (the five-step lifecycle, annotated with your method and durations) plus a written "we will not build this ourselves" boundary listing password storage, token signing, brute-force throttling, and recovery-token generation as provider responsibilities.
Quick verification: sign out, request a protected route, and confirm denial. Then expire a session (shorten lifetime in a preview environment), reload, and confirm the expired-state screen — not a crash, not silent access.
Check your understanding
1. What does your application receive after OAuth, and what does it specifically *not* receive? 2. Why is requesting calendar scope at sign-in for a watchlist app a bad trade? 3. An AI submits a custom hashPassword() function. What is your review response, and what do you point it to instead?
Next, Lesson 47.3 completes the picture: roles, ownership, team membership, and service credentials — and the policy tests that prove each one holds.
ARTICLE DISCUSSION
JOIN THE
CONVERSATION.
Got a question, a take, or a better way to do this? Log in and leave a comment.
