Authentication
Step 23 in the System Design path · 1 concepts · 0 problems
📘 Learn Authentication from zero
Authentication is the process of verifying that someone is who they claim to be. Think of an airport: at check-in you say "I'm Alex." That claim alone proves nothing. The agent asks for your passport — a credential issued by a trusted authority that is hard to forge. Matching your face to the passport photo is authentication. (Whether you may board this particular flight is authorization — a different gate, a different check.)
From first principles, authentication needs three things: a claim of identity ("I am user 42"), a credential that only the real user could produce (a password, a private key, a one-time code from your phone), and a verifier the system trusts to confirm the credential.
Worked example — password login. A naive system stores passwords in plaintext; one database leak exposes everyone. The correct design never stores the password itself. At signup, the server generates a random salt and computes hash = bcrypt(password, salt), storing only the resulting record (bcrypt embeds the salt and work factor in its output string, so you persist that one string). At login it recomputes the hash from the entered password and the stored salt, then compares the two with a constant-time check. A match means the user knew the password — without the server ever keeping it. The salt makes two users with the same password get different hashes, defeating precomputed "rainbow table" attacks; the slow, memory-hard hash makes mass offline brute-forcing infeasible even after a leak.
Once verified, re-checking the password on every request is wasteful, so the server issues a session token (or a signed JWT) the client presents thereafter — proof that authentication already happened.
Key insight: authentication verifies a hard-to-forge credential; it never stores or trusts the raw secret — prove identity, then store proof, not the password.
✨ Added by the guide to build intuition — not from the source course.
Lessons in this topic
🎯 Guided practice
Easy — Tell authentication from authorization. A user logs in successfully, then tries to delete another user's post and gets blocked. Which step blocked them?
Reasoning: (1) Login succeeded → the authentication step passed; the system confirmed who they are. (2) The block happened when deciding what they may do to a resource they don't own. (3) That "what are you allowed to do" decision is authorization. Pattern: authn establishes identity once; authz uses that identity on every protected action. They are always two distinct checks — name them separately in an interview.
Medium — Choose a token strategy for "Sign in with Google" across 10 microservices. Users authenticate via Google; your services must trust the result without each one re-asking Google.
Reasoning: (1) Delegated identity from a third party is the textbook case for OpenID Connect (the authentication layer on top of OAuth 2.0) — Google is the identity provider and returns a signed ID token (JWT) proving who the user is. (2) Your edge/gateway validates that ID token and typically mints your own short-lived access token (also a signed JWT) for internal calls; with 10 stateless services, a central session lookup on every call is a bottleneck, so each service verifies the token's signature locally using the issuer's published public key (JWKS) — an O(1) check, no shared DB. (3) The cost of stateless: you can't revoke a JWT before it expires. Mitigate with short-lived access tokens (minutes) plus a refresh token that mints new ones, so a stolen token dies quickly; for hard revocation, keep a small deny-list of token IDs. (4) Never put secrets in the payload — a JWT is signed (tamper-evident) but not encrypted, so its claims are readable by anyone holding it. Pattern: third-party identity → OIDC; scale + statelessness → short-lived signed JWTs verified via JWKS, plus refresh tokens to cover the revocation gap.
✨ Added by the guide — work these before the full problem set.