Skip to content

Feature/supabase custom auth route#2632

Merged
jlowin merged 6 commits intoPrefectHQ:mainfrom
EloiZalczer:feature/supabase-custom-auth-route
Dec 26, 2025
Merged

Feature/supabase custom auth route#2632
jlowin merged 6 commits intoPrefectHQ:mainfrom
EloiZalczer:feature/supabase-custom-auth-route

Conversation

@EloiZalczer
Copy link
Copy Markdown
Contributor

Description

Added an auth_route argument to SupabaseProvider, according to the suggestion in #2522.

This makes it possible to work with self-hosted supabase auth setups using custom routes.

Contributors Checklist

  • My change closes Allow custom supabase URL scheme #2522
  • I have followed the repository's development workflow
  • I have tested my changes manually and by adding relevant tests
  • I have performed all required documentation updates

Review Checklist

  • I have self-reviewed my changes
  • My Pull Request is ready for review

@marvin-context-protocol marvin-context-protocol Bot added enhancement Improvement to existing functionality. For issues and smaller PR improvements. auth Related to authentication (Bearer, JWT, OAuth, WorkOS) for client or server. labels Dec 16, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 16, 2025

Warning

Rate limit exceeded

@jlowin has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 5 minutes and 3 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 4476bbd and 2b9d33a.

⛔ Files ignored due to path filters (1)
  • tests/server/auth/providers/test_supabase.py is excluded by none and included by none
📒 Files selected for processing (2)
  • docs/integrations/supabase.mdx
  • src/fastmcp/server/auth/providers/supabase.py

Walkthrough

Adds a configurable auth_route (default "/auth/v1") to SupabaseProvider and SupabaseProviderSettings; updates the SupabaseProvider constructor to accept an auth_route parameter and exposes FASTMCP_SERVER_AUTH_SUPABASE_AUTH_ROUTE; replaces hardcoded "/auth/v1" paths with dynamic composition of {project_url}/{auth_route} for JWKS URI, issuer, authorization server URL, and OAuth metadata endpoint; normalizes auth_route by stripping slashes on initialization; and updates docs and examples to surface the new parameter.

Possibly related PRs

  • jlowin/fastmcp PR 2376: Modifies SupabaseProvider and SupabaseProviderSettings and changes JWT verifier construction, overlapping with provider configuration and JWT URL composition.
  • jlowin/fastmcp PR 2030: Updates Supabase integration documentation, overlapping with this PR’s documentation changes for auth_route.

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Feature/supabase custom auth route' clearly describes the main change - adding support for custom Supabase authentication routes.
Description check ✅ Passed The description is complete with all required checklist items checked and references the linked issue #2522, providing context for the change.
Linked Issues check ✅ Passed The PR implements the preferred solution from issue #2522 by adding an optional auth_route parameter with '/auth/v1' as the default, meeting all stated requirements.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing the auth_route feature across code and documentation files as required by issue #2522.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/fastmcp/server/auth/providers/supabase.py (1)

63-64: Update docstring to reflect dynamic auth_route.

The documentation still references hardcoded /auth/v1 paths, but the implementation now uses a configurable auth_route. Update these lines to mention the default or use placeholder text.

Apply this diff to update the documentation:

-       - FastMCP verifies JWTs using the JWKS endpoint at {project_url}/auth/v1/.well-known/jwks.json
-       - JWTs are issued by {project_url}/auth/v1
+       - FastMCP verifies JWTs using the JWKS endpoint at {project_url}{auth_route}/.well-known/jwks.json
+       - JWTs are issued by {project_url}{auth_route} (default: /auth/v1)
🧹 Nitpick comments (2)
docs/integrations/supabase.mdx (2)

121-123: Enhance parameter documentation with validation requirements.

The documentation should clarify that auth_route must start with a forward slash, as this is a requirement for proper URL construction in the implementation.

Apply this diff to improve the documentation:

 <ParamField path="FASTMCP_SERVER_AUTH_SUPABASE_AUTH_ROUTE" default="/auth/v1">
-Your Supabase auth route (e.g., `/auth/v1`)
+Your Supabase auth route. Must start with a forward slash. Used for self-hosted Supabase Auth instances with custom routes (e.g., `/auth/v1` for managed Supabase, `/my/auth/route` for self-hosted)
 </ParamField>

131-139: Consider adding AUTH_ROUTE to example .env file.

For completeness and to help users understand all available configuration options, consider adding the FASTMCP_SERVER_AUTH_SUPABASE_AUTH_ROUTE variable to the example .env file, even if commented out to show it's optional.

Example addition:

 # Supabase configuration
 FASTMCP_SERVER_AUTH_SUPABASE_PROJECT_URL=https://abc123.supabase.co
 FASTMCP_SERVER_AUTH_SUPABASE_BASE_URL=https://your-server.com
+# FASTMCP_SERVER_AUTH_SUPABASE_AUTH_ROUTE=/auth/v1  # Only needed for self-hosted with custom routes
 FASTMCP_SERVER_AUTH_SUPABASE_REQUIRED_SCOPES=openid,email
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8abd84b and 75eef92.

⛔ Files ignored due to path filters (1)
  • tests/server/auth/providers/test_supabase.py is excluded by none and included by none
📒 Files selected for processing (2)
  • docs/integrations/supabase.mdx (3 hunks)
  • src/fastmcp/server/auth/providers/supabase.py (6 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
docs/**/*.mdx

📄 CodeRabbit inference engine (docs/.cursor/rules/mintlify.mdc)

docs/**/*.mdx: Use clear, direct language appropriate for technical audiences
Write in second person ('you') for instructions and procedures in MDX documentation
Use active voice over passive voice in MDX technical documentation
Employ present tense for current states and future tense for outcomes in MDX documentation
Maintain consistent terminology throughout all MDX documentation
Keep sentences concise while providing necessary context in MDX documentation
Use parallel structure in lists, headings, and procedures in MDX documentation
Lead with the most important information using inverted pyramid structure in MDX documentation
Use progressive disclosure in MDX documentation: present basic concepts before advanced ones
Break complex procedures into numbered steps in MDX documentation
Include prerequisites and context before instructions in MDX documentation
Provide expected outcomes for each major step in MDX documentation
End sections with next steps or related information in MDX documentation
Use descriptive, keyword-rich headings for navigation and SEO in MDX documentation
Focus on user goals and outcomes rather than system features in MDX documentation
Anticipate common questions and address them proactively in MDX documentation
Include troubleshooting for likely failure points in MDX documentation
Provide multiple pathways (beginner vs advanced) but offer an opinionated path to avoid overwhelming users in MDX documentation
Always include complete, runnable code examples that users can copy and execute in MDX documentation
Show proper error handling and edge case management in MDX code examples
Use realistic data instead of placeholder values in MDX code examples
Include expected outputs and results for verification in MDX code examples
Test all code examples thoroughly before publishing in MDX documentation
Specify language and include filename when relevant in MDX code examples
Add explanatory comments for complex logic in MDX code examples
Document all API...

Files:

  • docs/integrations/supabase.mdx
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Use Python ≥3.10 with full type annotations in all code
Avoid bare except statements - be specific with exception types in error handling
Follow existing patterns and maintain consistency; prioritize readable, understandable code over cleverness
Avoid obfuscated or confusing patterns even if they're shorter

Files:

  • src/fastmcp/server/auth/providers/supabase.py
🧬 Code graph analysis (1)
src/fastmcp/server/auth/providers/supabase.py (1)
src/fastmcp/server/auth/providers/jwt.py (1)
  • JWTVerifier (165-498)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Run tests with lowest-direct dependencies
  • GitHub Check: Run tests: Python 3.10 on windows-latest
  • GitHub Check: Run tests: Python 3.13 on ubuntu-latest
  • GitHub Check: Run tests: Python 3.10 on ubuntu-latest
🔇 Additional comments (3)
src/fastmcp/server/auth/providers/supabase.py (2)

37-37: LGTM! Good backward compatibility.

The default value of "/auth/v1" ensures existing deployments continue to work without changes.


136-137: LGTM! Dynamic URL construction is correct.

The auth_route is properly integrated into all necessary endpoints: JWKS URI, issuer, authorization server, and OAuth metadata. Assuming the validation suggested in the previous comment is added, this implementation correctly supports custom auth routes.

Also applies to: 145-145, 170-170

docs/integrations/supabase.mdx (1)

20-20: LGTM! Clear prerequisite update.

The addition of "or a self-hosted Supabase Auth instance" clearly communicates when this feature would be used.

Comment thread docs/integrations/supabase.mdx
Comment thread src/fastmcp/server/auth/providers/supabase.py Outdated
@EloiZalczer EloiZalczer force-pushed the feature/supabase-custom-auth-route branch from a30375c to 4476bbd Compare December 19, 2025 14:26
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/fastmcp/server/auth/providers/supabase.py (2)

131-131: Consider validating non-empty auth_route.

The strip("/") normalization handles various input formats well. However, an empty string input would result in URLs with double slashes (e.g., https://example.com//.well-known/...).

🔎 Proposed validation
         self.auth_route = settings.auth_route.strip("/")
+        if not self.auth_route:
+            raise ValueError("auth_route cannot be empty")

168-171: Add timeout to prevent indefinite hangs.

The HTTP request to fetch Supabase metadata has no timeout configured. If Supabase is unresponsive, this could block indefinitely.

🔎 Proposed fix
             try:
-                async with httpx.AsyncClient() as client:
+                async with httpx.AsyncClient(timeout=10.0) as client:
                     response = await client.get(
                         f"{self.project_url}/{self.auth_route}/.well-known/oauth-authorization-server"
                     )
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e473fe4 and a30375c.

📒 Files selected for processing (2)
  • docs/python-sdk/fastmcp-server-auth-providers-supabase.mdx (1 hunks)
  • src/fastmcp/server/auth/providers/supabase.py (7 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
docs/**/*.mdx

📄 CodeRabbit inference engine (docs/.cursor/rules/mintlify.mdc)

docs/**/*.mdx: Use clear, direct language appropriate for technical audiences
Write in second person ('you') for instructions and procedures in MDX documentation
Use active voice over passive voice in MDX technical documentation
Employ present tense for current states and future tense for outcomes in MDX documentation
Maintain consistent terminology throughout all MDX documentation
Keep sentences concise while providing necessary context in MDX documentation
Use parallel structure in lists, headings, and procedures in MDX documentation
Lead with the most important information using inverted pyramid structure in MDX documentation
Use progressive disclosure in MDX documentation: present basic concepts before advanced ones
Break complex procedures into numbered steps in MDX documentation
Include prerequisites and context before instructions in MDX documentation
Provide expected outcomes for each major step in MDX documentation
End sections with next steps or related information in MDX documentation
Use descriptive, keyword-rich headings for navigation and SEO in MDX documentation
Focus on user goals and outcomes rather than system features in MDX documentation
Anticipate common questions and address them proactively in MDX documentation
Include troubleshooting for likely failure points in MDX documentation
Provide multiple pathways (beginner vs advanced) but offer an opinionated path to avoid overwhelming users in MDX documentation
Always include complete, runnable code examples that users can copy and execute in MDX documentation
Show proper error handling and edge case management in MDX code examples
Use realistic data instead of placeholder values in MDX code examples
Include expected outputs and results for verification in MDX code examples
Test all code examples thoroughly before publishing in MDX documentation
Specify language and include filename when relevant in MDX code examples
Add explanatory comments for complex logic in MDX code examples
Document all API...

Files:

  • docs/python-sdk/fastmcp-server-auth-providers-supabase.mdx
docs/python-sdk/**/*

📄 CodeRabbit inference engine (AGENTS.md)

Never modify docs/python-sdk/** files as they are auto-generated

Files:

  • docs/python-sdk/fastmcp-server-auth-providers-supabase.mdx
src/fastmcp/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/fastmcp/**/*.py: Write Python code with ≥3.10 type annotations required throughout
Never use bare except - be specific with exception types

Files:

  • src/fastmcp/server/auth/providers/supabase.py
🧠 Learnings (1)
📚 Learning: 2025-11-26T21:52:08.947Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: docs/.cursor/rules/mintlify.mdc:0-0
Timestamp: 2025-11-26T21:52:08.947Z
Learning: Applies to docs/**/*.mdx : Provide authentication examples showing proper format in MDX API documentation

Applied to files:

  • docs/python-sdk/fastmcp-server-auth-providers-supabase.mdx
🧬 Code graph analysis (1)
src/fastmcp/server/auth/providers/supabase.py (1)
src/fastmcp/server/auth/providers/jwt.py (1)
  • JWTVerifier (165-498)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Run tests: Python 3.10 on ubuntu-latest
  • GitHub Check: Run tests: Python 3.13 on ubuntu-latest
  • GitHub Check: Run tests with lowest-direct dependencies
  • GitHub Check: Run tests: Python 3.10 on windows-latest
🔇 Additional comments (5)
src/fastmcp/server/auth/providers/supabase.py (5)

37-37: LGTM!

The default value /auth/v1 matches Supabase's standard auth endpoint path and provides a sensible fallback.


63-64: LGTM!

The docstring accurately describes the endpoint construction. The use of {project_url}{auth_route} aligns with the default value format.


97-97: LGTM!

The parameter follows the established pattern with NotSetT for optional override, consistent with other constructor parameters.


134-140: LGTM!

The JWT verifier initialization correctly constructs JWKS URI and issuer using the normalized URL components with explicit path separators.


143-147: LGTM!

The authorization server URL construction is consistent with the JWKS/issuer URL patterns.

Comment on lines +38 to +39
- FastMCP verifies JWTs using the JWKS endpoint at {project_url}{auth_route}/.well-known/jwks.json
- JWTs are issued by {project_url}{auth_route}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

This file should not be manually modified.

As per coding guidelines, files in docs/python-sdk/** are auto-generated and should not be modified directly. These changes should be reverted, and the documentation should be regenerated from source instead.

🤖 Prompt for AI Agents
In docs/python-sdk/fastmcp-server-auth-providers-supabase.mdx around lines 38 to
39, this file is auto-generated and was manually edited; revert the manual
changes to restore the generated content and regenerate the documentation from
the source generator (do not commit manual edits). Undo the diff, run the docs
generation workflow or script used in this repo to produce files under
docs/python-sdk/**, verify the generated output includes the intended JWKS and
issuer lines, and commit only the regenerated files from the generator rather
than manual changes.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/fastmcp/server/auth/providers/supabase.py (1)

165-182: Consider more specific exception handling.

The current except Exception is quite broad. For HTTP client operations, catching more specific exceptions provides clearer error context and avoids masking unexpected errors.

🔎 Proposed improvement
         async def oauth_authorization_server_metadata(request):
             """Forward Supabase OAuth authorization server metadata with FastMCP customizations."""
             try:
                 async with httpx.AsyncClient() as client:
                     response = await client.get(
                         f"{self.project_url}/{self.auth_route}/.well-known/oauth-authorization-server"
                     )
                     response.raise_for_status()
                     metadata = response.json()
                     return JSONResponse(metadata)
-            except Exception as e:
+            except httpx.HTTPStatusError as e:
+                return JSONResponse(
+                    {
+                        "error": "server_error",
+                        "error_description": f"Supabase returned error: {e.response.status_code}",
+                    },
+                    status_code=502,
+                )
+            except httpx.RequestError as e:
                 return JSONResponse(
                     {
                         "error": "server_error",
-                        "error_description": f"Failed to fetch Supabase metadata: {e}",
+                        "error_description": f"Failed to connect to Supabase: {e}",
                     },
                     status_code=500,
                 )
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a30375c and 4476bbd.

⛔ Files ignored due to path filters (1)
  • tests/server/auth/providers/test_supabase.py is excluded by none and included by none
📒 Files selected for processing (3)
  • docs/integrations/supabase.mdx (3 hunks)
  • docs/python-sdk/fastmcp-server-auth-providers-supabase.mdx (1 hunks)
  • src/fastmcp/server/auth/providers/supabase.py (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/python-sdk/fastmcp-server-auth-providers-supabase.mdx
  • docs/integrations/supabase.mdx
🧰 Additional context used
📓 Path-based instructions (1)
src/fastmcp/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/fastmcp/**/*.py: Write Python code with ≥3.10 type annotations required throughout
Never use bare except - be specific with exception types

Files:

  • src/fastmcp/server/auth/providers/supabase.py
🧬 Code graph analysis (1)
src/fastmcp/server/auth/providers/supabase.py (1)
src/fastmcp/server/auth/providers/jwt.py (1)
  • JWTVerifier (165-498)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Run tests: Python 3.10 on windows-latest
  • GitHub Check: Run tests: Python 3.13 on ubuntu-latest
  • GitHub Check: Run tests with lowest-direct dependencies
🔇 Additional comments (3)
src/fastmcp/server/auth/providers/supabase.py (3)

37-37: LGTM!

The auth_route field with a sensible default of "/auth/v1" allows backward compatibility while enabling customization for self-hosted Supabase setups.


129-131: Normalization approach is clean.

The strategy of stripping slashes from both project_url (trailing) and auth_route (both ends), then composing URLs with explicit / separators, handles various user input formats gracefully.

Minor edge case: if someone passes auth_route="", the resulting URLs would have double slashes (e.g., https://example.com//.well-known/...). While most HTTP servers handle this correctly, you could consider adding validation to reject empty strings if this is never a valid use case.


134-145: LGTM!

The JWT verifier and authorization server configuration correctly use the dynamic auth_route for all endpoint URLs. The composition pattern is consistent across JWKS URI, issuer, and authorization server configuration.

@marvin-context-protocol
Copy link
Copy Markdown
Contributor

Test Failure Analysis

Summary: The Python 3.10 on ubuntu-latest job failed with exit code 1, but the exact test failure cannot be determined due to API log access restrictions.

Root Cause: This appears to be an intermittent/flaky test failure rather than a code issue. Evidence:

  • The same commit (4476bbd) passed in run #4293 but failed in run #4294
  • All other test jobs passed: Python 3.13 on Ubuntu, Python 3.10 on Windows, lowest-dependencies, and integration tests
  • Local test execution on the PR branch shows all 3,185 tests passing
  • Static analysis passed without issues

This failure pattern is consistent with known pytest-xdist worksteal scheduler issues on Python 3.10, particularly related to threading, race conditions, and worker process management (see pytest-xdist issue #884 and issue #907).

Suggested Solution:

  1. Re-run the failed workflow - This is likely an intermittent CI environment issue rather than a code problem
  2. If the issue persists, consider temporarily adjusting the test configuration for Python 3.10 specifically to use --dist load instead of --dist worksteal
Detailed Analysis

Test Environment

  • Failed: Python 3.10 on ubuntu-latest (exit code 1)
  • Passed: Python 3.13 on ubuntu-latest ✅
  • Passed: Python 3.10 on windows-latest ✅
  • Passed: Lowest dependencies ✅
  • Passed: Integration tests ✅

Local Verification

$ uv run pytest tests/server/auth/providers/test_supabase.py -v
16 passed in 0.51s

$ uv run pytest -n auto -m "not integration and not client_process"
3185 passed, 1 xfailed, 1 xpassed in 99.78s

Known Issues

pytest-xdist with --dist worksteal has documented issues with Python 3.10 on Ubuntu:

  • Hangs and race conditions with high core counts
  • Main thread execution issues since pytest-xdist 3.3.0
  • Intermittent failures on GitHub Actions runners

References:

Related Files
  • tests/server/auth/providers/test_supabase.py - All 16 tests pass locally
  • src/fastmcp/server/auth/providers/supabase.py - Implementation with auth_route parameter
  • .github/workflows/run-tests.yml - Uses --dist worksteal for Ubuntu runs

Note: Unable to access detailed job logs via API (403 error). Analysis based on workflow metadata, local test execution, and known pytest-xdist issues.

@jlowin jlowin changed the base branch from main to release/2.x December 26, 2025 20:00
@jlowin jlowin changed the base branch from release/2.x to main December 26, 2025 20:00
Resolved conflicts by updating PR 2632 to comply with PR 2752:
- Removed SupabaseProviderSettings and pydantic-settings usage
- Added auth_route parameter with direct parameter pattern
- Updated tests to remove env var loading tests
- Updated documentation to match new pattern
Copy link
Copy Markdown
Member

@jlowin jlowin left a comment

Choose a reason for hiding this comment

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

@EloiZalczer Thanks! I made some minor changes to account for changes in #2752 and I think it's GTG. Since main is tracking the FastMCP 3.0 release, I will also cherry pick these commits into a 2.14.2 release we may do in the next week.

@jlowin jlowin merged commit fb11282 into PrefectHQ:main Dec 26, 2025
8 checks passed
@EloiZalczer EloiZalczer deleted the feature/supabase-custom-auth-route branch December 29, 2025 10:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auth Related to authentication (Bearer, JWT, OAuth, WorkOS) for client or server. enhancement Improvement to existing functionality. For issues and smaller PR improvements.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow custom supabase URL scheme

2 participants