Skip to content

Conversation

@Rodriguespn
Copy link

@Rodriguespn Rodriguespn commented Dec 10, 2025

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'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.

Per RFC 9728, OAuth clients should be able to discover the authorization server by fetching:

/.well-known/oauth-protected-resource/<resource-path>

This wasn't possible for Edge Functions running locally.

What is the new behavior?

OAuth Protected Resource Metadata Endpoint

Added a Kong route that redirects OAuth protected resource discovery requests to the appropriate Edge Function:

/.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.

Example Edge Function implementation:

const supabaseUrl = Deno.env.get('SUPABASE_URL')!
const publicUrl = Deno.env.get('PUBLIC_URL') || `${supabaseUrl}/functions/v1/my-function`
const authServerUrl = Deno.env.get('AUTH_SERVER_URL') || `${supabaseUrl}/auth/v1`

app.get('/.well-known/oauth-protected-resource', (c) => {
  return c.json({
    resource: publicUrl,
    authorization_servers: [authServerUrl],
    scopes_supported: ['openid', 'profile', 'email'],
  })
})

Edge Functions can use custom environment variables (PUBLIC_URL, AUTH_SERVER_URL) passed via supabase functions serve --env-file to override URLs for local development.

Testing

# Start local Supabase
supabase start

# Serve your Edge Function
supabase functions serve my-oauth-function --env-file .env.local

# Test the OAuth protected resource discovery
curl http://127.0.0.1:54321/.well-known/oauth-protected-resource/functions/v1/my-oauth-function

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

Should close #4322 @cemalkilic

@Rodriguespn Rodriguespn requested a review from a team as a code owner December 10, 2025 14:07
@coveralls
Copy link

coveralls commented Dec 10, 2025

Pull Request Test Coverage Report for Build 20369862521

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 1 of 1 (100.0%) changed or added relevant line in 1 file are covered.
  • 68 unchanged lines in 6 files lost coverage.
  • Overall coverage decreased (-0.2%) to 56.046%

Files with Coverage Reduction New Missed Lines %
internal/gen/types/types.go 1 97.53%
internal/gen/keys/keys.go 5 12.9%
cmd/gen.go 9 0.0%
internal/functions/new/new.go 12 68.18%
cmd/init.go 19 0.0%
internal/init/init.go 22 78.9%
Totals Coverage Status
Change from base Build 20098526635: -0.2%
Covered Lines: 6813
Relevant Lines: 12156

💛 - 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
@Rodriguespn Rodriguespn marked this pull request as draft December 19, 2025 11:55
sweatybridge
sweatybridge previously approved these changes Dec 19, 2025
@Rodriguespn Rodriguespn marked this pull request as ready for review December 19, 2025 12:32
Rodriguespn and others added 4 commits December 19, 2025 12:32
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]>
The OAuth protected resource redirect feature doesn't require
SUPABASE_PUBLIC_URL. Edge Functions can handle URL resolution
themselves using custom env vars like PUBLIC_URL if needed.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@Rodriguespn Rodriguespn force-pushed the feat/supabase-public-url branch from ddae315 to 74ef3f6 Compare December 19, 2025 12:32
@Rodriguespn Rodriguespn changed the title feat: supabase public url feat: handle oauth-protected-resource for edge functions Dec 19, 2025
@sweatybridge sweatybridge dismissed their stale review December 23, 2025 07:05

decided to go with www-authenticate header instead

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.

5 participants