Iron Session
iron-session is a secure, stateless, and cookie-based session management library for JavaScript environments, primarily used in Node.js applications and Next.js projects (supporting both API Routes and the App Router). The current stable version is 8.0.4. It distinguishes itself by storing encrypted and signed session data directly within HTTP cookies, thereby eliminating the need for server-side storage or external databases, a pattern inspired by frameworks like Ruby On Rails. This design promotes statelessness, improving scalability and simplifying deployment strategies. While it doesn't adhere to a fixed release schedule, major versions typically introduce significant API adjustments or compatibility updates, such as the v8 release which focused on App Router support and API simplification. The library ships with comprehensive TypeScript types, ensuring a robust and type-safe development experience.
Common errors
-
ReferenceError: require is not defined
cause `iron-session` is primarily designed as an ES Module (ESM) since version 6.0.0. Using `require()` syntax in an ESM-only context will lead to this error.fixUpdate your import statements to use ES Module syntax: `import { getIronSession } from 'iron-session';`. Ensure your `package.json` specifies `"type": "module"` or use `.mjs` file extensions for your source files. -
Property 'session' does not exist on type 'NextApiRequest'
cause This TypeScript error often occurs when developers expect `req.session` to be automatically available on a Next.js request object without proper type augmentation or explicit session retrieval.fixAfter calling `const session = await getIronSession(req, res, sessionOptions);`, access session properties directly on the `session` object. For type safety, define a `SessionData` interface and pass it to `getIronSession<SessionData>(...)`. -
TypeError: session.destroy(...).then is not a function
cause This error arises when attempting to use `.then()` or `await` with `session.destroy()` after version 8.0.1, where `destroy()` was changed to be synchronous.fixRemove `await` or `.then()` from `session.destroy()`. Simply call `session.destroy();`. Remember to follow it with `await session.save()` if you want the cookie to be immediately cleared from the client.
Warnings
- breaking Version 8.0.0 significantly refactored the API to align with the Next.js App Router and simplify the overall surface. All previous opinionated wrapper functions like `withIronSessionSsr` or `withIronSessionApiRoute` have been removed in favor of a single `getIronSession()` method.
- breaking Version 6.0.0 was a complete rewrite of the library in TypeScript and involved a package rename from `next-iron-session` to `iron-session`. This introduced numerous breaking changes to the API, types, and internal structure.
- gotcha As of v8.0.1, the `session.destroy()` method is synchronous and returns `void`. Previous versions might have returned a `Promise<void>`, leading to developers incorrectly awaiting or chaining `.then()` to it.
- gotcha The `password` option in `sessionOptions` is critical for the security of your sessions. It must be a strong, cryptographically secure random string of at least 32 characters. Hardcoding this password or using a weak one makes your sessions vulnerable to decryption and tampering.
Install
-
npm install iron-session -
yarn add iron-session -
pnpm add iron-session
Imports
- getIronSession
const getIronSession = require('iron-session');import { getIronSession } from 'iron-session'; - IronSession
import { IronSession } from 'iron-session';import type { IronSession } from 'iron-session'; - sealData
import sealData from 'iron-session';
import { sealData } from 'iron-session';
Quickstart
import { getIronSession, type IronSession } from 'iron-session';
import { type NextApiRequest, type NextApiResponse } from 'next'; // Example for Next.js
// Define a type for your session data
interface SessionData {
username?: string;
isLoggedIn: boolean;
// Add other properties you want to store in the session
}
// Define session options, including a strong secret password
const sessionOptions = {
password: process.env.IRON_SESSION_PASSWORD ?? 'a-very-long-secret-password-at-least-32-chars-long',
cookieName: 'my-app-session-cookie',
cookieOptions: {
maxAge: 60 * 60 * 24 * 30, // 30 days
secure: process.env.NODE_ENV === 'production', // Set to true in production
httpOnly: true,
path: '/',
sameSite: 'lax'
}
};
// Example GET handler to retrieve session data
export async function getSessionHandler(req: NextApiRequest, res: NextApiResponse) {
const session = await getIronSession<SessionData>(req, res, sessionOptions);
// Initialize if not set for new sessions
if (session.isLoggedIn === undefined) {
session.isLoggedIn = false;
}
return res.status(200).json({ isLoggedIn: session.isLoggedIn, username: session.username });
}
// Example POST handler (e.g., login) to update session data
export async function loginHandler(req: NextApiRequest, res: NextApiResponse) {
const session = await getIronSession<SessionData>(req, res, sessionOptions);
// In a real app, you'd validate user credentials here
if (req.body.username === 'demo' && req.body.password === 'password') {
session.username = req.body.username;
session.isLoggedIn = true;
await session.save(); // Persist changes to the session cookie
return res.status(200).json({ message: 'Logged in successfully' });
}
return res.status(401).json({ message: 'Invalid credentials' });
}
// Example handler for logging out a user
export async function logoutHandler(req: NextApiRequest, res: NextApiResponse) {
const session = await getIronSession<SessionData>(req, res, sessionOptions);
session.destroy(); // This is synchronous since v8.0.1, removes the session cookie
await session.save(); // Ensure the cookie is cleared from the browser
return res.status(200).json({ message: 'Logged out successfully' });
}