bao

Cloudflare Service Binding

Call your bao auth worker directly from another Cloudflare Worker with zero HTTP overhead for server-side session checks.

If your app runs on Cloudflare Workers or Pages with Functions, you can bind directly to your bao auth Worker. Server-side session verification becomes an in-process call — no HTTP round-trip, no network latency.

Client-side code (running in the browser) still uses createAuthClient over HTTP as normal.


Add the service binding

In your app’s wrangler.json or wrangler.jsonc, add a services entry pointing at your bao worker name:

{
  "name": "my-app",
  "services": [
    {
      "binding": "BAO_AUTH",
      "service": "my-app-production", // your bao worker name
    },
  ],
}

Your bao worker name is the name field in the auth-service’s wrangler.json, typically {appName}-{env} (e.g. my-app-production).

Add the binding type to your environment interface:

// worker-configuration.d.ts
interface Env {
  BAO_AUTH: Fetcher;
  // ...your other bindings
}

Verify a session server-side

Forward the incoming request headers to the auth-service via the binding. The auth-service reads the session cookie and returns the session:

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    // Forward the session cookie to the auth-service
    const sessionResponse = await env.BAO_AUTH.fetch(
      new Request("https://bao/api/auth/get-session", {
        headers: request.headers,
      }),
    );

    const session = await sessionResponse.json<{
      user?: { id: string; email: string };
    }>();

    if (!session.user) {
      return new Response("Unauthorized", { status: 401 });
    }

    return new Response(`Hello ${session.user.email}`);
  },
};

The URL hostname (https://bao/...) is ignored by the service binding — only the path matters. Use any placeholder hostname.


Astro (Pages with Functions)

In an Astro SSR project using @astrojs/cloudflare, access the binding from Astro.locals.runtime.env:

// src/middleware.ts
import { defineMiddleware } from "astro:middleware";

export const onRequest = defineMiddleware(async (context, next) => {
  const env = context.locals.runtime.env as Env;

  const sessionResponse = await env.BAO_AUTH.fetch(
    new Request("https://bao/api/auth/get-session", {
      headers: context.request.headers,
    }),
  );

  const session = await sessionResponse.json<{ user?: { id: string } }>();
  context.locals.user = session.user ?? null;

  return next();
});
// src/pages/dashboard.astro (frontmatter)
---
if (!Astro.locals.user) {
  return Astro.redirect("/login");
}
---

Client-side setup

The binding only applies to server-side code. In the browser, use createAuthClient as normal — see Connect your app.


When to use this vs HTTP

HTTP clientService Binding
Works inAny runtimeCloudflare Workers / Pages only
Server-side latency~10–50ms per check~0ms (in-process)
SetupEnv var + CORSwrangler binding
Client-sideSameSame

If you’re already on Cloudflare and server-side auth is on the hot path (e.g. middleware that runs on every request), the service binding is worth it. Otherwise the HTTP client is simpler and portable.