Skip to content

Instantly share code, notes, and snippets.

@rusintez
Last active October 31, 2025 00:42
Show Gist options
  • Save rusintez/8d2b6b3c3bdd502dbcbf9ee5200057ae to your computer and use it in GitHub Desktop.
Save rusintez/8d2b6b3c3bdd502dbcbf9ee5200057ae to your computer and use it in GitHub Desktop.
Hono JWT Sessions
import { createMiddleware } from "hono/factory";
import { sign, verify } from "hono/jwt";
import { IEnv, ISession } from "./types";
/**
* @usage
*
* const app = new Hono<{ Bindings: { JWT_SECRET:string } }>()
*
* .use("/*", sessions({ ttl: 86400 }))
*
* .post("/signin", (c) => {
* c.var.updateSession({ userId: 1 });
* return c.json({ ok: true });
* })
*
* .get("/user", (c) => {
* const { userId } = c.var.session;
* return c.json(await getUser(c, userId));
* });
*
*/
export const sessions = (params: { ttl: number }) =>
createMiddleware<IEnv>(async (c, next) => {
const token = c.req.header("jwt");
if (token) {
try {
const session = await verify(token, c.env.JWT_SECRET);
c.set("session", session as ISession);
} catch (e) {
c.set("session", {});
}
} else {
c.set("session", {});
}
c.set("updateSession", (params) => Object.assign(c.var.session, params));
await next();
const expiration = ((Date.now() + params.ttl * 1000) / 1000) | 0;
c.res.headers.set(
"jwt",
await sign({ exp: expiration, ...c.var.session }, c.env.JWT_SECRET),
);
});
@rusintez
Copy link
Author

Cookie Sessions

import { getCookie, setCookie } from "hono/cookie";
import { createMiddleware } from "hono/factory";
import { sign, verify } from "hono/jwt";
import { IEnv, ISession } from "./types";

export const sessions = (params: { ttl: number }) =>
  createMiddleware<IEnv>(async (c, next) => {
    const token = getCookie(c, "jwt");

    if (token) {
      try {
        const session = await verify(token, c.env.JWT_SECRET);
        c.set("session", session as ISession);
      } catch (e) {
        c.set("session", {});
      }
    } else {
      c.set("session", {});
    }

    await next();

    const expiration = ((Date.now() + params.ttl * 1000) / 1000) | 0;

    setCookie(
      c,
      "jwt",
      await sign({ exp: expiration, ...c.var.session }, c.env.JWT_SECRET),
      { httpOnly: true, sameSite: "None", secure: true }
    );
  });

Client Config

import { hc } from "hono/client";
import { IApp } from "./server";

export const createClient = (baseUri: string) =>
  hc<IApp>(baseUri, { init: { credentials: "include" } });

Routes

const app = new Hono<IEnv>()
  .use(
    cors({
      origin: [
        "http://localhost:8787",
        // ...other origins here
      ],
      credentials: true,
    })
  )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment