Authentication
Verifying who a user is - password hashing, JWT tokens, session-based auth, and protecting routes with middleware.
What it is, in plain English: Authentication answers 'who is this user?' -- as opposed to authorization, which answers 'what are they allowed to do?'. In Express, authentication typically means: hashing passwords before storing them (never plain text), verifying credentials on login, and issuing some form of proof (a session cookie or a JWT token) that the browser sends back on future requests so the server doesn't need to ask for a password every time.
Verifying who someone is
Step 1 -- never store plain text passwords
// npm install bcrypt
import bcrypt from "bcrypt";
// On registration -- hash before storing:
app.post("/register", async (req, res) => {
const { email, password } = req.body;
const hashedPassword = await bcrypt.hash(password, 10); // 10 = salt rounds
const user = await db.users.create({ email, password: hashedPassword });
res.status(201).json({ id: user.id, email: user.email });
// NEVER send the password (even hashed) back in the response
});
// On login -- compare the entered password against the stored hash:
app.post("/login", async (req, res) => {
const { email, password } = req.body;
const user = await db.users.findOne({ email });
if (!user || !(await bcrypt.compare(password, user.password))) {
return res.status(401).json({ error: "Invalid email or password" });
// generic message -- don't reveal whether email exists (security)
}
// credentials are valid -- issue a token (next section)
});Step 2 -- issue a JWT token on successful login
// npm install jsonwebtoken
import jwt from "jsonwebtoken";
app.post("/login", async (req, res) => {
// ... verify password as above ...
const token = jwt.sign(
{ userId: user.id }, // payload -- data to embed
process.env.JWT_SECRET, // secret key -- NEVER hardcode this
{ expiresIn: "1h" } // token expires in 1 hour
);
res.json({ token });
});
// The client stores this token (localStorage or a cookie) and sends it
// with future requests: Authorization: Bearer <token>Step 3 -- protect routes with middleware
function requireAuth(req, res, next) {
const authHeader = req.headers.authorization;
const token = authHeader?.replace("Bearer ", "");
if (!token) {
return res.status(401).json({ error: "No token provided" });
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded; // attach decoded payload to the request
next();
} catch {
res.status(401).json({ error: "Invalid or expired token" });
}
}
// Use it on any route that needs a logged-in user:
app.get("/profile", requireAuth, (req, res) => {
res.json({ userId: req.user.userId });
});
Try It Yourself (Node.js logic)
Official Sources
- Express.js — Security Guide
- jsonwebtoken — npm package
- bcrypt — npm package
- Passport.js Documentation
- OWASP — Authentication Cheat Sheet
The Codex links only to official documentation. No third-party tutorials.