Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Auth (Beginner-Friendly Authentication Project)

This project is a simple Node.js + Express + MongoDB authentication backend.

If you are learning auth for the first time, this project teaches:

  • how user registration and login works
  • how passwords are hashed before saving
  • how accessToken and refreshToken are used together
  • how refresh token rotation works with sessions
  • how logout from one device and all devices works

1. Tech Stack

  • Node.js
  • Express
  • MongoDB + Mongoose
  • JWT (jsonwebtoken)
  • cookie-parser
  • morgan
  • dotenv
  • Node crypto module

2. Project Structure

Auth2/
├─ server.js
├─ package.json
├─ .env
├─ src/
│  ├─ app.js
│  ├─ config/
│  │  ├─ config.js
│  │  └─ database.js
│  ├─ models/
│  │  ├─ user.model.js
│  │  └─ session.model.js
│  ├─ controllers/
│  │  └─ auth.controller.js
│  └─ routes/
│     └─ users.route.js

3. How Server Starts

server.js

  • imports Express app from src/app.js
  • imports DB connection from src/config/database.js
  • calls connectDB()
  • starts server on PORT (or 5000 fallback)

src/app.js

  • creates Express app
  • enables JSON body parsing with express.json()
  • enables logs with morgan("dev")
  • enables cookie reading with cookieParser()
  • mounts all auth routes on /api/v1/auth

So final route pattern becomes:

  • /api/v1/auth/register
  • /api/v1/auth/login
  • etc.

4. Environment Variables

This project expects:

  • PORT
  • MONGO_URI
  • JWT_SECRET

src/config/config.js does:

  • dotenv.config() to read .env
  • throws error if MONGO_URI or JWT_SECRET is missing

Important:

  • keep .env private
  • never push real secrets to GitHub

5. Database Models

5.1 User model (src/models/user.model.js)

Fields:

  • username (unique, required)
  • email (unique, required)
  • password (required, stored as hash)
  • timestamps (createdAt, updatedAt)

5.2 Session model (src/models/session.model.js)

Each login/register creates a session record.

Fields:

  • user (reference to User document)
  • refreshTokenHash (hash of refresh token, not plain token)
  • ip (request IP)
  • userAgent (browser/app info)
  • revoke (boolean, default false)
  • timestamps

Why Session model matters:

  • lets you invalidate refresh tokens (logout)
  • supports "logout all devices"
  • avoids storing plain refresh tokens in DB

6. Authentication Concepts Used Here

Access Token

  • short life: 15m
  • sent in JSON response
  • client sends it in Authorization: Bearer <token>
  • used for protected APIs like /get-me

Refresh Token

  • longer life: 7d
  • stored in httpOnly cookie
  • used to get a new access token
  • rotated in /refresh-token (new one issued)

Password Hashing

  • password is converted to SHA-256 hash using Node crypto
  • only hash is saved in DB
  • during login, input password is hashed again and compared

7. Route-by-Route Workflow

All routes are defined in src/routes/users.route.js.

7.1 POST /api/v1/auth/register

Controller: registerUser

Flow:

  1. Read username, email, password from body.
  2. Check if username/email already exists.
  3. Hash password with SHA-256.
  4. Create new user in MongoDB.
  5. Create refresh token (7d).
  6. Hash refresh token and store in Session collection with ip + userAgent.
  7. Create access token (15m) with payload { id, sessionId }.
  8. Set refresh token in cookie:
    • httpOnly: true
    • secure: true
    • sameSite: "strict"
    • maxAge: 7 days
  9. Return user info + access token.

7.2 POST /api/v1/auth/login

Controller: loginUser

Flow:

  1. Read email, password.
  2. Find user by email.
  3. Hash incoming password and compare with DB hash.
  4. If valid, generate refresh token (7d).
  5. Hash refresh token and create a new session.
  6. Generate access token (15m) with payload { id, sessionId }.
  7. Set refresh token cookie.
  8. Return user info + access token.

7.3 GET /api/v1/auth/get-me

Controller: getMe

Flow:

  1. Read bearer token from Authorization header.
  2. Verify JWT using JWT_SECRET.
  3. Read user by decoded.id.
  4. Return basic user info.

7.4 GET /api/v1/auth/refresh-token

Controller: refreshToken

Flow:

  1. Read refresh token from cookie (req.cookies.refreshToken).
  2. If missing, return unauthorized.
  3. Verify refresh token JWT.
  4. Hash incoming refresh token.
  5. Find non-revoked matching session in DB.
  6. If session not found, return unauthorized.
  7. Create new access token (15m).
  8. Create new refresh token (7d).
  9. Hash new refresh token and update same session record.
  10. Set new refresh token cookie.
  11. Return new access token.

This route is the core of token rotation.

7.5 GET /api/v1/auth/logout

Controller: logoutUser

Flow:

  1. Read refresh token from cookie.
  2. Hash token and find active session.
  3. Mark session revoke = true.
  4. Clear refreshToken cookie.
  5. Return success.

Effect:

  • current device/session is logged out
  • that refresh token can no longer be used

7.6 GET /api/v1/auth/logout-all

Controller: logoutAllSessions

Flow:

  1. Read refresh token from cookie.
  2. Verify it and get user id.
  3. Revoke all active sessions for that user (updateMany).
  4. Clear cookie.
  5. Return success.

Effect:

  • user is logged out from all devices/sessions

8. Full Flow (Simple Story)

  1. User registers.
  2. Server creates User.
  3. Server creates Session + refresh token cookie.
  4. Server returns access token.
  5. Client uses access token for protected requests.
  6. Access token expires after 15 minutes.
  7. Client calls /refresh-token using cookie.
  8. Server validates session and rotates refresh token.
  9. Server sends new access token (+ updated cookie).
  10. User can logout current session or all sessions.

9. Cookie Settings in This Project

Current cookie options:

  • httpOnly: true
    JS in browser cannot read cookie directly (helps against XSS token theft).
  • secure: true
    cookie only sent over HTTPS.
  • sameSite: "strict"
    blocks cross-site sending in many cases.
  • maxAge: 7 days
    cookie expires after 7 days.

Note for local development:

  • with plain http://localhost, secure: true may prevent cookie being set in some environments.

10. How to Run the Project

  1. Install packages:
npm install
  1. Create .env with:
PORT=3000
MONGO_URI=your_mongodb_connection_string
JWT_SECRET=your_super_secret_key
  1. Start dev server:
npm run dev
  1. Base URL:
http://localhost:3000/api/v1/auth

11. API Quick Reference

Public

  • POST /register
  • POST /login

Requires Access Token in Header

  • GET /get-me

Requires Refresh Token Cookie

  • GET /refresh-token
  • GET /logout
  • GET /logout-all

12. How to Test (Postman)

  1. Call POST /register.
  2. Save returned accessToken.
  3. Confirm response also sets refreshToken cookie.
  4. Call GET /get-me with header: Authorization: Bearer <accessToken>
  5. Call GET /refresh-token with cookie sent automatically by client.
  6. Replace old access token with new one from response.
  7. Call GET /logout or GET /logout-all.

13. Beginner Notes and Learning Points

  • This project combines stateless JWT auth with DB-backed sessions.
  • Access token is short-lived for safety.
  • Refresh token is cookie-based and revocable through session records.
  • Hashing refresh token before storing is a good practice.

14. Current Improvement Ideas (Next Learning Steps)

  • Use bcrypt instead of plain SHA-256 for password hashing.
  • Add validation for request body inputs.
  • Add centralized error handling middleware.
  • Add auth middleware instead of repeating token checks in controllers.
  • Add CORS config if frontend is on a different domain.
  • Add tests for login/refresh/logout flows.

15. Final Summary

This codebase already teaches the most important auth building blocks:

  • user creation
  • secure password storage (hashed)
  • login verification
  • access + refresh token model
  • refresh token rotation
  • session revocation for logout and logout-all

If you understand this README and map each section to its file, you can explain this backend end-to-end to another beginner.

Learning - Ankur bhaiya (Sheryians)

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages