Auth Middleware
Let's add execution authentication with one middleware file. It rejects route-execution requests that don't carry a valid bearer token, and it passes the verified user id to every tool call in that run:
import { allow, defineMiddleware, reject } from "@b4run/sdk"
export default defineMiddleware(async (req) => {
const auth = req.headers["authorization"]
if (!auth?.startsWith("Bearer ")) {
return reject(401, { error: "Missing bearer token" })
}
const token = auth.slice("Bearer ".length)
const userId = await verifyJwt(token).catch(() => null)
if (!userId) {
return reject(401, { error: "Invalid token" })
}
return allow({ userId })
})
async function verifyJwt(token: string): Promise<string> {
// Replace with your real verifier.
const res = await fetch("https://auth.example.com/verify", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ token }),
})
if (!res.ok) throw new Error("verify failed")
const body = (await res.json()) as { readonly sub: string }
return body.sub
}NotesCopy link to section: Notes
- The tool name is the file name. The file is
tools/loadProfile.ts, so you callctx.tools.loadProfile(...). A file namedtools/load-profile.tswould bectx.tools["load-profile"](...), so stick with camelCase file names. - There's one global middleware.
src/middleware.tsruns once per route-execution request, before the route. For per-route policy, branch onreq.routeId. rejectshort-circuits. The route never runs, and the body ofreject(status, body?)becomes the HTTP response.allow(context)flows to tools. Whatever you pass becomesctx.middlewareon every tool call for that request. Callallow()with no arguments and it'sundefined.- Throwing returns 500. Any uncaught error becomes HTTP 500. Return an explicit
reject(401, ...)with a real body so callers get a useful response. - Check where you deploy. This middleware runs under
b4 dev, the Node B4.run HTTP runtime (b4 startor the generatedserver.mjs), and Hono builds. The generated LangSmith graph entries leave B4.run's HTTP middleware out, so on LangSmith you'll enforce authentication in the platform itself.