The dry run for your first demo has a witness: the partner whose clients your portal will hold. Signed in as one consultant, you open one of your own clients, and the address bar reads portal.example.com/clients/1041. You change 1041 to 1042 and press return. The page renders a different consultant's client: meeting notes, a billing dispute, a draft apology letter, none of it yours. The login screen you showed her a minute earlier worked exactly as built. It checked who you were once, at the door, and after that nothing checked anything, so the partner watches you read a stranger's file with nothing more technical than an address bar.
Nothing in that scene was hacked. Auth, the engineering shorthand for a product's account machinery, bundles two checks, and the portal was asked for a login screen, so it built only the first.
Auth is two checks, not one
Authentication asks who you are. It is the front desk, the sign-in flow that turns an anonymous visitor into a known user and hands over a keycard; engineers shorten it to authN.
Authorization asks what you may do. It is the reader on every door, the permission rule that runs when a known user tries to read a record; shortened to authZ, it belongs on every request the backend handles, because every request taps some door.
What you did in the address bar is called broken access control: a signed-in user reaching records no rule ever checked. It tops the OWASP Top 10, the industry's ranked list of web application risks, and it is just a missing permission check on one door.
A product is only safe when both checks run as separate jobs: authentication proves who someone is, and authorization decides, on every request, what they may do.
What happens when you sign in
Run the portal's sign-in and watch three moments; only its domain is invented.
The hand-off. Click "Sign in with Google" and the address bar jumps, trimmed to the parts that matter:
https://accounts.google.com/o/oauth2/v2/auth
?client_id=8123...apps.googleusercontent.com
&redirect_uri=https://portal.example.com/auth/callback
&scope=openid email
The portal never sees a password. It sends your browser to Google with client_id (which app is asking), redirect_uri (where Google sends you back), and scope (what the portal may learn: identity and email, nothing more). Tools call this family of borrowed sign-ins OAuth, and every consent screen you have clicked ("Allow this app to view your email address") is a scope rewritten for humans.
The keycard. Back at the portal, the reply carries one line that matters:
Set-Cookie: session=eyJhbGciOi...trimmed...; HttpOnly; Secure
That line tells the browser to keep a cookie, a small labeled value attached to every request from now on. The cookie holds the session, your signed-in state: the keycard from the desk. Some products double-check first: the texted six-digit code is a second factor, extra proof of identity before the session starts.
The doors. Repeat the opening's address-bar edit, still signed in:
GET /clients/1041 -> 200 OK your client's notes
GET /clients/1042 -> 200 OK another consultant's client, rendered anyway
A GET is the browser asking to read; 200 OK is the server agreeing. The same valid cookie rode both requests, so authentication passed twice; nothing asked whether this user may read this record. With doors, the second line ends in 403 Forbidden: the server recognizes you and still says no. That is the URL-swap test: ask for an ID that is not yours and read the reply.
Never build login yourself
Login looks like a beginner-sized feature, but it hides decades of solved problems: password storage a stolen database cannot expose, reset emails that cannot be hijacked, and sessions that expire on time. Build it yourself and you break these one at a time; rent the flow from a service such as Clerk, Auth0, or Supabase Auth and you never store a password; your job shrinks to the spec below.
The sign-in methods to choose from
When the service asks which methods to turn on, the menu is short.
- Email links. An emailed link signs the user in; no password ever exists. Products call these magic links.
- Sign in with Google or Apple. This is the borrowed sign-in you just traced: one button, vouched for by an account the user already trusts.
- Passwords. They are still everywhere and still the weakest entry: one password reused across sites leaks with the next breach.
- Passkeys. A passkey is a secret your device creates for one site, approved with whatever already opens your phone. A phishing page has nothing to capture, and passkeys are now the default on Apple, Google, and Microsoft accounts, so you have probably already used one.
An email link plus one big button covers nearly everyone; adding a method later is a setting, not a project.
The objection: your agent wires this up from one sentence
The obvious objection is that one sentence to your coding agent already produces a working login: service chosen, screens wired, cookie handled. That is true, and it is why you rent, not build. But the sentence cannot carry decisions you have not made: who may sign up, which roles exist, where the harm line sits. Left out, they become defaults, and no default encodes which consultant may open which client; the doors arrive missing. Cost does not change the answer: auth services typically run free into the first few thousand users, then charge per active user, and the expensive mistakes come from the rules you never wrote.
Many first builds need no auth at all
Accounts are permanent work: you maintain the flow, rescue locked-out users, and hold personal data that a breach could expose. A tool only you run, or a public site showing everyone the same content, needs none; we shipped this site with no accounts.
The test for your build: finish this sentence for each feature you planned to gate: "If any stranger on the internet could do this, the specific harm would be..." When no harm comes to mind, skip auth; adding a service later is days of work, not a rewrite. When the harm is obvious (private records, money moving, posts under someone's name), you need both checks from day one.
The three-line auth spec
When the build earns auth, answer the agent's login question with three lines.
- Who signs up. Anyone with an email address, only people you invite, or only addresses at one company's domain.
- How they sign in. Pick from the menu above, such as an email link plus Google.
- What each kind of user may do. Name the roles and draw the lines between them.
For the consultancy portal, the spec reads: anyone with a company email address can sign up; they sign in with Google; consultants see only their own clients while partners see every client plus invoicing. That third line is the authorization half, the rule whose absence rendered client 1042; written down, it turns that request into a 403. Hand the three lines to your agent and the wiring becomes its job; the spec drops straight into Write your Build Plan and ship.
Try it now
The drill takes about fifteen minutes and spends nothing. You arrive with the idea file from Decode the technical questions that stop you and leave with your AUTH SPEC added to it.
No setup: Audit the sign-in of two AI products you already use, say a chat assistant and a meeting notetaker. On each sign-in screen, list the methods: password, email link, Google or Apple, passkey. Click a borrowed sign-in: the hand-off flashes through the address bar, the consent screen shows its scope, and at least one product asks for a second-factor code. Sign out and record what locks; you are reading each product's auth spec from the outside.
With your tools: Write the three-line AUTH SPEC for your idea, paste it into Claude Code, and ask which auth service it would wire in and what it would check on each request to enforce your third line. Same move in Codex or Cursor: give the sidebar chat your spec and ask for the service pick and the per-request check. If your tools are not set up yet, The Setup Clinic gets you there.
Either way, add to the idea file. Save the three lines under the heading AUTH SPEC; if your honest first line is "no accounts yet", write that plus the harm sentence instead. Both versions feed the Build Plan.
Chapter Summary
- Auth bundles two checks: authentication proves who a user is, authorization decides what that user may do, and a login screen only delivers the first.
- The permission check runs on every meaningful request, not once at sign-in, because every request is a tap on some door.
- The classic failure is broken access control, the top risk on the OWASP Top 10: a signed-in user changes an ID in a URL and reads a stranger's record because no rule was ever checked.
- A sign-in has three visible moments: a hand-off URL that says which app is asking and what it may learn, a session cookie the browser attaches to every later request, and a door check (or its absence) on each record you ask for.
- Never build login yourself; rent it from a service such as Clerk, Auth0, or Supabase Auth, and you never store a password.
- The method menu runs from email links through Google and Apple buttons to passkeys, now the default on the major platform accounts; passwords remain the weakest choice.
- One sentence to an agent wires the plumbing, but who signs up, which roles exist, and where the harm line sits are decisions only you can supply.
- Many first builds need no accounts at all; when you cannot name the specific harm a stranger could do, skip auth for now.
- Your AUTH SPEC is three lines, who signs up, how they sign in, and what each role may do, saved in your idea file for the Build Plan.
- Everything you have built so far can fail quietly, sign-in included, and Monitoring, how you know it broke (and what it costs) is how you find out before your users do.
Sources
- OWASP Top 10, where broken access control holds the top position in the 2025 revision (last verified July 2026).
- Google Identity documentation on OAuth 2.0 for web sign-in (last verified July 2026).
- FIDO Alliance documentation on passkeys and platform support (last verified July 2026).