Skip to main content

Command Palette

Search for a command to run...

๐Ÿ”How JWT, Access Tokens & Refresh Tokens Work โ€” Node.js vs AWS Lambda

Updated
โ€ข5 min read
๐Ÿ”How JWT, Access Tokens & Refresh Tokens Work โ€” Node.js vs AWS Lambda

๐Ÿง  What Are Access Tokens and Refresh Tokens?

Token TypePurposeLifespanStored Where
Access TokenGrants access to protected resourcesShort-lived (e.g., 15 min)In memory or localStorage
Refresh TokenGets a new access token when expiresLong-lived (e.g., 7 days)Secure httpOnly cookie / DB

๐ŸŽฏ Real-Life Analogy: The Movie Hall Entry System

Imagine walking into a movie theater.

  1. ๐ŸŽŸ๏ธ At the entrance, you show your movie ticket to the guard โ€” this is your Access Token.
    It allows you to enter and enjoy the movie.

  2. ๐Ÿ•’ But the ticket is only valid for one movie (say 2 hours). If you want to watch another movie or re-enter after stepping out, you need a new ticket.

  3. ๐Ÿค Instead of going to the main counter again and proving your identity (logging in), you carry a VIP pass or membership card (Refresh Token).

  4. ๐ŸŽซ You present this refresh token at a special desk, and they issue you a new movie ticket (new Access Token) without requiring you to log in again.


๐Ÿ” Key Takeaway

  • Access Token = Movie Ticket

    • Short-lived, used to access services

    • Shown often (like at the theatre gate)

  • Refresh Token = Membership Card

    • Long-lived, used to get new access tokens

    • Hidden and securely stored

๐Ÿ” JWT Authentication Flow with Access + Refresh Tokens

  1. User logs in โ‡’ Receives both tokens

  2. An access token is used to call protected APIs

  3. If the access token expires, the client sends the refresh token to get a new access token

  4. Refresh token is stored securely (e.g., in cookies)

  5. If the refresh token is invalid or expired, โ‡’ user must log in again


๐Ÿ—๏ธ Implementation in Node.js (Express)

๐Ÿ“ฆ Install

npm install express jsonwebtoken cookie-parser

๐Ÿ” Token Functions (auth.js)

const jwt = require("jsonwebtoken");

const ACCESS_SECRET = "access-secret";
const REFRESH_SECRET = "refresh-secret";

function generateTokens(user) {
  const accessToken = jwt.sign(user, ACCESS_SECRET, { expiresIn: "15m" });
  const refreshToken = jwt.sign(user, REFRESH_SECRET, { expiresIn: "7d" });
  return { accessToken, refreshToken };
}

function verifyAccess(token) {
  return jwt.verify(token, ACCESS_SECRET);
}

function verifyRefresh(token) {
  return jwt.verify(token, REFRESH_SECRET);
}

module.exports = { generateTokens, verifyAccess, verifyRefresh };

๐Ÿง  Express Server (index.js)

const express = require("express");
const cookieParser = require("cookie-parser");
const { generateTokens, verifyAccess, verifyRefresh } = require("./auth");

const app = express();
app.use(express.json());
app.use(cookieParser());

app.post("/login", (req, res) => {
  const user = { email: req.body.email };
  const { accessToken, refreshToken } = generateTokens(user);
  res.cookie("refreshToken", refreshToken, { httpOnly: true });
  res.json({ accessToken });
});

app.get("/protected", (req, res) => {
  const auth = req.headers.authorization;
  if (!auth) return res.sendStatus(401);
  try {
    const user = verifyAccess(auth.split(" ")[1]);
    res.json({ message: "Access granted", user });
  } catch {
    res.status(403).json({ message: "Access token expired" });
  }
});

app.post("/refresh", (req, res) => {
  const refreshToken = req.cookies.refreshToken;
  if (!refreshToken) return res.sendStatus(401);
  try {
    const user = verifyRefresh(refreshToken);
    const { accessToken } = generateTokens(user);
    res.json({ accessToken });
  } catch {
    res.status(403).json({ message: "Refresh token invalid" });
  }
});

๐Ÿš€ JWT with Refresh Token in AWS Lambda

Lambda is stateless โ€” so no sessions! But you can use JWTs the same way.

๐Ÿ—‚๏ธ Structure

pythonCopyEditlambda-jwt-auth/
โ”œโ”€โ”€ handler.js
โ”œโ”€โ”€ auth.js

๐Ÿ” auth.js (Same logic as Express)

const jwt = require("jsonwebtoken");
const ACCESS_SECRET = "access-secret";
const REFRESH_SECRET = "refresh-secret";

function generateTokens(user) {
  const accessToken = jwt.sign(user, ACCESS_SECRET, { expiresIn: "15m" });
  const refreshToken = jwt.sign(user, REFRESH_SECRET, { expiresIn: "7d" });
  return { accessToken, refreshToken };
}

function verifyAccess(token) {
  return jwt.verify(token, ACCESS_SECRET);
}

function verifyRefresh(token) {
  return jwt.verify(token, REFRESH_SECRET);
}

module.exports = { generateTokens, verifyAccess, verifyRefresh };

๐Ÿง  handler.js

const { generateTokens, verifyAccess, verifyRefresh } = require("./auth");

exports.login = async (event) => {
  const body = JSON.parse(event.body);
  const user = { email: body.email };
  const { accessToken, refreshToken } = generateTokens(user);

  return {
    statusCode: 200,
    headers: {
      "Set-Cookie": `refreshToken=${refreshToken}; HttpOnly; Path=/; Max-Age=604800`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ accessToken }),
  };
};

exports.protected = async (event) => {
  const authHeader = event.headers.authorization;
  try {
    const user = verifyAccess(authHeader.split(" ")[1]);
    return {
      statusCode: 200,
      body: JSON.stringify({ message: "Access granted", user }),
    };
  } catch {
    return { statusCode: 403, body: JSON.stringify({ error: "Token expired" }) };
  }
};

exports.refresh = async (event) => {
  const cookie = event.headers.cookie || "";
  const token = cookie.split("refreshToken=")[1];
  try {
    const user = verifyRefresh(token);
    const { accessToken } = generateTokens(user);
    return {
      statusCode: 200,
      body: JSON.stringify({ accessToken }),
    };
  } catch {
    return { statusCode: 403, body: JSON.stringify({ error: "Refresh token invalid" }) };
  }
};

๐Ÿ“Š Node.js Server vs AWS Lambda (with Refresh Token)

FeatureNode.js + JWT + Refresh TokenAWS Lambda + API Gateway + JWT
Token HandlingIn memory or a cookieVia API Gateway headers/cookies
Refresh LogicSimple via cookieCookie needs to be manually parsed
Storage OptionCan use Redis for refresh token blacklistStore tokens in DB or skip blacklist
DeploymentRuns continuouslyCold start but lower cost
Use CaseComplex backend appsScalable microservices, low-traffic auth

๐Ÿง  Summary

  • Access tokens are short-lived and used to access protected resources.

  • Refresh tokens are long-lived and used to generate new access tokens without login.

  • JWTs help us implement stateless authentication in both Node.js servers and AWS Lambda functions.

  • Store refresh tokens securely (e.g., httpOnly cookies) and never expose them on the frontend.

27 views

More from this blog