Full Authentication Flow using MongoDB, Bcrypt, JWT & Cookies

surya nagsurya nag
3 min read

A beginner-friendly, explanation of how authentication works using MongoDB, JWT, Bcrypt, and Cookies — with a little code so you can copy-paste and test it easily.


🧍 1. User Signup (Registration)

When a new user signs up:

  • They enter their email and password.

  • We never store passwords directly. Instead, we use bcrypt to hash it:

const bcrypt = require("bcryptjs");
const hashedPassword = await bcrypt.hash(password, 10); // 10 = salt rounds
  • The hashed password is saved to MongoDB, not the plain text one.

Example:

const newUser = await User.create({
  email: email,
  password: hashedPassword,
  isVerified: false
});

This keeps your database secure, even if it gets hacked.


📧 2. Email Verification (Optional but Good Practice)

  • After signup, we send an email verification link.

  • The link contains a JWT token that expires in 24 hours.

const jwt = require("jsonwebtoken");
const verifyToken = jwt.sign({ id: newUser._id }, "emailSecretKey", { expiresIn: "1d" });
  • The user clicks the link → token is sent to backend → verified → we set:
user.isVerified = true;
await user.save();

This ensures only real users can log in.


🔓 3. User Login

User logs in by entering email & password.

Backend checks:

  • ✅ Is the email present?

  • ✅ Is the password correct?

  • ✅ Is the user verified?

const isMatch = await bcrypt.compare(inputPassword, user.password);

If all checks pass, we generate a JWT token:

const token = jwt.sign({ id: user._id }, "mySecretKey", { expiresIn: "1h" });

This token will prove who the user is in the next requests.


🎫 4. What is JWT?

JWT = JSON Web Token. It's a small string like:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEyMyIsImlhdCI6MTY5...signature

It has 3 parts:

  1. Header – Type & algorithm

  2. Payload – User data (like ID)

  3. Signature – Used to verify token wasn’t modified

It’s stateless, so we don’t need to store session in DB. Just verify token.


🍪 5. Storing JWT in Cookies

We don’t send the token in the frontend manually. We store it in a cookie:

res.cookie("authToken", token, {
  httpOnly: true,
  secure: true, // HTTPS only (for production)
  maxAge: 3600000 // 1 hour
});

Cookies are sent automatically with every request. Easy!


🔐 6. Accessing Protected Data

Now when the user visits a dashboard or profile page, we:

  1. Check the cookie.

  2. Verify the JWT token.

  3. If it's valid, give access.

Here's a sample middleware to protect any route:

const auth = (req, res, next) => {
  const token = req.cookies.authToken;
  if (!token) return res.status(401).send("Not authenticated");

  try {
    const decoded = jwt.verify(token, "mySecretKey");
    req.user = decoded;
    next();
  } catch (err) {
    res.status(403).send("Invalid or expired token");
  }
};

Use it like:

app.get("/dashboard", auth, (req, res) => {
  res.send("Welcome to your dashboard");
});

🧼 7. Logout

Just clear the cookie:

res.clearCookie("authToken").send("Logged out");

That’s it. You’re logged out.


✨ Done! You now understand how modern authentication works like a pro. Even your grandma can follow this.

0
Subscribe to my newsletter

Read articles from surya nag directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

surya nag
surya nag