Skip to the chapter
←System DesignGGroundworkSDSystem Design
System Design/Intermediate/I11
18 / 36 written chapters
/

The cover
  1. B1The mental model
  2. B2Client-server basics
  3. B3Vertical vs horizontal
  4. B4Databases in design
  5. B5Caching fundamentals
  6. B6APIs & communication
  7. B7Walkthrough: URL shortener
  1. I1Load balancing in depth
  2. I2CDNs
  3. I3Message queues & async
  4. I4Consistency models
  5. I5Replication
  6. I6Rate limiting & throttling
  7. I7Designing for availability
  8. I8Storage systems
  9. I9Search systems
  10. I10Microservices
  11. I11Security basics
  12. I12Walkthrough: feed/chat
  13. I13Walkthrough: notifications
  1. A1CAP theorem in depth
  2. A2Transactions and isolation
  3. A3Storage engines
  4. A4Sharding at scale
  5. A5Time, ordering and IDs
  6. A6Distributed consensus
  7. A7Batch & stream processing
  8. A8Fault tolerance
  9. A9Observability at scale
  10. A10Release safety
  11. A11Capacity estimation
  12. A12Case studies
  13. A13Walkthrough: key-value store
  14. A14Walkthrough: web crawler
  15. A15Walkthrough: payments
  16. A16Tradeoff thinking

SDI11 · Part 2 · Intermediate

Security basics for design

Who is calling, what may they do, and what happens on the day a secret leaks.

13 min read1 diagram9 sections0 exercises
18 of 36

In this chapter

  • Start with the threat, not the checklist
  • Authentication is who you are; authorization is what you may do
  • Sessions, tokens and OAuth: what each one is for
  • Passwords, passkeys and second factors
  • Authorization models: roles, attributes and relationships

and 4 more

about 13 min
09On this page
  1. Start with the threat, not the checklist
  2. Authentication is who you are; authorization is what you may do
  3. Sessions, tokens and OAuth: what each one is for
  4. Passwords, passkeys and second factors
  5. Authorization models: roles, attributes and relationships
  6. Encryption: in transit, at rest, and who holds the keys
  7. The attacks an interviewer expects you to name
  8. Dry run: reviewing a small design for flaws
  9. Recognizing it in an unseen problem

Start with the threat, not the checklist

Security in a design interview is not a list of acronyms. It is three questions asked in order: what are we protecting (accounts, payment data, other people's private messages), who might attack it (an anonymous visitor, a logged-in user going after someone else's data, an employee, a compromised dependency) and what do they gain if they succeed. Once you can say "the worst case here is one user reading another user's orders", every control you add has a reason, and every control you leave out is a decision you can defend.

Two habits carry most of the weight. Defense in depth: assume any single control will fail, so a stolen token should still be short-lived, still be scoped, still be logged. Least privilege: every user, service and credential gets only what its job needs, so a leak of one does not open everything.

Authentication is who you are; authorization is what you may do

Authentication establishes identity (a password, a passkey, a token). Authorization decides whether that identity may do this thing to this object. The two are separate checks, and the second is the one that fails in real systems: broken access control is the first category of the OWASP Top 10 in both the 2021 and the 2025 editions. The classic form is the insecure direct object reference. A request for GET /orders/8731 is authenticated, so the server returns the order, never checking that order 8731 belongs to the caller. Changing the number in the URL then walks through every customer's orders.

⚠ Check ownership on the server, on every request, deny by default Hiding a button or an id in the client protects nothing. The rule that holds up is: every handler loads the object, checks that the caller may touch this object with this action, and refuses when no rule says yes. A check that exists only in the gateway is not enough, because a second route or an internal caller skips it.

Sessions, tokens and OAuth: what each one is for

MechanismWhat it isStrengthWeakness
Session cookieA random id pointing at server-side stateYou can revoke it instantly by deleting the rowNeeds a shared session store once you have several servers
Opaque access tokenA random string the API checks with the auth serverRevocable, and carries no claims (though a leaked one is still a usable bearer token)An extra call per request, unless you cache the answer
JWT access tokenA signed, self-contained token: identity and claims insideAny service verifies it locally with a public key, no lookupCannot be revoked before it expires, so keep it short-lived (minutes)
Refresh tokenA longer-lived credential that only mints new access tokensLets the access token stay shortA stolen one is powerful: rotate it on every use and store it carefully

OAuth 2.0 is a framework for delegated authorization: a user lets one application act on their behalf at another without giving it their password. It is not a login protocol by itself. OpenID Connect adds an ID token on top, which is the part that says who the user is. For a browser or mobile app the flow is the authorization code flow with PKCE: the app sends the user to the identity provider with a hashed one-time challenge, the provider returns a short-lived code, and the app exchanges the code plus the original secret for tokens. The current OAuth security best-practice document (RFC 9700) says public clients must use PKCE, that the password grant must not be used and the implicit grant should not be, and that redirect URIs must match exactly.

your app makes a verifier identity provider signs the user in your API checks the token 1 hash of verifier, exact redirect 2 one-time code 3 code + verifier → tokens (to the provider) 4 short-lived access token, rotated refresh token a stolen code is useless without the verifier, which is never sent on the redirect
PKCE exists so that an attacker who intercepts the authorization code cannot trade it for tokens. Step 3 goes to the provider's token endpoint, not through the browser address bar.

JWT pitfalls are worth naming, because the format looks safer than it is. RFC 8725 lists them. Verify the signature with the algorithm you expect, never the one the token's own header claims, and reject none. Check the issuer, the audience and the expiry on every use. The payload is only base64url encoded, so anyone can read it: never put a secret in it. Plan key rotation with a key id so that you can publish a new key before retiring the old one. And on the client, a cookie marked HttpOnly keeps the token away from scripts (Secure and SameSite limit where it is sent), while a token in localStorage is readable by any cross-site scripting bug. A script can still make requests from the page while it is open, and cookies bring request forgery back, so neither choice replaces fixing the script bug.

Passwords, passkeys and second factors

Never store a password, and never store anything that can be turned back into one. Store the output of a slow, memory-hard hash with a unique random salt per user. The OWASP password storage cheat sheet puts Argon2id first, with minimum settings of about 19 MiB of memory, 2 iterations and 1 degree of parallelism, then scrypt, and keeps bcrypt (work factor of at least 10, and a 72-byte input limit) for legacy systems; PBKDF2 at a very high iteration count is the option where FIPS validation is required. A pepper, a secret kept outside the database, adds defense in depth, but it is not a substitute for the salt and the slow hash. Compare hashes in constant time and rate limit the login endpoint (see the rate limiting chapter), keyed by address as well as by account.

The stronger move is to need fewer passwords. A passkey (WebAuthn) is a public-key credential held by the user's device: the server stores only a public key, so there is nothing to phish and nothing to leak from your database that an attacker can replay on another site. A second factor (a one-time code, a hardware key) limits the damage when a password is stolen anyway.

Authorization models: roles, attributes and relationships

ModelRule looks likeGood forStrain
RBAC (roles)"Admins can delete projects"Internal tools, a small fixed set of job typesRole explosion once each team and project needs its own variation
ABAC (attributes and policies)"Editors can edit documents in their own department during business hours"Rules that depend on contextPolicies get hard to audit and test
ReBAC (relationships)"A user can view a document if they are a viewer of its folder, or a member of a group that is"Sharing graphs: documents, folders, teamsNeeds a store built for graph checks and a plan for consistency

Google's Zanzibar paper describes the relationship model at scale: access is stored as tuples of the form object, relation, user, and a check walks them, which is how one system answers "may Alice open this file?" for Drive, Photos and YouTube. Where it gets hard is exactly the part earlier chapters warned about: a permission cache is a replica, so a revoked permission keeps working for as long as a stale answer lives. Decide how stale an authorization answer may be, and let the sensitive actions bypass the cache.

Encryption: in transit, at rest, and who holds the keys

  • In transit: TLS everywhere, including between your own services, because a flat internal network is not a security boundary. Mutual TLS makes both ends present certificates, which gives each service a verifiable identity (a service mesh automates the certificates).
  • At rest: disk or volume encryption protects against a stolen disk and a discarded server. It does nothing against an attacker who gets your application's credentials, because the application sees decrypted data. For sensitive fields (card numbers, national ids) encrypt or tokenize them in the application so the database never holds plaintext.
  • Envelope encryption: a key management service holds a root key (AWS calls it a KMS key) that never leaves it. For each object you generate a data key, encrypt the data with it, then encrypt the data key with the master key and store the two together. Changing the wrapping key means re-wrapping small data keys, not re-encrypting terabytes (AWS KMS's automatic rotation keeps the old key material, so even that is needed only when you move to a new key).
  • Secrets: keep them in a secrets manager, inject them at runtime, give them a short life or rotate them, and never commit them to a repository, bake them into an image or write them to a log. A leaked secret should mean "rotate and redeploy", not "emergency".

The attacks an interviewer expects you to name

AttackWhat happensDesign-level defence
Injection (SQL, command)Input is interpreted as codeParameterized queries, never string-built SQL; validate on the server
Cross-site scriptingAn attacker's script runs in your page and reads tokens or acts as the userEncode output by context, a restrictive Content Security Policy, HttpOnly cookies
Cross-site request forgeryAnother site makes the user's browser send an authenticated requestSameSite cookies, anti-forgery tokens on state-changing requests
Server-side request forgeryYou fetch a URL the attacker chose, and reach an internal service or the cloud metadata addressAllowlist outbound destinations, resolve and then pin the address (against DNS rebinding), disable redirects, restrict egress at the network layer, and on AWS require the token-based IMDSv2 metadata service
Credential stuffingLeaked passwords from other sites are tried against yoursRate limits by address and device, breached-password checks, passkeys and a second factor
Denial of serviceVolume or expensive requests exhaust capacityCDN and edge filtering, per-client limits and load shedding (see those chapters)
Supply chainA dependency or build step is compromisedPin and verify dependencies, scan them, build from a clean, reviewed pipeline

Dry run: reviewing a small design for flaws

A notes app stores each user's notes. Its API is GET /notes/{id}. Login returns a JWT valid for 24 hours, which the single-page app keeps in localStorage. Passwords are stored as an unsalted SHA-256 of the password. A design review finds four problems.

FlawWhat an attacker doesFix
The handler returns any note by idLoops over ids and reads everyone's notesCheck note.owner == caller in the handler; use random ids as a second layer, not the first
24-hour token in localStorageOne cross-site scripting bug steals a token that works for a dayCookie with HttpOnly, Secure and SameSite; a 10 to 15 minute access token plus a rotating refresh token
Unsalted fast hashAfter a database leak, the same hash means the same password, and guessing is cheapArgon2id with a per-user salt
No limit on login attemptsCredential stuffing runs with nothing slowing it downPer-address and per-account limits and a breached-password check

How cheap is the guessing? An eight-letter lowercase password has 268 = 208,827,064,576 possibilities. At an illustrative 10 billion fast hashes a second on a single modern graphics card, that is about 21 seconds to try every one. A memory-hard hash with a salt does not make a bad password good, but it turns a 21-second job into one that costs real money per guess and cannot reuse work across users.

Say it like this → "First the worst case: one user reading another's data, so every handler checks ownership, not just the gateway. Login is the authorization code flow with PKCE through a managed identity provider, with a 15-minute access token in an HttpOnly cookie and a rotating refresh token. Passwords, if we hold any, are Argon2id with a per-user salt, and I'd offer passkeys. Services talk over mutual TLS, secrets come from a secrets manager and rotate, and sensitive fields are encrypted in the application with envelope keys. I'd rate limit login by address and account, and log every authorization failure."

Recognizing it in an unseen problem

  • Signals: any mention of users, accounts, payments, health data, multi-tenant data, or a third-party login. Say the security section out loud even if the prompt does not ask: it is expected at senior level.
  • The naive design authenticates at the edge and trusts everything behind it. Name the missing per-object authorization check, the long-lived token and the plaintext secrets.
  • Multi-tenant prompts (one service, many customers) make the tenant id part of every key, query and cache entry. A missing tenant filter is the data-leak bug.
  • Distinguish authentication, authorization and encryption: they fail in different ways and need different fixes.
  • Quantify the blast radius: "a leaked access token is good for 15 minutes and one scope" is a design statement. "We use JWT" is not.
  • The pitfall: inventing your own cryptography or token format. Use a managed identity provider, a standard flow and a vetted library.
Before you move on
  • State the difference between authentication and authorization, and give the object-reference bug as an example of the second failing.
  • Describe the authorization code flow with PKCE and say what attack the verifier prevents.
  • Say why a JWT cannot be revoked early, and what you do about it.
  • Say how you store a password and why a fast hash is the wrong tool.
  • Explain envelope encryption and what changing the wrapping key costs.
  • Name four attacks and the design-level defence for each.
Sources and further reading
  • OWASP Top 10 (2025 edition) — the current list of web application risks, with broken access control first
  • RFC 9700: OAuth 2.0 security best current practice — PKCE, exact redirect matching, no implicit or password grants
  • RFC 7636: Proof Key for Code Exchange — the verifier and challenge mechanism
  • RFC 6749: the OAuth 2.0 framework — roles, grants and tokens
  • RFC 8725: JSON Web Token best current practices — algorithm checks, audience and issuer validation
  • OWASP password storage cheat sheet — Argon2id minimums, bcrypt limits, pepper
  • NIST SP 800-63B: authentication and lifecycle management — password and authenticator guidance
  • W3C Web Authentication — passkeys and public-key credentials
  • Zanzibar: Google's consistent global authorization system — relationship tuples and checks at scale
  • AWS KMS: cryptography basics — data keys, master keys and envelope encryption

Claims in this chapter were checked against these sources in October 2026. The hash rate in the dry run is an illustrative figure.

✓Practise

5 questions drawn from 7, scored out of 5. This is practice: it runs in your browser, saves nothing and does not change what you have marked read.

I11

Finished reading?

0 of 36 chapters read in this series

→Next stop

  1. I10Previous · I10Microservices and service discovery
  2. I11you are here
  3. Next · I12Walkthrough: a news feed / chat appFan-out on write, fan-out on read, and the hybrid that exists because one account has 150 million followers.23 min read

01On this page

9 sections · 0%

  1. 01Start with the threat, not the checklist
  2. 02Authentication is who you are; authorization is what you may do
  3. 03Sessions, tokens and OAuth: what each one is for
  4. 04Passwords, passkeys and second factors
  5. 05Authorization models: roles, attributes and relationships
  6. 06Encryption: in transit, at rest, and who holds the keys
  7. 07The attacks an interviewer expects you to name
  8. 08Dry run: reviewing a small design for flaws
  9. 09Recognizing it in an unseen problem

[] chapters · t top