OnlineCBT Logo OnlineCBT
Node Tutorial
NODE · LESSON 12

Authentication with JWT (JSON Web Tokens)

By Ratan Updated: 16 Oct 2026

Implement stateless user authentication using bcrypt password hashing and signed JWT tokens.

Level: Beginner to Advanced
Duration: ~60 Mins Deep-Dive

Verify identity with signed, short-lived access tokens

Authentication establishes who a caller is; authorization decides what that caller may do. A JSON Web Token can carry signed claims such as a subject and expiry. Its payload is readable, so never include passwords, answer keys or confidential profile details. A signature protects integrity; it does not encrypt the token.

Password handling before token issuance

Install the practice dependencies with npm install express@5 jsonwebtoken bcrypt. At registration, validate the password, hash it with an appropriate bcrypt work factor and store only the hash. At login, compare the submitted password against that stored hash. Benchmark the work factor on your actual server. bcrypt uses at most 72 bytes of password input, so reject longer UTF-8 inputs or choose an appropriate alternative password-hashing scheme with a clear migration plan. Do not silently truncate.

// password-demo.mjs — local demonstration only
import bcrypt from 'bcrypt';
const password = 'Practice-only passphrase 384!';
if (Buffer.byteLength(password, 'utf8') > 72) throw new Error('Password too long');
const hash = await bcrypt.hash(password, 12);
console.log(await bcrypt.compare(password, hash)); // true
console.log(await bcrypt.compare('wrong password', hash)); // false

This hard-coded demonstration password is not an application credential. A real login needs a user database, generic failure messages, rate limiting and account recovery controls. Avoid printing passwords, hashes or tokens in normal logs.

Issue and verify with explicit constraints

Configure JWT_SECRET as a securely generated random secret of at least 32 random bytes encoded for storage. Keep it out of Git. This example uses one service with HS256; services using asymmetric keys need a different key distribution and rotation design.

// tokens.mjs
import jwt from 'jsonwebtoken';
const secret = process.env.JWT_SECRET;
if (!secret) throw new Error('JWT_SECRET is required');
const issuer = 'learning-api';
const audience = 'learning-web';

export function issueAccessToken(userId) {
  return jwt.sign({}, secret, {
    algorithm: 'HS256', subject: String(userId),
    issuer, audience, expiresIn: '15m'
  });
}
export function requireUser(req, res, next) {
  const match = /^Bearer ([^ ]+)$/.exec(req.get('authorization') ?? '');
  if (!match) return res.status(401).json({ error: 'Authentication required' });
  try {
    const claims = jwt.verify(match[1], secret, {
      algorithms: ['HS256'], issuer, audience
    });
    if (typeof claims !== 'object' || typeof claims.sub !== 'string' ||
        typeof claims.exp !== 'number') throw new Error('Invalid claims');
    req.auth = { userId: claims.sub };
    next();
  } catch {
    return res.status(401).json({ error: 'Invalid or expired access token' });
  }
}

Import requireUser and mount it before a protected Express route: app.get('/api/me', requireUser, (req, res) => res.json({ userId: req.auth.userId })). Call issueAccessToken only after successful password verification. jwt.decode alone does not verify a signature or establish trust.

Authorization and token lifetime

A valid subject still needs an active account and permission to access the requested record. Query ownership using the verified subject, not a userId supplied by the client. Role changes and logout do not automatically invalidate every existing self-contained token. Short expiry reduces the window; immediate revocation needs an explicit session/revocation strategy. Refresh-token rotation requires persistent storage and reuse detection.

Use HTTPS. Browser storage choices have tradeoffs: JavaScript-readable storage can be stolen through XSS; cookies need appropriate HttpOnly, Secure and SameSite settings plus a CSRF strategy where required. Never place bearer tokens in URLs.

Practice checkpoint

Check missing token, altered signature, expired token, wrong audience and a valid token belonging to a different record owner. Expect 401 for failed authentication and an intentional authorization response for forbidden access. Explain why a readable token payload is normal and why that makes confidential claims unsuitable.

📝 Live Lesson Practice

HTML/CSS JavaScript Python C++ C PHP
⌨️ Practice Inputs (लाइव इनपुट भरें) (खाली होने पर RED, भरने पर GREEN underline)
💻 Code Editor (Monaco VS Code Engine)
👀 Live Preview
Address Contact

+91 7877547686

E-mail

onlinecbtportal@gmail.com

Helpline Number

+91 7877547686


Click To Download
Get it on Google Play

ऐप डाउनलोड करने
के लिए Google Play पर
उपलब्ध है

WhatsApp Chat