Case study · Backend · REST API
Node.js Authentication System
A REST API for sign-up, login and session management built with Node.js, Express.js and MongoDB, using 15-minute JWT access tokens and rotating refresh tokens kept in HTTP-only cookies.
- Type
- Backend · REST API
- Built by
- Nishan Bharati
- Started
- April 2026
- Status
- Source code on GitHub. API only, no public deployment.
- Stack
- Node.js
- Express.js
- MongoDB
- Mongoose
- JSON Web Tokens
- bcrypt
- cookie-parser
What it does
Most web applications need user accounts, and the difficult part is keeping people signed in without leaving long-lived credentials where browser scripts can read them. This project is a standalone authentication API: it issues short-lived access tokens, keeps refresh tokens out of JavaScript’s reach, and lets a user end one session or every session at once.
Features
- Registration that rejects a duplicate username or email with 409 Conflict
- Login that compares the password against a bcrypt hash
- JWT access tokens that expire after 15 minutes
- Refresh tokens that last 7 days, sent in HTTP-only, Secure, SameSite=strict cookies
- Refresh token rotation on every refresh request
- Logout from the current session and logout from all devices
- A protected /get-me endpoint that reads the bearer token
How it works
Sessions are stored as hashes
Every login creates a document in a MongoDB sessions collection holding the user ID, a bcrypt hash of the refresh token, the client IP address, the user agent and a revoked flag. The raw refresh token is never stored, so a copy of the database does not contain usable tokens.
Rotation and revocation
POST /api/auth/refresh-token verifies the refresh token, compares it with the stored hash, then issues a new access token and a new refresh token and replaces the stored hash. Logging out marks that session as revoked; logging out of all devices revokes every active session for the user.
Endpoints
All routes live under /api/auth: POST /register, POST /login, GET /get-me, POST /refresh-token, POST /logout and GET /logout-all.
What I would improve next
- Sign access tokens and refresh tokens with separate secrets, so one leaked key cannot forge both.
- Find the session by the session ID inside the token instead of the user’s first active session, so refresh works when the same user is signed in on several devices.
- Add email verification and password reset with Nodemailer, which is already a dependency but not yet used.
- Make logout-all a POST request and rate-limit the login route.
Built by Nishan Bharati, MERN Stack Developer and co-founder of Navya EdTech. Want something similar built?
Get in touch