@supabase/server - v1.7.0
    Preparing search index...

    Variable withRequiredClaimsConst Alpha

    withRequiredClaims: Middleware<
        "jwtClaims",
        WithRequiredClaimsConfig
        | void,
        Record<never, never>,
        JWTClaims,
    > = ...

    Alpha. The user-mode auth gate: requires a valid user JWT and contributes non-null ctx.jwtClaims. Verification runs against the project JWKS, the same core withSupabase uses for its user auth mode.

    This is the required-caller counterpart to withClaims, which contributes claims when a token is present and lets token-less requests proceed as anonymous. A pipeline picks one or the other, "claims required" or "claims if present"; composing both is a compile-time conflict on the jwtClaims key.

    Behavior — every short-circuit uses the standard error payload, with the same code withSupabase({ auth: 'user' }) returns for an identical request:

    • No Authorization: Bearer token → 401 MISSING_CREDENTIALS. The handler never runs.
    • An sb_* API key in that position → 401 UNUSABLE_CREDENTIAL: a credential arrived, just not a user JWT.
    • Token present but invalid → 401 INVALID_JWT, naming the specific reason.
    • Token present but no JWKS configured → 500 JWKS_NOT_CONFIGURED; verification is not optional and there is no decode-only mode.

    Because the contribution is non-null, gated handlers read ctx.jwtClaims directly, with no ?.sub ?? 'anon' fallbacks. Downstream entries declaring a jwtClaims prerequisite, such as withPostgresClient, compose with no further verification.

    The 401 and 500 short-circuits carry no CORS headers, and a bare pipeline answers no OPTIONS preflight. For browser callers, compose withCors (@supabase/middleware/cors) ahead of the gate: it answers preflight before the gate runs and stamps Access-Control-* headers on the short-circuit responses.

    After withSupabase in a pipeline the context already carries verified jwtClaims, so this gate is unnecessary there and placing it after withSupabase is a compile-time conflict. Use withSupabase({ auth: 'user' }) to gate that path.

    import { pipeline } from '@supabase/middleware'
    import { withRequiredClaims } from '@supabase/server/middleware/required-claims'
    import { withPostgresClient } from '@supabase/server/middleware/postgres'

    export default {
    fetch: pipeline([withRequiredClaims(), withPostgresClient()], async (req, ctx) => {
    const rows = await ctx.postgres.query`select id, title from posts`
    return Response.json({ rows, caller: ctx.jwtClaims.sub })
    }),
    }

    The composable middleware surface tracks @supabase/middleware 0.x — entry shapes, context keys, and config options may change between 0.x releases.