19. Security Basics for System Design

Security is a cross-cutting concern that must be considered at every layer of a system. A single vulnerability can compromise an entire architecture.


Security Principles

Principle Description
Defense in depth Multiple layers of security; no single point of failure
Least privilege Grant minimum permissions necessary
Zero trust Never trust, always verify — even internal traffic
Fail secure On failure, deny access rather than allow
Separation of duties No single entity has full control
Security by design Build security in from the start, not as an afterthought

Authentication

Verifying who you are.

Methods

Method Description Use Case
API Keys Static secret passed in header/query Server-to-server, public APIs
Username/Password Basic credentials User login
OAuth 2.0 Delegated authorization framework Third-party access, SSO
JWT (JSON Web Tokens) Self-contained signed tokens Stateless auth, microservices
mTLS Mutual TLS certificate verification Service-to-service in service mesh
SAML XML-based SSO Enterprise SSO
Multi-factor (MFA) Password + second factor (OTP, TOTP, hardware key) High-security accounts

JWT (JSON Web Token)

Header.Payload.Signature

Header:   {"alg": "RS256", "typ": "JWT"}
Payload:  {"sub": "user-123", "role": "admin", "exp": 1705312800}
Signature: HMAC-SHA256(base64(header) + "." + base64(payload), secret)
Client → Login (username/password) → Auth Service
Auth Service → Verify credentials → Issue JWT → Client
Client → Request + JWT (Authorization: Bearer <token>) → API Service
API Service → Verify JWT signature → Extract claims → Process request

JWT Pros: Stateless (no session store), self-contained, works across services.
JWT Cons: Can't be revoked before expiration (without a deny-list), token size overhead.

OAuth 2.0 Flows

Flow Use Case
Authorization Code Web apps (most secure)
Authorization Code + PKCE Mobile/SPA apps
Client Credentials Server-to-server
Device Code IoT, TV apps
Authorization Code Flow:
1. Client → Auth Server: "User wants to log in" (redirect)
2. Auth Server → User: "Enter credentials" (login page)
3. User → Auth Server: Credentials
4. Auth Server → Client: Authorization Code (redirect)
5. Client → Auth Server: Exchange code for tokens (server-side)
6. Auth Server → Client: Access Token + Refresh Token

Authorization

Verifying what you can do.

Models

Model Description
RBAC (Role-Based Access Control) Permissions assigned to roles; users assigned to roles
ABAC (Attribute-Based Access Control) Permissions based on attributes (user, resource, environment)
ACL (Access Control List) Explicit list of who can access what
ReBAC (Relationship-Based Access Control) Permissions based on relationships (e.g., "owner of document")

RBAC Example

Roles:
  admin  → [read, write, delete, manage_users]
  editor → [read, write]
  viewer → [read]

Users:
  Alice → admin
  Bob   → editor
  Carol → viewer

Request: Bob tries to DELETE /resource/123
→ Bob has role "editor" → "editor" doesn't have "delete" → 403 Forbidden

Encryption

At Rest

Data stored on disk is encrypted.

Application → Plaintext → [Encryption (AES-256)] → Ciphertext → Disk
Disk → Ciphertext → [Decryption] → Plaintext → Application

Types:
| Type | Description |
|------|-------------|
| Server-side encryption (SSE) | Cloud provider encrypts/decrypts (S3, RDS) |
| Client-side encryption | Application encrypts before sending to storage |
| Transparent Data Encryption (TDE) | Database handles encryption automatically |

In Transit

Data moving over the network is encrypted.

Client ←─[TLS 1.3]─→ Server
Service A ←─[mTLS]─→ Service B

Always use HTTPS in production. No exceptions.

Key Management

Service Provider
AWS KMS AWS
Cloud KMS Google Cloud
Azure Key Vault Azure
HashiCorp Vault Open source / enterprise

Principles:

  • Never hardcode secrets in code.
  • Rotate keys regularly.
  • Use envelope encryption (data key encrypted by master key).
  • Audit key usage.

Common Attack Vectors & Mitigations

SQL Injection

-- Vulnerable:
query = "SELECT * FROM users WHERE id = " + user_input
-- Attacker input: "1; DROP TABLE users;--"

-- Safe: Parameterized queries
query = "SELECT * FROM users WHERE id = $1"
params = [user_input]

Cross-Site Scripting (XSS)

<!-- Vulnerable: -->
<p>Welcome, ${user_input}</p>
<!-- Attacker input: <script>steal_cookies()</script> -->

<!-- Safe: Escape output -->
<p>Welcome, ${escape(user_input)}</p>

Cross-Site Request Forgery (CSRF)

Attacker site → Hidden form → POST to victim.com/transfer?amount=10000
  (using victim's authenticated session cookie)

Mitigation: CSRF tokens, SameSite cookies, checking Origin header.

DDoS (Distributed Denial of Service)

Millions of requests → Your server → Overloaded → Legitimate users can't access

Mitigation:
- CDN (Cloudflare, AWS Shield)
- Rate limiting
- Auto-scaling
- WAF (Web Application Firewall)
- Anycast routing (distribute attack traffic)

Man-in-the-Middle (MITM)

Client ←─[unencrypted]─→ Attacker ←─→ Server

Mitigation: TLS everywhere, certificate pinning, HSTS.

Network Security

Firewall / Security Groups

Internet → [WAF] → [Load Balancer] → [Security Group: Allow port 443]
                                          ↓
                                    [App Servers]
                                    [SG: Allow port 8080 from LB only]
                                          ↓
                                    [Database]
                                    [SG: Allow port 5432 from App only]

Rules:

  • Public subnet: Only load balancers and bastion hosts.
  • Private subnet: App servers (no direct internet access).
  • Data subnet: Databases (only accessible from app servers).

API Security Checklist

Security Measure Description
HTTPS everywhere Encrypt all traffic
Authentication Verify identity on every request
Authorization Check permissions for each resource
Rate limiting Prevent abuse and DDoS
Input validation Validate and sanitize all inputs
Output encoding Prevent XSS
CORS policy Restrict cross-origin requests
HSTS Force HTTPS via Strict-Transport-Security header
CSP Content Security Policy to prevent XSS
No sensitive data in URLs Query parameters are logged; use headers/body
Audit logging Log all security-relevant events
Dependency scanning Check for known vulnerabilities in libraries

Secrets Management

Never store secrets in:

  • Source code
  • Environment variables (unless injected at runtime)
  • Configuration files committed to git

Use instead:
| Tool | Description |
|------|-------------|
| HashiCorp Vault | Centralized secret store with audit, rotation, dynamic secrets |
| AWS Secrets Manager | Managed secret rotation for AWS services |
| AWS Parameter Store | Simple key-value with encryption |
| Kubernetes Secrets | Native K8s secret management (encrypt with external KMS) |
| Doppler, 1Password | Developer-friendly secret management |


Data Privacy

Principle Description
Data minimization Collect only what you need
Purpose limitation Use data only for stated purpose
Anonymization Remove identity from data
Pseudonymization Replace identity with tokens
Right to erasure Users can request data deletion (GDPR)
Encryption Protect data at rest and in transit

Summary

Concept Key Point
Authentication JWT for stateless, OAuth 2.0 for delegation
Authorization RBAC for most systems; ABAC for fine-grained
Encryption TLS in transit, AES-256 at rest, KMS for key management
API security HTTPS + auth + rate limiting + input validation
Network security Defense in depth with security groups and private subnets
Secrets Use Vault or managed secret services; never hardcode

Rule of thumb: Assume every input is malicious. Encrypt everything. Follow the principle of least privilege. Use established libraries and services — never roll your own crypto or auth.