Production-style authentication & user profile API. Implements access/refresh tokens (rotation + revocation), protected routes, input validation, and consistent errors. Email verification and password reset flows are stubbed (tokens logged to console).
The API starts on http://localhost:${PORT||8080}
.
Base path: api/auth
POST http://localhost:8080/api/auth/register
- POST
/register
- body:
{ email, username, password, name? }
- 201:
{ message, user }
(without secrets). Logs email verify token to console.
- body:
output { "message": "Registered. Please verify email (check server log).", "user": { "email": "ahee@example1.com", "username": "ahee", "name": "Ahee Bala", "isEmailVerified": false, "_id": "68c702526bfaa92d1d4f77aa", "createdAt": "2025-09-14T17:58:42.180Z", "updatedAt": "2025-09-14T17:58:42.180Z", "__v": 0 } }
POST http://localhost:8080/api/auth/login
2. POST /login
- body:
{ identifier, password }
(identifier = email | username
) - 200:
{ accessToken, user }
andrefreshToken
set as HttpOnly cookie.
output { "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2OGM3MDI1MjZiZmFhOTJkMWQ0Zjc3YWEiLCJ1c2VybmFtZSI6ImFoZWUiLCJlbWFpbCI6ImFoZWVAZXhhbXBsZTEuY29tIiwiaWF0IjoxNzU3ODc0MDEyLCJleHAiOjE3NTc4NzQ5MTJ9.V71wim0j-sac6_1QNIINGbVKOG1x35CnzpAXAjQIoQU", "user": { "_id": "68c702526bfaa92d1d4f77aa", "email": "ahee@example1.com", "username": "ahee", "name": "Ahee Bala", "isEmailVerified": false, "createdAt": "2025-09-14T17:58:42.180Z", "updatedAt": "2025-09-14T17:58:42.180Z", "__v": 0 } }
POST http://localhost:8080/api/auth/refresh
3. POST /refresh
- body:
{ refreshToken? }
- 200:
{ accessToken }
. Rotates refresh token (revokes previous).
output
{ accessToken:"" }
POST http://localhost:8080/api/auth/logout
4. POST /logout
- body/cookie:
refreshToken
(optional) - 200:
{ success: true }
. Revokes current refresh token and clears cookie.
output { "message": "Logged out successfully" }
GET http://localhost:8080/api/auth/me
5. GET /me
(protected)
- header:
Authorization: Bearer <accessToken>
- 200:
{ user }
.
output
{ "user": { "_id": "68c702526bfaa92d1d4f77aa", "email": "ahee@example1.com", "username": "ahee", "name": "Ahee Bala", "isEmailVerified": false, "createdAt": "2025-09-14T17:58:42.180Z", "updatedAt": "2025-09-14T17:58:42.180Z", "__v": 0 } }
PATCH http://localhost:8080/api/auth/me
6. PATCH /me
(protected)
- body:
{ name?, username? }
- 200:
{ user }
(updated).
output
{ "user": { "_id": "68c702526bfaa92d1d4f77aa", "email": "ahee@example1.com", "username": "shayiUserName", "name": "Shayi", "isEmailVerified": false, "createdAt": "2025-09-14T17:58:42.180Z", "updatedAt": "2025-09-15T16:10:53.412Z", "__v": 0 } }
PATCH http://localhost:8080/api/auth/password
7. PATCH /password
(protected)
- body:
{ oldPassword, newPassword }
- 200:
{ success: true }
and revokes all refresh tokens for the user.
output
{ "success": true }
POST http://localhost:8080/api/auth/forgot-password
8. POST /forgot-password
- body:
{ identifier }
- 200 always. Logs reset token to console. Token valid 30 minutes.
output
{ "message": "If the account exists, a reset token was issued (stubbed to server log).", "resetToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2OGM3MDI1MjZiZmFhOTJkMWQ0Zjc3YWEiLCJ0IjoicmVzZXQiLCJpYXQiOjE3NTc5NTUwMDAsImV4cCI6MTc1Nzk1NjgwMH0.GGbLyf86UcXpBsblfPhEHMcqX3Ce5CcRh2m_vDM-lHA" }
POST http://localhost:8080/api/auth/reset-password
9. POST /reset-password
- body:
{ token, newPassword }
- 200 on success. Revokes all refresh tokens.
output { "success": true }
To test login again and they will form new access and refresh token.
POST http://localhost:8080/api/auth/verify-email
10. POST /verify-email
- body:
{ token }
- 200 on success.
- Validation:
express-validator
+ strong password rule on register. - Security: Bcrypt hashes, never log secrets, Helmet, rate-limit on
auth/*
, CORS restricted via env, HttpOnly refresh cookie. - Tokens: Access (~15m) and refresh (~7–30d) lifetimes configurable in env. Refresh stored hashed in DB and rotated on
/refresh
. Revocation on logout/password reset/change. - Auth middleware: validates access token and sets
req.user
. - Errors: JSON format:
{ error: { code, message, details? } }
. - Email flows: token generation & checks implemented; sending is stubbed via server logs.
/
config/db.js
controllers/authController.js
middlewares/auth.js
models/
User.js
RefreshToken.js
routes/auth.js
app.js
- Register a user: watch server console for
verify
token. - Login: store
accessToken
in client memory;refreshToken
is in a cookie. - Use
/refresh
when access token expires; cookie will be rotated. - Use
/logout
to revoke current session. - Run
/forgot-password
and check console for reset token; then call/reset-password
.