Hono - [炎] means flame🔥 in Japanese - is a small, simple, and ultrafast web framework for the Edges. It works on any JavaScript runtime: Cloudflare Workers, Fastly Compute@Edge, Deno, Bun, Vercel, Netlify, Lagon, AWS Lambda, Lambda@Edge, and Node.js.

@unkey/hono offers a middleware for authenticating API keys with unkey.

github.com/unkeyed/unkey/tree/main/packages/hono

Install

 npm install @unkey/hono

Let’s dive straight in. The minimal setup looks like this. All you need is your api id. Go to /app/api, select your API and copy the id.

By default it tries to grab the api key from the Authorization header and then verifies it with unkey. The result of the verification will be written to the context and can be access with c.get("unkey").

import { Hono } from "hono"
import { type UnkeyContext, unkey } from "@unkey/hono";

const app = new Hono<{ Variables: { unkey: UnkeyContext } }>();

app.use("*", unkey({
  apiId: "<UNKEY_API_ID>"
}));


app.get("/somewhere", (c) => {
  // access the unkey response here to get metadata of the key etc
  const ... = c.get("unkey")

  return c.text("yo")
})

Customizing the middleware

By default the middleware tries to grab the api key from the Authorization header. You can change this by passing a custom header name to the middleware.

app.use(
  "*",
  unkey({
    getKey: (c) => c.req.header("x-api-key"),
  })
);

If the header is missing the middleware will return a 401 error response like this

c.json({ error: "unauthorized" }, { status: 401 });

To customize the response in case the header is missing, just return a response from the getKey function.

app.use(
  "*",
  unkey({
    getKey: (c) => {
      const key = c.req.header("x-api-key");
      if (!key) {
        return c.text("missing api key", 401);
      }
      return key;
    },
  })
);

Handle errors

If omited, the middleware will throw an HTTPException like hono recommends

To handle errors globally you can pass an onError handler to the middleware. The handler will be called with the context and the error.

app.use(
  "*",
  unkey({
    onError: (c: Context, err: UnkeyError) => {
      // handle error
      return c.text("unauthorized", 401);
    },
  })
);

Handle invalid keys

By default the middleware will not do anything with the verification response other than writing it to the context. However you most likely would like to just return a 401 response if the key is invalid and not continue with the request.

To do this you can pass a handleInvalidKey handler to the middleware. See here for the full result object.

app.use(
  "*",
  unkey({
    handleInvalidKey: (c, result) => {
      return c.json({
          error: "unauthorized",
          reason: result.code,
        }, 401);
    },
  })
);

Disable telemetry

By default, Unkey collects anonymous telemetry data to help us understand how our SDKs are used.

If you wish to disable this, you can do so by passing a boolean flag to the constructor:

app.use(
  "*",
  unkey({ disableTelemetry: true })
)