Use case

Add authentication to a Hono API

AscendKit access tokens secure a Hono API the same way they secure any backend: verify the token in middleware and resolve the request to a usr_ record scoped by your public key. Because Hono runs on edge runtimes, JWKS-based verification keeps the check lightweight.

How it works

  1. 1. Authenticate the client
    Sign users in with the AscendKit SDK and pass access tokens to your Hono API.
  2. 2. Verify with middleware
    Add Hono middleware that verifies the access token against AscendKit's JWKS endpoint.
  3. 3. Resolve the user
    Map each verified request to a usr_ record scoped by your project public key.

Why does Hono suit JWKS verification particularly well?

Because Hono usually runs on edge runtimes, and JWKS verification needs no database and no origin round-trip. The check is a signature validation against cached public keys, which is exactly the shape of work an edge runtime is good at.

The contrast is session-based auth, which needs a lookup in a session store on every request. From an edge worker that means a network hop back to a database, which erases the latency benefit of running at the edge in the first place.

One constraint to design around: edge runtimes have no long-lived process memory in the way a Node server does. A cached JWKS may not survive between invocations, so verification can occasionally pay the fetch cost.

src/middleware.ts
import { createMiddleware } from "hono/factory";
import { createRemoteJWKSet, jwtVerify } from "jose";

const JWKS = createRemoteJWKSet(
  new URL(`${process.env.ASCENDKIT_API_URL}/api/auth/jwks`),
);

export const requireUser = createMiddleware(async (c, next) => {
  const token = c.req.header("Authorization")?.replace(/^Bearer /, "");
  if (!token) return c.json({ error: "Missing token" }, 401);

  try {
    const { payload } = await jwtVerify(token, JWKS);
    c.set("userId", payload.sub as string);
    await next();
  } catch {
    return c.json({ error: "Invalid token" }, 401);
  }
});

What is different from a Node backend?

Three things, and all of them are runtime constraints rather than AscendKit ones. Environment variables are bound differently depending on the platform, `process.env` may not exist, and Node built-ins are unavailable.

Use Web Crypto rather than the Node crypto module -- `jose` already does this, which is why it works unmodified on the edge where older JWT libraries do not.

Read configuration from the platform's binding rather than assuming `process.env`. On Cloudflare Workers that means the env argument passed to the handler; the code above assumes a Node-compatible runtime and needs adjusting otherwise.

Troubleshooting

Every request returns 401 in production but works locally

Cause: The token was issued against one environment and is being verified against another. Development and production have different keys.

Fix: Confirm the public key on the backend belongs to the same environment the frontend authenticates against.

Intermittent 503s under load

Cause: The JWKS cache expired and several requests tried to refresh it at once.

Fix: Treat 503 as retryable, not as an auth failure. Never sign a user out on a 503 -- that is our outage, not their session expiring.

FAQ

Does token verification work on edge runtimes?

Yes. AscendKit publishes signing keys via JWKS, so Hono middleware can verify access tokens on edge runtimes without a round trip.

Can I add email and journeys to a Hono backend?

Yes. Auth, email, journeys, and surveys are one platform, so a Hono API can trigger lifecycle messaging on the same user record.

Related guides

Start with one API key

Auth, email, surveys, and journeys share one user record, so you ship this without stitching vendors together.

Start free