Alpha. Contributes ctx.jwtClaims by verifying the caller's Bearer token against the project JWKS — the same verification core withSupabase uses for its user auth mode.
Use this when composing a standalone pipeline([...], handler) that is not wrapped by withSupabase — for example a Supabase-agnostic Edge Function that still wants the caller's verified claims available to a downstream middleware such as withPostgresClient. Inside withSupabase, the context already carries jwtClaims, so withClaims is unnecessary.
Behavior:
Authorization: Bearer token (or an sb_* API key in that position) → contributes null; the request proceeds as anonymous.{ message, code }, matching withSupabase's error shape).withClaims is not an auth gate. It never rejects a request that has no token. A pipeline like [withClaims(), withSupabaseClient()] accepts anonymous callers and is not the composable form of withSupabase({ auth: 'user' }), which rejects token-less requests with a 401. To require an authenticated caller, compose withRequiredClaims from @supabase/server/middleware/required-claims instead. The two entries share the jwtClaims key, so a pipeline picks "claims if present" or "claims required"; composing both is a compile-time conflict.
import { pipeline } from '@supabase/middleware'
import { withClaims } from '@supabase/server/middleware/claims'
import { withPostgresClient } from '@supabase/server/middleware/postgres'
export default {
fetch: pipeline([withClaims(), withPostgresClient()], async (req, ctx) => {
const rows = await ctx.postgres.query`select id, title from posts`
return Response.json({ rows, caller: ctx.jwtClaims?.sub ?? 'anon' })
}),
}
The composable middleware surface tracks @supabase/middleware 0.x — entry shapes, context keys, and config options may change between 0.x releases.