Skip to main content

Command Palette

Search for a command to run...

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

Published
β€’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

NishikantaRay

46 posts