auth
auth copied to clipboard
feat(oauth): add Supabase OAuth provider
Summary
This PR adds support for using Supabase Auth as an OAuth 2.1 provider with full PKCE support, enabling Supabase Auth instances to federate authentication to other Supabase Auth instances. This implements the OAuth 2.1 capabilities discussed in https://github.com/orgs/supabase/discussions/38022.
What Changed
1. New Supabase OAuth Provider (internal/api/provider/supabase.go)
- Implements OAuth 2.1 authorization code flow with PKCE. (PKCE is a must for OAuth2.1 Authorization Code flow)
- Temporary Implementation: Currently decodes user data from JWT claims instead of calling a
/userinfoendpoint- TODO: Update to use OpenID Connect Discovery when Supabase Auth supports OIDC
- TODO: Update to call /userinfo endpoint when available
- Scopes: Currently placeholder implementation (not yet supported by Supabase Auth OAuth 2.1)
- Extracts and preserves
app_metadataanduser_metadataas custom claims
2. Generic PKCE Support for OAuth Providers
Added code to support dual PKCE flows:
- User PKCE: Code challenge/verifier between end user and this auth instance
- Provider PKCE: Separate code challenge/verifier between this instance and external provider
Currently, only supabase auth requires PKCE but added the code to make it future proof as OAuth2.1 adoption is increasing. Added RequiresPKCE() method (returns false by default) to all 25 existing providers
Flow Matrix:
| User Flow | Provider Requires PKCE | FlowState Created? | Result |
|---|---|---|---|
| PKCE | Yes | ✅ | Auth code (both PKCEs) |
| PKCE | No | ✅ | Auth code (user PKCE only) |
| Implicit | Yes | ✅ | Token (provider PKCE internal) |
| Implicit | No | ❌ | Token (traditional implicit) |
Configuration
Users can configure the Supabase provider via environment variables:
GOTRUE_EXTERNAL_SUPABASE_ENABLED=true
GOTRUE_EXTERNAL_SUPABASE_CLIENT_ID=your-oauth-client-id
GOTRUE_EXTERNAL_SUPABASE_SECRET=your-oauth-client-secret
GOTRUE_EXTERNAL_SUPABASE_URL=https://other-supabase-project.supabase.co/auth/v1
GOTRUE_EXTERNAL_SUPABASE_REDIRECT_URI=https://your-auth-instance.supabase.co/auth/v1/callback
Technical Highlights
- No Supabase-specific conditionals in flow logic. All PKCE handling works for any provider via the
RequiresPKCE()interface method. - Uses golang.org/x/oauth2 Built-in PKCE:
-
oauth2.GenerateVerifier()- generates code verifier -
oauth2.S256ChallengeOption()- adds challenge to auth URL -
oauth2.VerifierOption()- adds verifier to token exchange
-
- Separation of Concerns:
- User's PKCE stored in
FlowState.CodeChallengeand verified against user's verifier - Provider's PKCE stored in
FlowState.ProviderCodeVerifierand sent to provider during token exchange - Both flows are completely independent
- User's PKCE stored in
Manual Testing Scenarios:
- ✅ User PKCE + Supabase provider (dual PKCE)
- ✅ User implicit + Supabase provider (provider PKCE only, return token)
- ✅ User PKCE + non-PKCE provider (user PKCE only)
- ✅ User implicit + non-PKCE provider (traditional implicit)