Dev Learning

Authentication, authorization and secrets

Who are you, what are you allowed to do, and where do the keys live.

1

What problem does these controls solve?

Every design has a box labelled "auth" that nobody explains. Then the interviewer asks how a request proves who it is across five services, and the answer falls apart.

Two different questions hide behind one word. Authentication is proving who you are. Authorization is deciding what you may do. They fail differently, they live in different places, and mixing them up is a classic mistake in this area.

2

What these controls costs you

What it costs you
Security is friction you pay on every request, forever. Checking a token costs time. Checking permissions properly usually costs a lookup. Short token lifetimes mean more refreshes; long ones mean a stolen token stays useful for longer. Encryption costs CPU and makes debugging harder because you can no longer read what is going past. And every one of these is a place where being slightly wrong is much worse than being slow.

Every concept in here states a cost. A technique with no price is a technique you have not understood yet — and naming the cost out loud is most of what separates a senior answer from a junior one.

3

When to reach for these controls, and when not to

Use it when

  • Any system with users. Say how a request proves who it is, once, early, and move on.
  • Any public API. The auth model decides the rate limiting story too.
  • Anywhere one user's data must not reach another user. Which is everywhere.
  • Whenever the design crosses a trust boundary: browser to server, your company to a partner.

Do not, when

  • Do not design your own crypto, token format or password hashing. Use what exists. Saying that is the correct answer.
  • Do not spend ten minutes on auth in a 45-minute interview unless it is the question. State the model in two sentences and move to the part they asked about.
4

How these controls actually works

A
Stateless token (JWT)
  • —The token carries the claims and a signature. Any service can verify it with a public key.
  • —No lookup on the auth path, so it scales without a shared store.
  • —You cannot revoke it. It stays valid until it expires.
  • —Fix: keep lifetimes short (minutes) with a refresh token, plus a small deny list.
  • —Right for: service-to-service calls, and short-lived access tokens.
B
Opaque session token
  • —The token is a random id. The truth lives in a session store.
  • —Revocation is instant: delete the row and the session is gone.
  • —Every request costs a lookup, so that store is now on your critical path.
  • —Mitigated by caching, which brings back a revocation delay as long as the cache TTL.
  • —Right for: browser sessions, anywhere "log out everywhere" must work now.
Which one: The common hybrid in production: a short-lived stateless access token for the request path, plus a long-lived opaque refresh token held in the session store. You get verification with no lookup, and revocation that takes effect within the access token's lifetime rather than never.
The one decision that shapes everything else: is the token self-describing, or is it a lookup key?

Authentication. A user proves who they are once, and gets a token. Passwords are stored as a slow hash (bcrypt, scrypt or argon2), never encrypted and never in plain text. They are slow on purpose, to make guessing expensive. The credential check should also be rate limited per account and per IP, because that endpoint is the one people attack.

OAuth and OIDC, in one paragraph, because people quote the names without the meaning. OAuth is about *delegated access*: it lets one application act on a user's behalf at another service without ever seeing their password. That is what "sign in with Google" is doing underneath. OIDC is a thin layer on top of OAuth that adds identity: an ID token that says who the user is, not just what you may do. If you are asked why not just take the user's password for the other service, the answer is that a password is unlimited and permanent, and a token is scoped and expiring.

Authorization is the part that gets skipped and the part that leaks data. Two models cover almost everything. *Role-based*: a user has roles, and roles grant permissions. Simple, and it breaks the moment permissions depend on the specific object: "an editor, but only on documents in their team". *Attribute or relationship based*: the decision is computed from the user, the object and the context. More powerful, more expensive, and it usually needs its own service so the rules live in one place instead of being scattered across every endpoint.

The rule that matters more than the model: check authorization at the point of data access, not at the edge. A gateway can confirm a request has a valid token. It usually cannot know that document 91 belongs to a different tenant. If the check lives only in the gateway, then the first internal service that forgets it leaks data. Every query should be scoped by the caller's identity, and the safest designs make it hard to write a query that is not.

Between services. Do not let internal calls be unauthenticated just because they are on a private network. Breach write-ups often describe an attacker moving freely once inside the network. Use mutual TLS, or signed service tokens, and pass the end user's identity along explicitly so the service doing the data access can make the real decision. Also decide whether a service is acting for itself or on behalf of a user, because those are different permissions.

Secrets. Keys and credentials do not live in the repository, in an environment variable pasted by hand, or in a config file. They live in a secret manager, they are injected at runtime, and they can be rotated without a code change. Say "rotatable" out loud, because the likely follow-up is what you do when a key leaks, and the answer has to be better than "redeploy everything".

Encryption, briefly and correctly. In transit means TLS everywhere, including inside your network. At rest means the disk or the field is encrypted, which mostly protects you against a stolen backup or a disposed disk. It does nothing against an attacker who has valid application credentials, and saying so shows you understand what it buys. Sensitive fields can be encrypted individually so that even a database dump is not enough, at the cost of not being able to query them.

Common trap
  • Saying "JWT" and then promising instant logout everywhere. Pick one.
  • Checking permissions only at the gateway, so any internal service that forgets leaks data.
  • Trusting internal calls because they are on a private network.
  • Secrets in environment variables or config files, with no rotation story.
  • Designing your own token format or password hashing.
Say this
"Short-lived signed access tokens so services verify without a lookup, plus an opaque refresh token in a session store so logout actually works within fifteen minutes. Authorization is checked at data access: every query is scoped by the caller, not just by the gateway. Secrets come from a secret manager and are rotatable without a deploy."
5

The these controls follow-up an interviewer will ask

"A user clicks log out on their laptop. How fast does that take effect on their phone?"

What a strong answer sounds like

It depends on the token design, and this question shows whether someone has shipped auth. With opaque session tokens, instantly: the session row is deleted, and the next request from any device fails its lookup. With stateless JWTs, not at all until the token expires, because every service can verify that token on its own without asking anybody, which is the property that made it fast. That is the trade JWTs make, and the mistake is choosing them and then promising instant revocation. What I would build is the hybrid: an access token with a five to fifteen minute life, and a refresh token that lives in a session store. Logging out deletes the refresh token, so the phone keeps working for up to fifteen minutes and then cannot renew. If the product needs immediate revocation (a compromised account, a fired employee), I would add a small deny list of revoked token ids, checked on the request path and cached, which is cheap because it only ever holds tokens revoked in the last fifteen minutes. Cost: I have put a lookup back on the critical path for the case I said I was avoiding, so I would apply it only where it matters.

6

Your turn

60-second self-check

Your API gateway validates the token on every request. Is that enough to stop user A reading user B's invoice? Explain.

Stuck? Take one hint at a time0 of 2 used
0 / 25 characters
7

Learn it from the source

This page gets you interview-ready. These take you to where the idea is actually specified or measured — read them when you want the real depth.

Where you will use this