Skip to content

The Big TypeScript Rewrite

Compare
Choose a tag to compare
@vvo vvo released this 04 Nov 13:39
· 345 commits to main since this release

This is a BREAKING CHANGE (Major) release.

I did a full rewrite of the library in TypeScript, both as an exercise for me and to provide better types by default for consumers of the library. Since it was a full rewrite I took the opportunity to solve most of the issues from the GitHub repository along with feature requests.

Hope you like it. You'll find a migration guide in these changes.

Changes:

  • The library was renamed to iron-session (since it works on all Node.js HTTP frameworks)
  • TypeScript: We have better types and you can now easily type check your session data (see usage in README). Fixes #369. Fixes #368.
  • You can access and set session data directly on req.session.* instead of having to call .get()/.set()/.unset()
  • get/set/unset methods were removed
  • The library exposes different wrappers for Next.js API Routes, Next.js getServerSideProps, and Express.js middleware (see migration guide)
  • List of passwords (rotation) must now be passed as objects like {1: 'password1', 2: 'password2'}
  • When upgrading previous sessions will be kept which means that you can safely upgrade and your users will not lose their data or be logged out
  • We now expose sealData/unsealData methods to create magic links and impersonation flows. iron-store is no more used.
  • We have updated the examples (Next.js, Next.js with TypeScript and Express.js) to use the new API
  • The library is now published as an ES module along with CommonJS
  • We now warn on bad usage (http + secure or save called after the response was sent). Fixes #8
  • We now automatically set the cookie to secure or not secure based on the protocol.
  • You can now have "session cookies" by passing {cookiesOptions: {maxAge: undefined}}. Fixes #340
  • We handle the case where the cookie has been tampered with (we generate a new one). Fixes #380

Migration guide:

1. Uninstall next-iron-session and install iron-session:

npm remove next-iron-session
npm add iron-session

2. Change import paths in your code:

Before:

import { withIronSession } from "next-iron-session";

After:

import { withIronSessionApiRoute, withIronSessionSsr } from "iron-session/next";
import { ironSession } from "iron-session/express";

3. Change your code to use the new API:

Before:

req.session.set("user", { name: "John" });
const user = req.session.get("user");
req.session.unset("user");

After:

req.session.user = { name: "John" };
const user = req.session.user; // or use req.session.user directly
delete req.session.user;

4. (Optional) Remove secure flag from your options

The cookie secure flag is now automatically set based on http/https unless you want to change it.

Before:

withIronSession(handler, {
  password: "complex_password_at_least_32_characters_long",
  cookieName: "myapp_cookiename",
  // if your localhost is served on http:// then disable the secure flag
  cookieOptions: {
    secure: process.env.NODE_ENV === "production",
  },
});

After:

withIronSessionApiRoute(handler, {
  password: "complex_password_at_least_32_characters_long",
  cookieName: "myapp_cookiename",
});

5. (Optional) Change the format of your password

If you were passing down a list of passwords (for password rotations) then you need to update it to:

Before:

withIronSession(handler, {
  password: [
    {
      id: 2,
      password: "complex_password_at_least_32_characters_long",
    },
    {
      id: 1,
      password: "complex_password_at_least_32_characters_long",
    },
  ],
});

After:

withIronSessionApiRoute(handler, {
  password: {
    2: "another_password_at_least_32_characters_long",
    1: "complex_password_at_least_32_characters_long",
  },
});

6. (Optional) Replace iron-store usage with sealData/unsealData

If you were using iron-store to create seals for magic links or impersonation flows then you can replace it with sealData/unsealData.

Because we no more needed get/set/unset methods. We completely ditched the iron-store library that was initially built for next-iron-session needs.

Before:

const store = await ironStore({
  password: "complex_password_at_least_32_characters_long",
  ttl: 14 * 24 * 60 * 60 * 1000
});

store.set("user", { name: "John" });
const seal = await store.seal();

// later on, in a different file:
const store = await ironStore({
  seal: req.query.seal,
  password: "complex_password_at_least_32_characters_long",
  ttl: 14 * 24 * 60 * 60 * 1000
});

const user = store.get("user);

After:

import { sealData } from "iron-session";
const store = {
  user: { name: "John" },
};

const seal = await sealData(store, {
  password: "complex_password_at_least_32_characters_long",
  // ttl is always 14 days by default
});

// later on, in a different file:
import { unsealData } from "iron-session";
const store = await unseatData(req.query.seal, {
  password: "complex_password_at_least_32_characters_long",
});
const user = store.user;

5. (Optional) Check the best way to use TypeScript with the library

Have a look at the README to know how to do that, here: https://github.com/vvo/iron-session#session-wrappers

Enjoy!