Deep Dive: Secure Session Authentication
The primary goal of the Inventory Management System was to implement a stateful, "security-first" authentication flow that protects sensitive merchant data from common web vulnerabilities.
The Strategy: Sessions over Tokens
While many modern applications use JSON Web Tokens (JWT) stored in localStorage, I chose Session-based authentication with server-side persistence in PostgreSQL.
Why not LocalStorage?
Storing sensitive credentials in localStorage makes an application vulnerable to Cross-Site Scripting (XSS). By using HttpOnly Cookies, we ensure that the session identifier is inaccessible to client-side JavaScript, effectively neutralizing XSS-based credential theft.
The Authentication Lifecycle
1. The Handshake (Login)
When a user submits their credentials, a "silent" security exchange occurs:
- Hashing: The backend verifies the password using
bcrypt. - Session Storage: A unique session record is created in a PostgreSQL table via
connect-pg-simple. - The Cookie: The server sends a
Set-Cookieheader withHttpOnly,Secure, andSameSite=Laxflags.
2. Validating Requests
Every subsequent request (like /items) follows this logic:
- The browser automatically attaches the session cookie.
- The server intercepts the request and checks the cookie against the PostgreSQL session store.
- If valid, the server attaches the
user_idto the request object.
Data Scoping & Multi-Tenancy
To ensure a "Merchant-First" experience where users never see each other's data, I implemented Strict Data Scoping. Every database query is filtered by the authenticated user_id:
-- The backend automatically injects the session's user_id ($1)
SELECT * FROM items
WHERE id = $2 AND user_id = $1;
Summary of Security Wins
- No XSS exposure: Sensitive identifiers are hidden from JavaScript.
- No stale data: Sessions can be revoked instantly from the database.
- Server-side Truth: The client never dictates "who" they are; the server maintains that state.