Chapter 17: User Authentication and Authorization
Why This Exists
An e-commerce platform holds a treasure trove of sensitive data: home addresses, purchase histories, partial credit card numbers, and passwords. If a malicious actor can pretend to be someone else, they can steal data, hijack orders, or lock legitimate users out. User Authentication exists to prove who a user is. Authorization exists to determine what they are allowed to do. Together, they form the security perimeter of the entire application.
Real World Problem
A junior developer builds an API endpoint to view order receipts: GET /api/orders/1005.
They assume that because the link is only shown on the user's private dashboard, it is safe.
A hacker logs into their own account, clicks their receipt (Order 1005), and then changes the URL in their browser to GET /api/orders/1006.
Because the API does not check if the logged-in user actually owns Order 1006, the hacker downloads the receipt, name, and address of another customer. This is called Insecure Direct Object Reference (IDOR), and it is the most common and devastating vulnerability in e-commerce.
Everyday Analogy
- Authentication (AuthN): Showing your passport at airport security. It proves you are exactly who you say you are.
- Authorization (AuthZ): Your boarding pass. Even though security knows who you are, your boarding pass dictates that you are allowed to enter Gate 12, but you are absolutely not authorized to enter the cockpit.
Beginner Explanation
When you log into a website:
- You type your email and password.
- The server checks the database to see if they match. (Authentication)
- If they match, the server gives your browser a temporary digital wristband (a Token or Cookie).
- Every time you click a new page, your browser shows the wristband to the server so you don't have to log in again.
- If you try to access the "Admin Dashboard," the server looks at your wristband, sees you are a "Customer," and kicks you out. (Authorization)
Intermediate Explanation
Modern architectures use JSON Web Tokens (JWT) for stateless authentication. Instead of storing session data in the server's RAM (which breaks when you have multiple load-balanced servers), the server creates a cryptographically signed JSON object.
Payload example: {"user_id": 123, "role": "customer", "exp": 16900000}
The server signs this with a secret key and sends it to the browser. The browser stores it (ideally in an HttpOnly cookie). On every request, the browser sends the JWT. The server verifies the signature to ensure it wasn't tampered with, reads the user_id, and processes the request. The server doesn't need to query the database to know who the user is.
Advanced Explanation
In complex e-commerce systems (like a Multi-Vendor Marketplace), you need sophisticated Role-Based Access Control (RBAC) or Attribute-Based Access Control (ABAC).
A user might have different roles in different contexts:
- User A is a
Customer. - User A is also a
Vendor Adminfor "Shop X". - User A is a
Support Agentfor the overarching platform.
Authorization logic cannot just be if (user.role == 'admin'). It must be contextual.
When accessing /api/shops/5/orders, the middleware must check: "Is this user a Vendor Admin, AND does their vendor_id match Shop 5?" This prevents cross-tenant data leaks.
Real World Example
Best Buy's Guest Checkout: E-commerce sites hate forcing users to create accounts because it causes cart abandonment. Best Buy uses "Guest Auth." You provide an email to checkout, but no password. The system creates a shadow account. Later, if you click "Create Account" and use that same email, the system sends an OTP (One Time Password) to verify your identity, and then automatically merges all your past "Guest" orders into your newly authenticated profile.
Architecture Design
Here is the flow of JWT Authentication and API Gateway Authorization:
sequenceDiagram
participant Browser
participant Auth_Service
participant API_Gateway
participant Order_Service
Browser->>Auth_Service: POST /login (email, password)
Note over Auth_Service: Hashes password, checks DB
Auth_Service-->>Browser: Returns JWT (HttpOnly Cookie)
Browser->>API_Gateway: GET /api/orders (Includes JWT)
Note over API_Gateway: Validates JWT Signature
API_Gateway->>Order_Service: GET /orders (Headers: X-User-Id=123)
Note over Order_Service: AuthZ Check: Does User 123 own these orders?
Order_Service-->>Browser: Returns Order Data
Database Design
Never store plain text passwords. Always use strong, salted hashing algorithms like bcrypt or Argon2.
CREATE TABLE users (
id UUID PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL, -- Never plain text!
role VARCHAR(50) DEFAULT 'customer',
created_at TIMESTAMP
);
CREATE TABLE user_roles (
user_id UUID,
role_name VARCHAR(50), -- 'admin', 'vendor', 'support'
context_id UUID NULL, -- e.g., the specific Vendor ID they manage
PRIMARY KEY (user_id, role_name)
);
API Design
Login (AuthN):
POST /api/auth/login
Payload: { "email": "[email protected]", "password": "Password123!" }
Response: Sets HttpOnly Secure Cookie containing JWT.
Data Access (AuthZ):
GET /api/users/me/orders
Notice the endpoint is /me/. Do not use /users/123/orders in consumer APIs, as it invites hackers to change the ID.
Production Considerations
- JWT Revocation: Because JWTs are stateless, if a user clicks "Logout," or a hacker steals their token, the server cannot "delete" the token. The token remains mathematically valid until its expiration time (
exp). To solve this, you must keep a "Blocklist" in Redis of revoked tokens and check it on every request, or use very short expiration times (15 minutes) coupled with Refresh Tokens. - Rate Limiting: Login endpoints must have strict rate limiting (e.g., 5 attempts per minute per IP). Without this, attackers use botnets to test millions of stolen passwords (Credential Stuffing).
Security Considerations
- XSS and LocalStorage: Do not store JWTs in browser
localStorage. If a malicious script gets on your site (Cross-Site Scripting), it can easily readlocalStorageand steal the token. Always store JWTs inHttpOnly, Secure, SameSite=Strictcookies, which JavaScript cannot read. - Salting: If you don't "salt" passwords before hashing them, two users with the password "password123" will have the exact same hash in the database, allowing hackers to use pre-computed tables (Rainbow Tables) to crack them instantly.
bcrypthandles salting automatically.
Common Mistakes
- IDOR (Insecure Direct Object Reference): Assuming that hiding a button in the UI secures the API. You must enforce Authorization on every single API endpoint, verifying the
user_idinside the JWT matches the owner of the requested data. - Rolling your own Crypto: Writing a custom algorithm to encrypt passwords. It will be flawed. Always use industry standards (
bcrypt).
Tradeoffs and Alternatives
- Custom Auth vs. AuthaaS (Auth-as-a-Service): Building login forms, password resets, and email verification takes weeks. Using services like Auth0, AWS Cognito, or Firebase Auth saves massive amounts of time and is generally more secure, but introduces vendor lock-in and pricing that scales linearly with your user base.
Interview Questions
- Explain the difference between Authentication and Authorization. Give a real-world API example.
- What is an IDOR vulnerability, and how do you prevent it in an e-commerce order history API?
- Why should you never store a JWT in
localStorage? Where should it go instead?
Hands-On Exercise
- Go to
jwt.io. - Look at the encoded token string on the left.
- Look at the decoded JSON payload on the right. Notice how the data (like name and ID) is just Base64 encoded, not encrypted. Anyone can read a JWT payload; the security comes from the Signature at the bottom, which prevents modification.
Key Takeaways
- AuthN verifies Identity; AuthZ verifies Permissions.
- Use
bcryptfor passwords; never store plain text. - Use JWTs for scalable, stateless authentication, but store them securely in HttpOnly cookies.
- Every single API endpoint must explicitly check if the authenticated user is authorized to view or mutate the requested resource.
Further Reading
- OWASP Top 10: Broken Access Control (IDOR)
- RFC 7519: JSON Web Token (JWT) standard