A production-ready, full-stack authentication boilerplate featuring a highly secure Backend-For-Frontend (BFF) cookie architecture, seamless Google OAuth integration, passwordless OTP flows, and dual-layer rate limiting.
- BFF Cookie Architecture: Zero frontend token management. Access and Refresh tokens are securely handled via
HttpOnlycookies, eliminating XSS vulnerabilities and race conditions. - Silent Auto-Refresh: The Express middleware acts as a smart bouncer, automatically intercepting expired access tokens and silently issuing new ones using the refresh token without disrupting the user experience.
- Multi-Provider Account Linking: Users can log in via OTP and Google OAuth or anyother OAuth. The system intelligently recognizes the email and silently links the accounts in the database without throwing constraint errors.
- Rate Limiting: Prevents endpoint spamming (Max 5 attempts per IP / 30 mins) and Prevents targeted account bombing (Max 3 attempts per Email / 30 mins).
- Passwordless First: Primary authentication is driven by ultra-fast 6-digit OTPs sent via email, with traditional passwords available as an optional account upgrade.
- State Management : A lightweight, custom-built global user management and notification system powered by Zustand, fully decoupled from React's render cycle.
Frontend
- React(Vite): React for its efficiency and ease of development for SPA with vite as a lightining fast bundler.
- Zustand: Lightweight global state management.
- Axios: HTTP client with lots of features beyound fetching API.
- Tailwind CSS:Utility-first styling for the UI components.
Backend
- Node JS + Express: API routing and middleware management.
- PostgresSQL + Drizzle ORM_: Type-safe, high-performance relational database management.
- Redis: High-speed in-memory store for OTP generation, Refresh Token blacklisting, and Rate Limiting.
- JWT: Cryptographically signed short-lived Access Tokens (15m) and long-lived Refresh Tokens (7d).
- Bcrypt : Hashing password Securely.
Prerequisites
- Node.js (v18+)
- Docker or Redis and PostgresSQL instances running
- A Google Cloud Console account (for OAuth credentials)
- Resend API and Domain (Setup Resend account with domain to use opt services)
Client
Starting the frontend
Env for client
VITE_GOOGLE_CLIENT_ID= //google client id
cd client
pnpm install
pnpm run dev
Use any package manager as per your choice like npm or yarn
Database and Redis (Docker)
Env for server
CLIENT_URL=http://localhost:5173
PORT=8000
NODE_ENV=development
DB_HOST=
DB_PORT=
DB_USER=
DB_PASSWORD=
DB_NAME=
DATABASE_URL=postgres://host:password@host:port/database_name
REDIS_HOST=
REDIS_PORT=
REDIS_URL=redis://host:port
RESEND_API_KEY=
EMAIL_FROM=
JWT_ACCESS_SECRET=
JWT_REFRESH_SECRET=
GOOGLE_CLIENT_ID=
cd server
pnpm install
pnpm db-push
pnpm docker-up
Use any package manager as per your choice like npm or yarn
If you have your own instances of postgres and redis running just fill the provided field in the env
Server
Ensure the Docker or PostgresSQL and redis instances are running.
pnpm run dev
Use any package manager as per your choice like npm or yarn
-
Login/Register: User authenticates via OTP, Password, or Google.
-
Token Generation: Express generates a JWT Access Token (15m) and Refresh Token (7d). The Refresh token is backed up to Redis.
-
Cookie Delivery: Tokens are sent to the browser exclusively via Set-Cookie headers configured with HttpOnly, Secure, and SameSite=Strict.
-
Subsequent Requests: Axios automatically attaches the cookies to every request.
-
Middleware: If the Access Token is valid, the request proceeds.
If the Access Token is expired, the middleware checks the Refresh Token cookie, verifies it against Redis, silently generates a new Access Token cookie, and fulfills the request.
If both are expired (or missing), a 401 Unauthorized is thrown.
-
Frontend Safety Net: A global Axios interceptor catches any 401 errors, clears the Zustand user store, and redirects to /login.
Jumpstart your project with this secure Auth Boilerplate. Built on a BFF architecture with HttpOnly cookies, Redis rate-limiting, and passwordless flows, it eliminates client-side token vulnerabilities. Skip the auth setup and focus on building your core product. Happy coding!
If you found this helpful, please ⭐️ star the repo.
Security is a community effort. If you spot a vulnerability or bug, fork the repo and submit a PR. Let's build a safer web together.