1. Authentication vs. Authorization at Scale
Authentication answers "who are you?"; authorization answers "what are you allowed to do?" — conflating them is a common design mistake: a system that only checks "is this a valid logged-in user?" without a separate check for "is this specific user allowed to do this specific thing to this specific resource?" will happily let a logged-in user edit someone else's data.
Request: DELETE /orders/8821, from user_id 4821
1. AuthN: is this request's token valid, and whose is it?
--> yes, it belongs to user 4821
2. AuthZ: does user 4821 have permission to delete order 8821?
--> check: is 4821 the owner of order 8821, or an admin?
--> if neither: reject with 403, even though AuthN succeeded
At scale, authentication is usually centralized in one identity provider (issuing tokens that every service can verify independently, often JWTs — Week 21 of the React course covers the client side of this), while authorization is typically pushed as close to the resource as possible — the Order Service itself decides whether a given user can act on a given order, rather than a central gatekeeper trying to know every service's permission rules. This mirrors Week 15's bounded context principle: each service owns the authorization logic for the data it owns.
In an interview, describing a system as secure because "requests are authenticated" leaves the more important question unanswered: authenticated to do what? Naming the specific authorization check — ownership, role, resource-level permission — that runs on the sensitive action itself is what actually demonstrates the distinction is understood.
2. Encryption in Transit & at Rest
These protect against two different threats, and a system needs both — one doesn't substitute for the other.
- Encryption in transit (TLS) protects data while it's moving across a network — between a client and the API gateway, and increasingly between services themselves (Week 16's service mesh often provides this automatically via mutual TLS). It defends against an attacker intercepting traffic on the wire.
- Encryption at rest protects data while it's stored — on disk, in a database, in a backup. It defends against a completely different threat: someone gaining access to the underlying storage (a stolen disk, a misconfigured backup bucket, a compromised database snapshot) without ever touching the network.
A system with TLS everywhere but an unencrypted database is fully protected against network eavesdropping and fully exposed the moment that database's storage is accessed directly — the two controls address non-overlapping attack surfaces, which is exactly why "we use HTTPS" is an incomplete answer to "is this data protected."
3. Secrets Management
Database passwords, API keys, and encryption keys themselves are a special category of data: if they leak, they compromise everything they protect. Two rules cover most of what a design needs to get right here.
WRONG:
DATABASE_PASSWORD = "hunter2" // hardcoded in source code
-- now in git history forever, visible to anyone with repo
access, and rotating it means a code change + redeploy
RIGHT:
DATABASE_PASSWORD = secretsManager.get("prod/db/password")
-- fetched at runtime from a dedicated secrets store (e.g.
Vault, AWS Secrets Manager), never committed to source
control, rotatable without a code change or redeploy
The second rule is least privilege: a service should be able to fetch only the specific secrets it actually needs, not every secret in the system. If the Notification Service is compromised, it should never have had access to the Payment Service's database credentials in the first place — least privilege limits the blast radius of any single service being breached, rather than relying on every service being perfectly secure all the time.
A useful question to ask about any secrets design: "if this credential leaked right now, how long would it take to fully rotate it, and what breaks while that's happening?" A design where rotation means editing source code and redeploying every service is a much weaker design than one where rotation is a single API call to a secrets store that every service re-reads automatically.
4. Deep Dive: Designing for DDoS Resilience
Every system this course has designed assumes traffic is trying to use the system. A distributed denial-of-service (DDoS) attack is traffic trying to overwhelm it — often by simple volume, from many sources at once, making it impossible to block with a single IP-based rule.
[Attacker traffic, many sources]
|
v
[CDN / Edge Network] -- absorbs and filters volumetric traffic
| far from your own infrastructure (Week 2);
| many attacks never reach past this layer
v
[Rate Limiter / WAF] -- Week 11's algorithms, now defending
| against abuse instead of just fair use;
| blocks patterns that look automated
v
[API Gateway] -- authenticated, legitimate traffic only
| reaches this point
v
[Your Services]
The core idea worth stating explicitly: absorb and filter as far from your own infrastructure as possible. A CDN or edge network (Week 2) has vastly more capacity than any single system's own servers, so pushing the first line of defense there means most volumetric traffic never reaches infrastructure that could actually be overwhelmed. Week 11's rate limiter, originally designed for fair usage among legitimate clients, is repurposed here as an abuse filter — the same algorithms (token bucket, sliding window), applied against a different kind of traffic pattern.
A second, less obvious risk: a system that gracefully degrades under a DDoS by serving cached or simplified responses is far more resilient than one that fails completely — Week 6-7's caching strategies double as a DDoS mitigation, since a flood of read requests hitting a cache never reaches the database at all, while a flood hitting an uncached endpoint can take the database down even at moderate request volume.
5. Hands-on Exercise
Secure the ride-booking system from Week 15
Week 15's decomposed ride-booking system (Order, Inventory, Shipping-equivalent services) currently has no explicit security design.
Requirements:
- Design the authentication flow: where tokens are issued, and how a downstream service (say, the Trip Service) verifies a request's token without calling back to the identity provider on every single request.
- Design one concrete authorization check for "a rider can view their own trip history, but not another rider's" — name which service owns that check and what it actually verifies.
- Identify one piece of data in this system that needs encryption at rest specifically (not just in transit), and justify why.
- Propose a secrets management approach for the Trip Service's database credentials, applying the least-privilege principle from Section 3.
- Sketch a layered DDoS defense (Section 4) for the public trip-request endpoint, naming what each layer filters out before it reaches your services.
For requirement 1: a signed token (like a JWT) that a service can verify using only a shared public key avoids calling back to the identity provider per-request — the token itself carries enough information to be checked locally, which matters a lot once dozens of services are each handling many requests per second.
6. Knowledge Check
Four quick questions. Expand each to check your answer.
Q1
A system correctly verifies every request comes from a logged-in user, but any logged-in user can edit any other user's order. What's missing?
A system correctly verifies every request comes from a logged-in user, but any logged-in user can edit any other user's order. What's missing?
Authorization. The system has authentication (confirming who the user is) but no authorization check verifying that specific user has permission to act on that specific resource — the two are different checks, and a valid identity alone doesn't imply permission to do anything to anything.
Q2
Why is "we use HTTPS everywhere" an incomplete answer to whether user data is fully protected?
Why is "we use HTTPS everywhere" an incomplete answer to whether user data is fully protected?
HTTPS/TLS only protects data in transit, defending against network interception. It does nothing to protect data at rest — a stolen disk, a misconfigured backup, or direct access to an unencrypted database bypasses TLS entirely, since that data was never moving across a network in that scenario. Both protections are needed because they defend against different attack surfaces.
Q3
Why does the least-privilege principle matter for secrets management specifically, beyond just "don't hardcode secrets in source code"?
Why does the least-privilege principle matter for secrets management specifically, beyond just "don't hardcode secrets in source code"?
Least privilege limits the blast radius of a single service being compromised — if a low-risk service like Notifications never had access to Payment's database credentials, compromising Notifications doesn't expose Payment's data. Without it, every service effectively has access to every secret, so any one service's compromise becomes a compromise of the entire system.
Q4
Why does a layered DDoS defense push filtering as far from your own infrastructure as possible (CDN/edge first, rate limiter second)?
Why does a layered DDoS defense push filtering as far from your own infrastructure as possible (CDN/edge first, rate limiter second)?
A CDN or edge network has vastly more capacity than any single system's own servers, so absorbing and filtering volumetric traffic there means most of an attack never reaches infrastructure that could actually be overwhelmed. Filtering only at your own API gateway means the attack traffic has already consumed your own network capacity before any defense runs.