Add the Hanko API URL

Retrieve the API URL from the Hanko console and place it in your .env file.

.env
HANKO_API_URL=https://f4****-4802-49ad-8e0b-3d3****ab32.hanko.io
If you are self-hosting Hanko you need to provide your own URL.

Hanko Authentication with JWT

Upon a successful login, Hanko sends a cookie containing a JSON Web Token (JWT). You can use this JWT to authenticate requests on your backend.

Steps to Authenticate Requests

  1. Retrieve the JSON Web Key Set (JWKS): The JWKS has the public keys to verify the JWT. Fetch it from the Hanko API’s .well-known/jwks.json endpoint.

  2. Verify the JWT: Use the JWKS obtained to verify the JWT.

Bun-based Backend Examples

In the following examples, we demonstrate how to implement a custom middleware in Hono.js and Elysia.js backend using jose library.

  • Hono.js

  • Elysia.js

import { Hono, Context } from "hono";
import { createRemoteJWKSet, jwtVerify } from "jose";
import { getCookie } from "hono/cookie";
import { cors } from "hono/cors";

const app = new Hono();

app.use(
  "/*",
  cors({
    origin: "http://localhost:3000", // your frontend URL
    credentials: true,
  })
);

const JWKS = createRemoteJWKSet(
  new URL(`${process.env.HANKO_API_URL}/.well-known/jwks.json`)
);

async function verifyTokenMiddleware(c: Context, next: Function) {
  let token = "";
  if (
    c.req.header("authorization") &&
    c.req.header("authorization")?.split(" ")[0] === "Bearer"
  ) {
    token = c.req.header("authorization")?.split(" ")[1] || "";
  } else if (getCookie(c, "hanko")) {
    console.log("hanko", getCookie(c, "hanko"));
    token = getCookie(c, "hanko") || "";
  }
  if (token === null || token.length === 0) {
    console.log("no token");
    return new Response("Unauthorized", { status: 401 });
  }
  let authError = false;
  await jwtVerify(token, JWKS).catch((err) => {
    console.log("jwt verify error");
    authError = true;
    console.log(err);
  });
  if (authError) {
    console.log("auth error");
    return new Response("Authentication Token not valid", { status: 401 });
  }
  console.log("token valid");
  await next();
}

app.get("/", (c) => c.json({ message: "Hono x Hanko!" }));

app.get("/protected", verifyTokenMiddleware, (c) =>
  c.json({ message: "Hello from protected route!" })
);

export default {
  port: 8000,
  fetch: app.fetch,
};

Try it yourself

Hono.js example (React frontend)

Full source code available on our GitHub.