CodingNic

Token-Based Authentication with JWT

Exercises

Token-Based Authentication with JWT 30 min read

Exercises

Objectives

By the end of this lesson, you should be able to:

  • Add an extra claim to a JWT’s payload, and read it back in a protected route
  • Inspect a token’s claims without verifying it, and explain when that’s appropriate
  • Reason about token lifetime as a real, tunable trade-off

⚠️ A note on verification: every command and every output in this lesson was actually run, with real HTTP requests against a real Express app.

Exercise: Adding a Role Claim

a) Add a role field. Give the in-memory user a role field ('member'), and include it in the JWT payload at login:

javascript
const token = jwt.sign({ userId: user.id, email: user.email, role: user.role }, SECRET, { expiresIn: '15m' });

b) Read the claim in a protected route. Update GET /api/v1/me to return role alongside userId and email, straight from req.user.

c) Inspect a token’s claims without verifying it. jsonwebtoken also exposes jwt.decode(), which reads a token’s payload without checking the signature at all:

javascript
const decoded = jwt.decode(token);
console.log(decoded);
text
{
  userId: 1,
  email: 'erin@example.com',
  role: 'member',
  iat: 1785865631,
  exp: 1785866531
}

d) Explain the danger. jwt.decode() never checks the signature, so it will happily “decode” a completely forged or tampered token. Write, in your own words, one sentence on why jwt.decode() must never be used in place of jwt.verify() to make an authorization decision, and one legitimate use for it (a debugging tool, logging a token’s claims without needing the secret).

e) Confirm the protected route still requires real verification. Send a forged token (any string with three period-separated parts, none of it signed with your real secret) to GET /api/v1/me, and confirm it’s rejected with 401, unlike jwt.decode(), which would have “succeeded” on the same input.

f) Reason about token lifetime. This exercise used expiresIn: '15m', a much shorter lifetime than Lesson 3’s '1h'. Calculate, from a token’s iat and exp claims, exactly how many seconds it’s valid for, and explain, in a sentence or two, the trade-off between a short-lived token (safer if stolen, but requires re-authenticating more often) and a long-lived one.

Recap

This module covered stateless authentication end to end: what a JWT is and why it isn’t encrypted, signing and verifying tokens correctly, and issuing and checking them in a real Express API, including the real difference between jwt.verify() (checks the signature) and jwt.decode() (does not, and must never be used for authorization).

Next module: authorization, restricting specific routes to specific roles, building directly on the role claim added here.