Implementing Authentication

1. Installing Passport.js

Example: Install

npm i passport passport-local passport-jwt passport-google-oauth20 bcrypt jsonwebtoken

2. Configuring Passport Middleware

Example: Init

import passport from "passport";
import "./auth/strategies.js";  // registers strategies

app.use(passport.initialize());
// app.use(passport.session()); // only if using sessions

3. Implementing Local Strategy

Example: Username/password

import { Strategy as LocalStrategy } from "passport-local";
import bcrypt from "bcrypt";

passport.use(new LocalStrategy({ usernameField: "email" }, async (email, password, done) => {
  try {
    const user = await db.users.findByEmail(email);
    if (!user || !(await bcrypt.compare(password, user.passwordHash))) {
      return done(null, false, { message: "Invalid credentials" });
    }
    return done(null, user);
  } catch (err) { return done(err); }
}));

4. Serializing Users

Example: Store user.id in session

passport.serializeUser((user, done) => done(null, user.id));

5. Deserializing Users

Example: Load user from id

passport.deserializeUser(async (id, done) => {
  try { done(null, await db.users.findById(id)); }
  catch (err) { done(err); }
});

6. Using JWT Authentication

AspectRecommendation
AlgorithmHS256 (shared secret) or RS256/EdDSA (key pair)
Access TTL5–15 min
Refresh TTL7–30 days, rotate on use
StorageHttpOnly cookie (preferred) over localStorage

7. Creating JWT Tokens

Example: jwt.sign

import jwt from "jsonwebtoken";

function issueTokens(user) {
  const access = jwt.sign(
    { sub: user.id, role: user.role },
    process.env.JWT_SECRET,
    { algorithm: "HS256", expiresIn: "15m", issuer: "api.example.com" }
  );
  const refresh = jwt.sign({ sub: user.id, typ: "refresh" }, process.env.JWT_REFRESH_SECRET, { expiresIn: "30d" });
  return { access, refresh };
}

8. Verifying JWT Tokens

Example: Verify middleware

export function requireAuth(req, res, next) {
  const token = (req.get("Authorization") || "").replace(/^Bearer\s+/i, "");
  if (!token) return next(new HttpError(401, "Missing token"));
  try {
    req.user = jwt.verify(token, process.env.JWT_SECRET, { algorithms: ["HS256"] });
    next();
  } catch (err) {
    next(new HttpError(401, "Invalid token"));
  }
}

9. Implementing OAuth Strategies

Example: Google OAuth 2.0

import { Strategy as GoogleStrategy } from "passport-google-oauth20";

passport.use(new GoogleStrategy({
  clientID:     process.env.GOOGLE_ID,
  clientSecret: process.env.GOOGLE_SECRET,
  callbackURL:  "/auth/google/callback"
}, async (accessToken, refreshToken, profile, done) => {
  const user = await db.users.upsertFromGoogle(profile);
  done(null, user);
}));

app.get("/auth/google",          passport.authenticate("google", { scope: ["profile","email"] }));
app.get("/auth/google/callback", passport.authenticate("google", { session: false }),
  (req, res) => res.json(issueTokens(req.user)));

10. Protecting Routes

Example: Apply requireAuth

app.get("/me", requireAuth, (req, res) => res.json(req.user));
app.use("/api/admin", requireAuth, requireRole("admin"), adminRouter);

11. Handling Login and Logout

app.post("/login", passport.authenticate("local", { session: false }), (req, res) => {
  const tokens = issueTokens(req.user);
  res.cookie("rt", tokens.refresh, { httpOnly: true, secure: true, sameSite: "lax", path: "/auth/refresh" });
  res.json({ accessToken: tokens.access });
});

app.post("/logout", (req, res) => {
  res.clearCookie("rt", { path: "/auth/refresh" });
  res.sendStatus(204);
});

12. Using bcrypt for Passwords

Example: Hash + compare

import bcrypt from "bcrypt";
const COST = 12;

const hash = await bcrypt.hash(password, COST);
const ok   = await bcrypt.compare(password, user.passwordHash);
Algorithm2026 Recommendation
bcryptOK — cost ≥ 12
argon2idPreferred (OWASP) RECOMMENDED
scryptAcceptable
MD5/SHA-1NEVER