Authentication Flow Diagrams
- Express + Prisma + PostgreSQL Backend
- Next.js Frontend (HTTP Client)
This document visualizes how authentication works between the frontend, the API server, and the database.
The system uses:
- JWT Access Tokens
- Refresh Tokens (HttpOnly cookie)
- Express authentication middleware
- Prisma ORM for database access
System Components
| Component | Role |
|---|---|
| Next.js Frontend | HTTP client consuming API |
| Express API | Authentication and business logic |
| Prisma ORM | Database access layer |
| PostgreSQL | Persistent storage |
Architecture overview:
Next.js Frontend
|
| HTTP requests
v
Express API (Auth + Business Logic)
|
v
Prisma ORM
|
v
PostgreSQLLogin Flow
User authentication process.
User
|
| 1. Enter email + password
v
Next.js Frontend
|
| POST /api/auth/login
v
Express API
|
| Verify credentials
v
Prisma
|
| SELECT user WHERE email=...
v
PostgreSQL
|
| Return user record
v
Express API
|
| Validate password (bcrypt)
| Generate JWT access token
| Generate refresh token
v
Response
|
| accessToken (JSON)
| refresh_token (HttpOnly cookie)
v
Next.js FrontendResult:
- Access token stored in memory
- Refresh token stored in secure cookie
Accessing Protected APIs
Example: retrieving orders.
Next.js Frontend
|
| Authorization: Bearer <access_token>
v
GET /api/orders
|
v
Express Auth Middleware
|
| Verify JWT signature
| Validate expiration
v
Attach user to request
|
v
Protected Route Handler
|
v
Prisma
|
v
PostgreSQL
|
v
Response returnedExample middleware:
verifyJWT
|
+-- token valid -> continue
|
+-- token invalid -> 401 UnauthorizedAccess Token Expiration Flow
When the access token expires:
Next.js Frontend
|
| POST /api/auth/refresh
| (refresh_token cookie automatically sent)
v
Express API
|
| Verify refresh token
| Validate session
v
Generate new access token
|
v
Return new JWT
|
v
Next.js stores new tokenLogout Flow
Next.js Frontend
|
| POST /api/auth/logout
v
Express API
|
| Invalidate refresh token
| Clear cookie
v
Response
|
v
User logged out
Cookie cleared:
refresh_token = deletedAuthentication Middleware Flow
Every protected endpoint uses authentication middleware.
Example:
Request
|
| Authorization header
v
Auth Middleware
|
| Extract token
| Verify signature
| Check expiration
v
Token valid?
|
+-- YES --> attach req.user -> continue
|
+-- NO --> return 401 UnauthorizedExample payload attached to request:
req.user = {
id: "uuid",
email: "admin@example.com",
role: "ADMIN"
}Role-Based Authorization
After authentication, routes may enforce roles.
Example:
requireRole("ADMIN")Flow:
Authenticated request
|
v
Check req.user.role
|
+-- ADMIN -> allow
|
+-- USER -> 403 ForbiddenPrisma User Lookup
Typical login query:
prisma.user.findUnique({
where: { email }
})Password verification:
bcrypt.compare(password, user.password)Complete Request Lifecycle
Client Request
|
v
Express Router
|
v
Auth Middleware
|
v
Authorization Middleware
|
v
Route Controller
|
v
Prisma ORM
|
v
PostgreSQL
|
v
ResponseSecurity Model Summary
| Mechanism | Purpose |
|---|---|
| JWT Access Token | Authenticate requests |
| Refresh Token | Renew expired access tokens |
| HttpOnly Cookie | Protect refresh token from JS |
| bcrypt Password Hashing | Secure password storage |
| Role Checks | Enforce authorization |
| HTTPS | Protect tokens in transit |
Development vs Production Differences
| Setting | Development | Production |
|---|---|---|
| Bootstrap Admin | Enabled | Disabled |
| Secure Cookies | Optional | Required |
| HTTPS | Optional | Required |
| Logging | Verbose | Minimal |
Example .env:
NODE_ENV=production
JWT_SECRET=<secure_secret>
JWT_ACCESS_TTL=15m
JWT_REFRESH_TTL=7d
ALLOW_BOOTSTRAP=falseKey Design Principle
The Express API owns authentication and authorization.
The Next.js frontend is a stateless HTTP consumer.
Benefits:
- clear separation of concerns
- backend reusable for other clients (mobile, CLI, integrations)
- easier security auditing
- easier scaling of frontend and backend independently