or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/npm-iron-session

Secure, stateless, and cookie-based session library for JavaScript

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/iron-session@8.0.x

To install, run

npx @tessl/cli install tessl/npm-iron-session@8.0.0

0

# iron-session

1

2

iron-session is a secure, stateless, and cookie-based session library for JavaScript that provides encrypted session storage using signed cookies with @hapi/iron cryptography, eliminating the need for server-side session storage or external services.

3

4

## Package Information

5

6

- **Package Name**: iron-session

7

- **Package Type**: npm

8

- **Language**: TypeScript

9

- **Installation**: `npm install iron-session` or `pnpm add iron-session`

10

11

## Core Imports

12

13

```typescript

14

import { getIronSession, sealData, unsealData, type IronSession, type SessionOptions } from "iron-session";

15

```

16

17

For CommonJS:

18

19

```javascript

20

const { getIronSession, sealData, unsealData } = require("iron-session");

21

```

22

23

## Basic Usage

24

25

```typescript

26

import { getIronSession } from "iron-session";

27

28

// Next.js API Routes / Node.js Express

29

export async function handler(req, res) {

30

const session = await getIronSession(req, res, {

31

password: "complex_password_at_least_32_characters_long",

32

cookieName: "myapp_cookiename",

33

});

34

35

// Read session data

36

console.log(session.username);

37

38

// Set session data

39

session.username = "john_doe";

40

session.isLoggedIn = true;

41

42

// Save the session

43

await session.save();

44

}

45

46

// Next.js App Router (Route Handlers, Server Components, Server Actions)

47

import { cookies } from "next/headers";

48

49

export async function GET() {

50

const session = await getIronSession(cookies(), {

51

password: "complex_password_at_least_32_characters_long",

52

cookieName: "myapp_cookiename",

53

});

54

55

return Response.json({ username: session.username });

56

}

57

```

58

59

## Architecture

60

61

iron-session is built around several key components:

62

63

- **Stateless Design**: Session data is stored entirely in encrypted cookies, requiring no server-side storage

64

- **Cryptographic Security**: Uses @hapi/iron encryption with signed seals for data protection

65

- **Multi-Environment Support**: Works with Node.js/Express, Next.js (Pages/App Router), and Web APIs

66

- **Password Rotation**: Supports multiple passwords for seamless security updates

67

- **Type Safety**: Full TypeScript integration with generic session data types

68

69

## Capabilities

70

71

### Session Management

72

73

Core session functionality for creating, reading, updating, and destroying encrypted cookie-based sessions.

74

75

```typescript { .api }

76

/**

77

* Creates an encrypted session from HTTP request/response objects (Node.js/Express)

78

*/

79

function getIronSession<T extends object>(

80

req: IncomingMessage | Request,

81

res: Response | ServerResponse,

82

sessionOptions: SessionOptions

83

): Promise<IronSession<T>>;

84

85

/**

86

* Creates an encrypted session from Next.js cookie store (App Router)

87

*/

88

function getIronSession<T extends object>(

89

cookies: CookieStore,

90

sessionOptions: SessionOptions

91

): Promise<IronSession<T>>;

92

```

93

94

### Data Sealing and Unsealing

95

96

Direct encryption utilities for creating secure tokens and magic links without session cookies.

97

98

```typescript { .api }

99

/**

100

* Encrypts arbitrary data into a signed seal string

101

*/

102

function sealData(

103

data: unknown,

104

options: { password: Password; ttl?: number }

105

): Promise<string>;

106

107

/**

108

* Decrypts a seal string back to original data

109

*/

110

function unsealData<T>(

111

seal: string,

112

options: { password: Password; ttl?: number }

113

): Promise<T>;

114

```

115

116

**Usage Examples:**

117

118

```typescript

119

// Create a magic login link

120

const userId = 123;

121

const seal = await sealData(

122

{ userId, action: "login" },

123

{ password: "your_password", ttl: 3600 } // 1 hour

124

);

125

const magicLink = `https://yourapp.com/magic-login?token=${seal}`;

126

127

// Verify and use the magic link

128

const data = await unsealData(tokenFromUrl, {

129

password: "your_password",

130

ttl: 3600

131

});

132

console.log(data.userId); // 123

133

```

134

135

## Types

136

137

### Required Imports for Types

138

139

```typescript { .api }

140

import type { IncomingMessage, ServerResponse } from "http";

141

import type { CookieSerializeOptions } from "cookie";

142

```

143

144

### Session Object

145

146

```typescript { .api }

147

type IronSession<T> = T & {

148

/**

149

* Encrypts the session data and sets the cookie.

150

*/

151

readonly save: () => Promise<void>;

152

153

/**

154

* Destroys the session data and removes the cookie.

155

*/

156

readonly destroy: () => void;

157

158

/**

159

* Update the session configuration. You still need to call save() to send the new cookie.

160

*/

161

readonly updateConfig: (newSessionOptions: SessionOptions) => void;

162

};

163

```

164

165

### Configuration Types

166

167

```typescript { .api }

168

interface SessionOptions {

169

/**

170

* The cookie name that will be used inside the browser.

171

* Make sure it's unique given your application.

172

*/

173

cookieName: string;

174

175

/**

176

* The password(s) that will be used to encrypt the cookie.

177

* Must be at least 32 characters long.

178

*

179

* For password rotation, use an object with incrementing keys:

180

* { 1: 'old-password', 2: 'new-password' }

181

* The highest numbered key is used for new cookies.

182

*/

183

password: Password;

184

185

/**

186

* Session validity time in seconds. Default: 1209600 (14 days)

187

* ttl = 0 means no expiration

188

*/

189

ttl?: number;

190

191

/**

192

* Additional cookie configuration options.

193

* For session cookies (deleted when browser closes), use: { maxAge: undefined }

194

*/

195

cookieOptions?: CookieOptions;

196

}

197

198

/**

199

* Cookie store interface for Next.js cookies() API

200

*/

201

interface CookieStore {

202

get: (name: string) => { name: string; value: string } | undefined;

203

set: {

204

(name: string, value: string, cookie?: Partial<ResponseCookie>): void;

205

(options: ResponseCookie): void;

206

};

207

}

208

209

/**

210

* W3C CookieListItem specification with additional response properties

211

*/

212

interface ResponseCookie extends CookieListItem {

213

httpOnly?: boolean;

214

maxAge?: number;

215

priority?: 'low' | 'medium' | 'high';

216

}

217

218

/**

219

* CookieListItem as specified by W3C Cookie Store API

220

*/

221

interface CookieListItem {

222

/** A string with the name of a cookie */

223

name: string;

224

/** A string containing the value of the cookie */

225

value: string;

226

/** A number of milliseconds or Date interface containing the expires of the cookie */

227

expires?: Date | number;

228

domain?: string;

229

path?: string;

230

sameSite?: 'strict' | 'lax' | 'none';

231

secure?: boolean;

232

}

233

234

/**

235

* Map of password IDs to password strings for rotation

236

*/

237

type PasswordsMap = Record<string, string>;

238

239

/**

240

* Union type for password specification

241

*/

242

type Password = PasswordsMap | string;

243

244

/**

245

* Cookie serialization options (excluding encode)

246

*/

247

type CookieOptions = Omit<CookieSerializeOptions, "encode">;

248

```

249

250

## Default Configuration

251

252

```typescript { .api }

253

/**

254

* Default session options applied automatically

255

*/

256

const defaultOptions = {

257

ttl: 1209600, // 14 days in seconds (fourteenDaysInSeconds)

258

cookieOptions: {

259

httpOnly: true,

260

secure: true,

261

sameSite: "lax",

262

path: "/"

263

// maxAge is computed dynamically as ttl - 60 (timestampSkewSec)

264

}

265

};

266

```

267

268

## Error Handling

269

270

iron-session performs validation and throws descriptive errors for common issues:

271

272

- **Password validation**: "Password must be at least 32 characters long."

273

- **Cookie size limits**: "Cookie length is too big (X bytes), browsers will refuse it. Try to remove some data."

274

- **Headers sent**: "session.save() was called after headers were sent. Make sure to call it before any res.send() or res.end()"

275

- **Missing configuration**: "Missing cookie name." or "Missing password."

276

- **Bad usage**: "Bad usage: use getIronSession(req, res, options) or getIronSession(cookieStore, options)."

277

- **Invalid seals**: Expired, corrupted, or tampered session data returns empty session (no error thrown)

278

279

**Common Error Patterns:**

280

281

```typescript

282

try {

283

const session = await getIronSession(req, res, {

284

password: "short", // Error: Password too short

285

cookieName: "app-session"

286

});

287

} catch (error) {

288

console.error(error.message); // "iron-session: Bad usage. Password must be at least 32 characters long."

289

}

290

291

// Expired/invalid sessions don't throw - they return empty objects

292

const session = await getIronSession(req, res, validOptions);

293

console.log(session.userId); // undefined if session expired/invalid

294

```

295

296

## Environment Compatibility

297

298

### Node.js / Express

299

300

```typescript

301

import { getIronSession } from "iron-session";

302

303

app.get('/profile', async (req, res) => {

304

const session = await getIronSession(req, res, sessionOptions);

305

res.json({ user: session.user });

306

});

307

```

308

309

### Next.js Pages Router

310

311

```typescript

312

// pages/api/session.js

313

import { getIronSession } from "iron-session";

314

315

export default async function handler(req, res) {

316

const session = await getIronSession(req, res, sessionOptions);

317

// Use session...

318

}

319

```

320

321

### Next.js App Router (Route Handlers)

322

323

```typescript

324

// app/api/session/route.ts

325

import { cookies } from "next/headers";

326

import { getIronSession } from "iron-session";

327

328

export async function POST() {

329

const session = await getIronSession(cookies(), sessionOptions);

330

session.user = { id: 1, name: "John" };

331

await session.save();

332

return Response.json({ success: true });

333

}

334

```

335

336

### Next.js App Router (Server Components)

337

338

```typescript

339

// app/profile/page.tsx

340

import { cookies } from "next/headers";

341

import { getIronSession } from "iron-session";

342

343

async function ProfilePage() {

344

const session = await getIronSession(cookies(), sessionOptions);

345

346

if (!session.user) {

347

return <div>Please log in</div>;

348

}

349

350

return <div>Welcome, {session.user.name}</div>;

351

}

352

```

353

354

### Next.js App Router (Server Actions)

355

356

```typescript

357

// app/login/actions.ts

358

"use server";

359

import { cookies } from "next/headers";

360

import { getIronSession } from "iron-session";

361

362

export async function loginAction(formData: FormData) {

363

const session = await getIronSession(cookies(), sessionOptions);

364

365

// Authenticate user...

366

session.user = { id: userId, name: username };

367

await session.save();

368

}

369

```

370

371

## Security Features

372

373

- **Encryption**: All session data is encrypted using @hapi/iron cryptography

374

- **Signing**: Cookies are cryptographically signed to prevent tampering

375

- **Password Rotation**: Support for multiple passwords enables seamless security updates

376

- **Time-based Validation**: TTL (time-to-live) prevents replay attacks with expired tokens

377

- **Cookie Security**: Secure defaults with httpOnly, secure, and sameSite attributes

378

- **Size Limits**: Automatic validation against browser cookie size limits (4096 bytes)

379

- **Cross-platform Crypto**: Uses uncrypto for consistent behavior across Node.js and browsers

380

381

## Password Rotation Example

382

383

```typescript

384

// Current configuration

385

const sessionOptions = {

386

cookieName: "session",

387

password: {

388

1: "old_password_32_characters_minimum",

389

2: "new_password_32_characters_minimum" // This will be used for new sessions

390

}

391

};

392

393

// iron-session will:

394

// - Use password ID 2 for encrypting new sessions

395

// - Accept both password IDs 1 and 2 for decrypting existing sessions

396

// - Allow gradual migration as old sessions expire

397

```