System Design course menu
Security Basics for System Design
Security concepts for design interviews: authentication and authorisation, sessions and JWT, OAuth, encryption in transit and at rest, password hashing, and protecting against abuse.
On this page
Security is part of design, and not something to add at the end. A short, confident security discussion also stands out in an interview.
Authentication and authorisation#
- Authentication: who are you?
- Authorisation: what are you allowed to do?
A 401 response means that you are not signed in, and 403 means that you are not allowed.
Sessions or tokens#
A JWT is signed, not encrypted, so anyone can read its contents. The signature shows that it has not been changed:
import base64
import hashlib
import hmac
import json
secret = b"demo-secret-not-for-real-use"
def b64(data):
return base64.urlsafe_b64encode(data).rstrip(b"=").decode()
def sign(payload):
body = b64(json.dumps(payload).encode())
sig = b64(hmac.new(secret, body.encode(), hashlib.sha256).digest())
return f"{body}.{sig}"
def verify(token):
body, sig = token.split(".")
good = b64(hmac.new(secret, body.encode(), hashlib.sha256).digest())
return hmac.compare_digest(sig, good)
token = sign({"user": 42, "role": "user"})
print("Valid:", verify(token))
body, sig = token.split(".")
fake = b64(json.dumps({"user": 42, "role": "admin"}).encode())
print("Changed payload valid:", verify(f"{fake}.{sig}"))Valid: True
Changed payload valid: FalseThis shows the idea. Use a tested library in real code, such as the one in Authentication with JWT.
Short-lived access tokens, with a longer-lived refresh token, reduce the damage if a token leaks.
OAuth and single sign-on#
OAuth 2 lets a user allow an app to act for them without sharing a password, as in "Sign in with Google". OpenID Connect adds login on top of it. Prefer these to building your own login, if you can.
Passwords#
Never store passwords as plain text, or with a fast hash such as SHA-256. Use a slow algorithm made for passwords, such as bcrypt or Argon2, with a unique salt for each user. Salts make the same password look different:
import hashlib
import os
for salt in (b"salt-one", b"salt-two"):
h = hashlib.pbkdf2_hmac("sha256", b"hunter2", salt, 100_000)
print(h.hex()[:24])6028ca1550471792a5e0aa26
1be9d41053797afd2bcc7cabAdd two-factor authentication for sensitive accounts.
Encryption#
Authorisation models#
A very common bug is forgetting the ownership check. If GET /orders/1001 does not check who is asking, anyone can read any order.
Least privilege and defence in depth#
- Give each user and service only what it needs.
- Use several layers, so that one failure is not fatal.
- Keep databases on private networks.
- Keep secrets in a secret manager, not in code.
Common attacks#
Common mistakes#
Practice#
Practice exercise
Decode the payload of the token above without using the secret, to show that it is not encrypted.
Show solution
body = token.split(".")[0]
padded = body + "=" * (-len(body) % 4)
print(base64.urlsafe_b64decode(padded).decode()){"user": 42, "role": "user"}Key takeaway#
Next: Design a URL Shortener.
Finished this lesson?
Related lessons
Recommended System Design resources
- System Design Interview by Alex Xu
Step-by-step walkthroughs of common design questions, for interview preparation.
Some links are affiliate links. If you buy through them, Laviyx Learn may earn a commission at no extra cost to you. As an Amazon Associate, we earn from qualifying purchases.