Skip to Content
chalvien 1.0 is released
DocumentationGuidesSecurityAuthenticationJWTJWT Auth Flow

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

ComponentRole
Next.js FrontendHTTP client consuming API
Express APIAuthentication and business logic
Prisma ORMDatabase access layer
PostgreSQLPersistent storage

Architecture overview:

Next.js Frontend | | HTTP requests v Express API (Auth + Business Logic) | v Prisma ORM | v PostgreSQL

Login 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 Frontend

Result:

  • 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 returned

Example middleware:

verifyJWT | +-- token valid -> continue | +-- token invalid -> 401 Unauthorized

Access 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 token

Logout 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 = deleted

Authentication 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 Unauthorized

Example 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 Forbidden

Prisma 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 Response

Security Model Summary

MechanismPurpose
JWT Access TokenAuthenticate requests
Refresh TokenRenew expired access tokens
HttpOnly CookieProtect refresh token from JS
bcrypt Password HashingSecure password storage
Role ChecksEnforce authorization
HTTPSProtect tokens in transit

Development vs Production Differences

SettingDevelopmentProduction
Bootstrap AdminEnabledDisabled
Secure CookiesOptionalRequired
HTTPSOptionalRequired
LoggingVerboseMinimal

Example .env:

NODE_ENV=production JWT_SECRET=<secure_secret> JWT_ACCESS_TTL=15m JWT_REFRESH_TTL=7d ALLOW_BOOTSTRAP=false

Key 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