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

    Variable withOAuthProtectedResourceConst Alpha

    withOAuthProtectedResource: Middleware<
        "oauthProtectedResource",
        OAuthProtectedResourceConfig
        | undefined,
        Record<never, never>,
        OAuthProtectedResourceContribution,
    > = ...

    Alpha. Wraps a request handler with OAuth 2.1 Protected Resource behavior (RFC 9728).

    • Serves OAuth Protected Resource Metadata at GET {resource}/oauth-protected-resource (with permissive CORS, including the OPTIONS preflight, so browser-based clients can read it)
    • Enriches a 401 from the inner handler with WWW-Authenticate: Bearer resource_metadata="...", unless the handler already set a WWW-Authenticate header (its value wins)
    • Passes any other path through to the inner handler unchanged (composition, not routing, decides what happens to it)
    • Answers a default URL it cannot derive with the JSON error response withSupabase returns for its own configuration failures (500, x-supabase-server-error); a throw from a configured resourceServer or authorizationServer function is the caller's and propagates

    The metadata route is matched on the path suffix, so any GET or OPTIONS ending in /oauth-protected-resource is answered here and never reaches the inner handler, at any depth. Other methods pass through.

    Zero-config on Supabase Edge Functions. Elsewhere OAuthProtectedResourceConfig.resourceServer is required and OAuthProtectedResourceConfig.authorizationServer falls back to SUPABASE_URL; one that cannot be resolved is reported as MISSING_RESOURCE_SERVER / MISSING_AUTHORIZATION_SERVER.

    Contributes ctx.oauthProtectedResource (the resolved metadata URL) to the downstream context. Nested under withSupabase, the key is typed on the handler's ctx when the outermost call is anchored with satisfies FetchHandler — see withSupabase's type note. Placed directly after withSupabase with an auth mode that requires credentials, the composition is refused when the stack is built, since the gate would answer discovery and preflight before this middleware runs.

    The OAuth Protected Resource surface is alpha — the config shape, the contributed context key, and the metadata route may change in a minor release.

    import { withOAuthProtectedResource, withSupabase } from '@supabase/server'

    Deno.serve(
    withOAuthProtectedResource(
    withSupabase({ auth: 'user' }, async (_req, { supabase }) => {
    const { data, error } = await supabase.from('items').select('*')
    if (error) throw error
    return Response.json(data)
    }),
    ),
    )
    import { withOAuthProtectedResource, fromSupabaseUrl } from '@supabase/server'

    export default {
    fetch: withOAuthProtectedResource(
    {
    resourceServer: (req) => new URL(req.url).origin + '/api/mcp',
    authorizationServer: fromSupabaseUrl('https://abc123.supabase.co'),
    },
    handler,
    ),
    }
    withOAuthProtectedResource(
    {
    resourceServer: 'https://api.example.com/mcp',
    authorizationServer: 'https://example.clerk.accounts.dev',
    },
    handler,
    )