Auth & Authorization: Securing Backend Systems
Authentication proves who you are. Authorization proves what you can do. Both are hard.
Auth & Authorization: Securing Backend Systems
Authentication proves who you are. Authorization proves what you can do. Both are hard.
What you'll learn
- Authentication (who you are) and authorization (what you can do) are separate concerns — don't conflate them.
- Use RS256 (asymmetric JWT signing) in multi-service architectures so services can verify tokens without the signing key.
- JWT payloads are base64url encoded, NOT encrypted. Never store sensitive data in claims.
- Authorization Code + PKCE is the modern OAuth flow for user-facing applications.
- Use RBAC for most applications. Consider ReBAC (Google Zanzibar model) for complex relationship-based permissions.
- Return 401 for missing/invalid identity. Return 403 for valid identity with insufficient permissions.
Lesson outline
The Two Concepts Every Security Bug Conflates
In 2019, a security researcher found that any Twitter user could access any other user's DMs by changing a single user ID in the API request. No authentication bypass needed — just substituting your own session token with a different resource ID. This is authorization failure, not authentication failure.
| Concept | Question | Mechanism | Example |
|---|---|---|---|
| Authentication (AuthN) | "Who are you?" | Password + MFA, OAuth, certificates | "Is this really Alice's session?" |
| Authorization (AuthZ) | "What can you do?" | RBAC, ABAC, ACLs, policies | "Can Alice access Bob's DMs?" |
OWASP #1 and #5: The Most Common Auth Bugs
#1 Broken Access Control (authorization) and #5 Security Misconfiguration are the top two web app vulnerabilities. Most security incidents aren't from exotic exploits — they're from missing authorization checks.
JWTs: The Standard Bearer (and Its Pitfalls)
JSON Web Tokens are the de facto standard for stateless authentication in APIs. Understanding them deeply prevents critical security vulnerabilities.
JWT Anatomy
- 🔵Header — {"alg": "HS256", "typ": "JWT"} — base64url encoded. Declares the signing algorithm.
- 🟢Payload (Claims) — {"sub": "user-123", "exp": 1735689600, "roles": ["admin"]} — base64url encoded. NOT encrypted.
- 🔴Signature — HMAC-SHA256(header + "." + payload, secret) — cryptographic proof the server created this token.
JWT Payload Is NOT Encrypted
JWTs are base64url-encoded, not encrypted. Anyone can decode the payload and read the contents. Never store sensitive data (passwords, PII, credit card numbers) in JWT claims. Only store non-sensitive identifiers.
JWT Vulnerabilities You Must Know
01
alg=none attack: Old libraries accepted tokens with algorithm set to "none" (no signature). Always validate the algorithm in your library.
02
HS256 vs RS256: HS256 uses a shared secret (symmetric). RS256 uses public/private key (asymmetric). Use RS256 for multi-service architectures so services can verify without knowing the signing key.
03
JWT expiry: Short-lived tokens (15 min) + refresh tokens is the production pattern. Long-lived tokens can't be revoked without a blocklist.
04
Key rotation: Rotate signing keys regularly. Use key IDs (kid) in the header so services know which key to use for verification.
alg=none attack: Old libraries accepted tokens with algorithm set to "none" (no signature). Always validate the algorithm in your library.
HS256 vs RS256: HS256 uses a shared secret (symmetric). RS256 uses public/private key (asymmetric). Use RS256 for multi-service architectures so services can verify without knowing the signing key.
JWT expiry: Short-lived tokens (15 min) + refresh tokens is the production pattern. Long-lived tokens can't be revoked without a blocklist.
Key rotation: Rotate signing keys regularly. Use key IDs (kid) in the header so services know which key to use for verification.
1// Production JWT implementation with Node.js2import jwt from 'jsonwebtoken';3import { Request, Response, NextFunction } from 'express';45// ✅ Use RS256 (asymmetric) for multi-service architectures6const JWT_PRIVATE_KEY = process.env.JWT_PRIVATE_KEY!; // Only auth service has thisPrivate key signs, public key verifies. Only auth service needs private key7const JWT_PUBLIC_KEY = process.env.JWT_PUBLIC_KEY!; // All services can verify89interface JWTPayload {10sub: string; // subject = user ID11roles: string[];12iat: number; // issued at13exp: number; // expiration14}1516// Sign token — only call from auth service17function signToken(userId: string, roles: string[]): string {18return jwt.sign(RS256 prevents the alg:none attack and enables services to verify without the signing secret19{ sub: userId, roles },20JWT_PRIVATE_KEY,15 minutes is the production standard for access tokens. Pair with refresh tokens21{22algorithm: 'RS256',23expiresIn: '15m', // Short-lived: 15 minutes24issuer: 'auth-service',25}26);27}2829// Verify middleware — used by all services30function requireAuth(req: Request, res: Response, next: NextFunction) {31const token = req.headers.authorization?.replace('Bearer ', '');Explicitly whitelist algorithms. Never let the client choose the algorithm32if (!token) return res.status(401).json({ error: 'Missing token' });3334try {35const payload = jwt.verify(token, JWT_PUBLIC_KEY, {36algorithms: ['RS256'], // Explicitly allow ONLY RS256 — prevent alg:none attack37issuer: 'auth-service',38}) as JWTPayload;3940req.user = { id: payload.sub, roles: payload.roles };41next();42} catch (err) {43return res.status(401).json({ error: 'Invalid or expired token' });401 = unauthenticated (no valid identity). 403 = unauthorized (valid identity, wrong permissions)44}45}4647// Authorization: role-based check48function requireRole(role: string) {49return (req: Request, res: Response, next: NextFunction) => {50if (!req.user?.roles.includes(role)) {51return res.status(403).json({ error: 'Insufficient permissions' });52}53next();54};55}5657// Usage58router.delete('/admin/users/:id',59requireAuth, // 401 if no valid token60requireRole('admin'), // 403 if not admin61deleteUserHandler62);
OAuth 2.0 and OIDC: The Industry Standard Delegated Auth
OAuth 2.0 is an authorization framework. OpenID Connect (OIDC) is an authentication layer built on top of OAuth 2.0. Understanding the difference prevents building broken "Login with Google" implementations.
| Flow | Use Case | How It Works |
|---|---|---|
| Authorization Code + PKCE | Web apps, mobile apps (RECOMMENDED) | Exchange authorization code for tokens. PKCE prevents code interception attacks. |
| Client Credentials | Machine-to-machine (M2M) | Client ID + Secret → access token. No user involved. |
| Implicit (DEPRECATED) | Old SPA pattern | Token returned directly in URL. Vulnerable to leakage. Never use for new projects. |
| Device Flow | Smart TVs, CLIs | User authorizes on phone/computer while device polls for token. |
The Modern Auth Stack
Authorization Code + PKCE for user-facing apps. Client Credentials for service-to-service. Use an identity provider (Auth0, Cognito, Firebase Auth) instead of building your own — auth is hard to get right and catastrophic when wrong.
OAuth Authorization Code + PKCE Flow
01
App generates code_verifier (random string) and code_challenge (SHA256 hash)
02
App redirects user to Identity Provider with code_challenge
03
User authenticates with Identity Provider (Google, GitHub, etc.)
04
Identity Provider redirects back with authorization code
05
App exchanges code + code_verifier for access token (verifier proves it's the same app)
06
App uses access token for API calls
07
When access token expires, app uses refresh token to get a new one
App generates code_verifier (random string) and code_challenge (SHA256 hash)
App redirects user to Identity Provider with code_challenge
User authenticates with Identity Provider (Google, GitHub, etc.)
Identity Provider redirects back with authorization code
App exchanges code + code_verifier for access token (verifier proves it's the same app)
App uses access token for API calls
When access token expires, app uses refresh token to get a new one
How this might come up in interviews
Auth questions test both security knowledge and system design thinking. Interviewers want to see that you know JWT internals, understand OAuth flows, and can design authorization that scales.
Common questions:
- How would you implement authentication for a multi-service architecture?
- What is the difference between JWT HS256 and RS256? When would you use each?
- How do you handle token revocation with stateless JWTs?
- Design the authorization system for a multi-tenant SaaS application
Strong answers include:
- Mentions PKCE unprompted when discussing OAuth
- Discusses token revocation strategies (blocklist, short expiry + refresh)
- Knows the alg:none JWT attack
- Understands 401 vs 403 distinction
Red flags:
- Stores passwords in plain text or with MD5/SHA1
- Doesn't know what OAuth 2.0 authorization code flow does
- Confuses authentication and authorization
- Uses symmetric signing (HS256) across multiple services
Quick check · Auth & Authorization: Securing Backend Systems
1 / 3
A user with role "editor" tries to delete a post they didn't create. Your API returns 200 OK. What type of vulnerability is this?
Key takeaways
- Authentication (who you are) and authorization (what you can do) are separate concerns — don't conflate them.
- Use RS256 (asymmetric JWT signing) in multi-service architectures so services can verify tokens without the signing key.
- JWT payloads are base64url encoded, NOT encrypted. Never store sensitive data in claims.
- Authorization Code + PKCE is the modern OAuth flow for user-facing applications.
- Use RBAC for most applications. Consider ReBAC (Google Zanzibar model) for complex relationship-based permissions.
- Return 401 for missing/invalid identity. Return 403 for valid identity with insufficient permissions.
From the books
OAuth 2.0 in Action — Justin Richer, Antonio Sanso (2017)
Chapters 1-3: OAuth Fundamentals
OAuth 2.0 is a delegation framework, not an authentication protocol. OIDC adds authentication on top. Confusing the two leads to security vulnerabilities.
Ready to see how this works in the cloud?
Switch to Career Paths for structured paths (e.g. Developer, DevOps) and provider-specific lessons.
View role-based pathsSign in to track your progress and mark lessons complete.
Discussion
Questions? Discuss in the community or start a thread below.
Join DiscordIn-app Q&A
Sign in to start or join a thread.