Stop 10 · Authentication & AuthorizationTopics · 4/11

Passport.js

Part of the Backend Developer Roadmap

In short

Email login today, Google tomorrow, GitHub next week. Passport.js gives each login method its own plug-in 'strategy', so your routes don't turn into a jungle of if-else.

A widely used Node.js authentication middleware supporting dozens of 'strategies' (local, JWT, Google, GitHub, etc.) behind one consistent API.

The blob character at a checkpoint desk picks one stamp from a row of different stamps.

Think of it like this

One checkpoint, many stamps

At a busy checkpoint, one officer handles every visitor. Show a college ID and he uses one stamp; show a visitor pass and he picks another. The desk stays the same; only the check changes. Passport is that desk, and each strategy is a stamp.

Watch it happen

A local login through Passport

Request
authenticate
Strategy
verify()
req.user

1/5POST /login arrives with an email and password in the body.

The big ideas

What you need to know

Strategies are plug-ins

passport-local, passport-jwt, passport-google-oauth20 and many more. Install only the ones you need.

You write verify()

Passport never touches your database. Your verify function decides whether the credentials are good.

Sessions are optional

Use serializeUser with sessions, or pass session: false for token-based APIs like JWT.

Same middleware everywhere

Routes just call passport.authenticate(name), so adding a login method barely touches them.

See it in code

Walk through the code

ts
1import passport from "passport";2import { Strategy as LocalStrategy } from "passport-local";3import bcrypt from "bcrypt";4 5passport.use(new LocalStrategy({ usernameField: "email" }, async (email, password, done) => {6  const user = await db.users.findByEmail(email);7  if (!user || !(await bcrypt.compare(password, user.passwordHash))) {8    return done(null, false, { message: "Wrong email or password" });9  }10  return done(null, user);11}));12 13passport.serializeUser((user: any, done) => done(null, user.id));14passport.deserializeUser(async (id: string, done) => done(null, await db.users.find(id)));15 16app.post("/login", passport.authenticate("local"), (req, res) => res.json({ id: req.user!.id }));

1/4Register the local strategy. It reads email and password from the body and hands them to you.

This assumes express-session is set up and app.use(passport.session()) runs before your routes.

Save yourself the pain

Common mistakes

Oops

Telling users 'email not found' in one case and 'wrong password' in the other.

Do this instead

That lets attackers check which emails are registered. Use one message for both.

Oops

Forgetting app.use(passport.session()) and wondering why req.user is empty.

Do this instead

With sessions, add express-session and then passport.session() before your routes, in that order.

Your mission

Plug in a second strategy

~40 min

Quick check

With Passport's local strategy, who checks whether the password is correct?

Go deeper

  1. 1Set up Passport's local strategy for email/password login.
  2. 2Add a second strategy, e.g. Google OAuth, alongside your local one.
  3. 3Learn how Passport serializes/deserializes a user into the session.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge