Hono Sessions Middleware

0.8.1 · active · verified Sun Apr 19

hono-sessions is a middleware library designed for the Hono web framework, providing robust cookie-based session management. Currently at version 0.8.1, the library is actively maintained with a focus on stability and features like `autoExtendExpiration` and improved type safety. It differentiates itself by supporting a wide array of runtimes, including Node.js (v20+), Deno, Bun, Cloudflare Workers, and Cloudflare Pages, leveraging the Web Crypto API for secure, encrypted cookies via `iron-webcrypto`. Key features include support for 'flash messages' (data deleted after one read), built-in Memory and Cookie storage drivers, extensible architecture for custom drivers (like Bun SQLite), and strong TypeScript typing for session variables. It offers a flexible approach to user session management, particularly powerful in serverless and edge environments where persistent server-side state might be impractical.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates basic session usage with `hono-sessions`, including setting and retrieving data, handling flash messages, and explicitly touching the session to extend its expiration. It configures `CookieStore` with essential options like `encryptionKey` and `cookieOptions`, and incorporates TypeScript types for session data.

import { Hono } from 'hono'
import {
  Session,
  sessionMiddleware,
  CookieStore
} from 'hono-sessions'

// Add types to your session data for improved safety and autocomplete
type SessionDataTypes = {
  'counter': number,
  'flashMessage'?: string
}

// Set up your Hono instance with session types
const app = new Hono<{
  Variables: {
    session: Session<SessionDataTypes>,
    session_key_rotation: boolean // Type for internal middleware variable
  }
}>()

const store = new CookieStore()

app.use('*', sessionMiddleware({
  store,
  // IMPORTANT: encryptionKey must be at least 32 characters long for CookieStore
  encryptionKey: process.env.SESSION_ENCRYPTION_KEY ?? 'super-secret-key-that-is-at-least-thirty-two-characters-long',
  expireAfterSeconds: 900, // Session expires after 15 minutes of inactivity
  autoExtendExpiration: true, // Automatically extends session on activity (default: true)
  cookieOptions: {
    sameSite: 'Lax', // Recommended for basic CSRF protection
    path: '/', // Required for the library to function correctly
    httpOnly: true, // Recommended to prevent client-side script access
    secure: process.env.NODE_ENV === 'production' // Use 'Secure' in production
  },
}))

app.get('/', async (c) => {
  const session = c.get('session')

  const currentCounter = session.get('counter') || 0;
  session.set('counter', currentCounter + 1);

  const flash = session.getFlash('flashMessage');
  if (flash) {
    console.log(`Flash message: ${flash}`);
  }

  return c.html(`
    <h1>You have visited this page ${session.get('counter')} times</h1>
    ${flash ? `<p style="color: green;">${flash}</p>` : ''}
    <p><a href="/set-flash">Set a flash message</a></p>
    <p><a href="/read">Read counter (and touch session)</a></p>
  `)
})

app.get('/set-flash', async (c) => {
  const session = c.get('session');
  session.setFlash('flashMessage', 'This is a one-time message!');
  return c.redirect('/');
});

app.get('/read', (c) => {
  const session = c.get('session')
  session.touch() // Explicitly update the session expiration time
  return c.json({
    counter: session.get('counter'),
    flash: session.getFlash('flashMessage') // This will be undefined after first read
  })
})

// For Bun, Cloudflare Workers, etc.
// export default {
//   port: 3000,
//   fetch: app.fetch
// }

// For Deno
// Deno.serve(app.fetch)

// For Node.js (via Hono adapter)
// import { serve } from '@hono/node-server';
// serve({ fetch: app.fetch, port: 3000 });

view raw JSON →