Skip to content

Conversation

@Rodriguespn
Copy link

What kind of change does this PR introduce?

Feature - Enables local development and testing of OAuth-protected Edge Functions (like MCP servers).

What is the current behavior?

When building OAuth-protected Edge Functions locally, there are two issues:

  1. No OAuth Protected Resource discovery: There's no way for OAuth clients to discover the authorization server for a protected Edge Function resource via the standard /.well-known/oauth-protected-resource path.

  2. Internal Docker URLs exposed: SUPABASE_URL is set to http://kong:8000 (internal Docker network), which external OAuth clients cannot resolve. This breaks OAuth metadata responses that need client-facing URLs.

What is the new behavior?

1. OAuth Protected Resource Metadata Endpoint

Added Kong route that redirects:

/.well-known/oauth-protected-resource/functions/v1/<function-name>/*
  → /<function-name>/.well-known/oauth-protected-resource

This enables OAuth clients to discover the authorization server for any Edge Function per RFC 9728.

2. SUPABASE_PUBLIC_URL Environment Variable

Added a new environment variable passed to Edge Functions containing the external-facing URL (e.g., http://127.0.0.1:54321).

Edge Functions can use:

  • SUPABASE_URL → for internal API calls (server-to-server within Docker)
  • SUPABASE_PUBLIC_URL → for client-facing URLs (OAuth metadata, redirects)

Example usage:

const supabaseUrl = Deno.env.get('SUPABASE_URL')!  // Internal calls
const publicUrl = Deno.env.get('SUPABASE_PUBLIC_URL') ?? supabaseUrl  // Client-facing

// OAuth metadata uses public URL
const resourceUrl = `${publicUrl}/functions/v1/${functionName}`

// Internal API calls use internal URL
const supabase = createClient(supabaseUrl, anonKey)

Production compatibility: In production, SUPABASE_PUBLIC_URL won't exist, so Edge Functions fall back to SUPABASE_URL (which is already the public URL).

Closes https://linear.app/supabase/issue/DEVWF-940/add-supabase-public-url-environment-variable-to-edge-functions

Related issue: https://linear.app/supabase/issue/AI-311/add-oauth-authentication-section-to-byom-one-pager-docs

Rodriguespn and others added 3 commits December 10, 2025 14:00
Add SUPABASE_PUBLIC_URL environment variable that contains the external-facing
URL (e.g., http://127.0.0.1:54321) for use in client-facing responses.

This is needed for OAuth-protected Edge Functions (like MCP servers) that need
to return public URLs in OAuth metadata and WWW-Authenticate headers, while
still using the internal Docker URL (SUPABASE_URL) for server-to-server calls.

In production, SUPABASE_PUBLIC_URL won't exist, so Edge Functions should
fall back to SUPABASE_URL which is already the public URL.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…rect

The previous implementation appended /.well-known/oauth-protected-resource
to the entire remaining path, causing requests like
/.well-known/oauth-protected-resource/functions/v1/func-name/mcp to fail.

Now correctly extracts just the function name and ignores sub-paths.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@Rodriguespn Rodriguespn requested a review from a team as a code owner December 10, 2025 14:07
@coveralls
Copy link

Pull Request Test Coverage Report for Build 20101390169

Details

  • 2 of 2 (100.0%) changed or added relevant lines in 2 files are covered.
  • 5 unchanged lines in 1 file lost coverage.
  • Overall coverage decreased (-0.02%) to 56.216%

Files with Coverage Reduction New Missed Lines %
internal/gen/keys/keys.go 5 12.9%
Totals Coverage Status
Change from base Build 20098526635: -0.02%
Covered Lines: 6833
Relevant Lines: 12155

💛 - Coveralls

@Rodriguespn Rodriguespn changed the title Feat/supabase public url feat: supabase public url Dec 11, 2025
@Rodriguespn Rodriguespn self-assigned this Dec 11, 2025
local path_after_prefix = uri:gsub("^/.well%-known/oauth%-protected%-resource/functions/v1/", "")
local function_name = path_after_prefix:match("^([^/]+)")
local new_uri = "/" .. function_name .. "/.well-known/oauth-protected-resource"
kong.service.request.set_path(new_uri)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocked on further discussion on how to make this easier for users to get started https://supabase.slack.com/archives/C02KMRX22NR/p1765511478510969?thread_ts=1765363756.296219&cid=C02KMRX22NR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants