Skip to content

config push silently ignores [auth.oauth_server], and its diff cannot show it #6367

Description

@neuromusic

Describe the bug

supabase config push accepts, validates and displays [auth.oauth_server], then sends none of it to the project — and the diff it prints for that section is guaranteed empty regardless of what the file says, so there is no way to tell from the CLI's output that nothing happened.

The result is a config file that looks deployed, a push that reports success, and a project where the OAuth server is off.

To Reproduce

  1. Put this in supabase/config.toml for a linked project whose OAuth server is off:
[auth.oauth_server]
enabled = true
allow_dynamic_registration = true
authorization_url_path = "/oauth/consent"
  1. supabase config push

Expected: a diff showing the three values changing, and the project's OAuth server enabled.

Actual: the auth diff contains no oauth_server hunk at all, the push exits 0, and the project is unchanged:

$ curl -s https://<ref>.supabase.co/.well-known/oauth-authorization-server/auth/v1
{"code":404,"error_code":"feature_disabled","msg":"OAuth server is disabled"}

GET /auth/v1/.well-known/openid-configuration still answers 200 but without registration_endpoint, so every MCP client fails dynamic client registration with a message like "Automatic client registration isn't supported by <host>".

Cause

Both halves of the mapping are stubs — apps/cli-go/pkg/config/auth.go L1678-1690:

func (o OAuthServer) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
	// TODO(cemal) :: implement me
	// OAuth server configuration is behind a feature flag in the remote API
	// Will be implemented when the feature reaches GA
}

func (o *OAuthServer) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
	// TODO(cemal) :: implement me
	// ... same
}

Both are wired in and called (L443, L473) — they just do nothing. The TypeScript CLI has the same hole (// OAuthServer — TODO not yet implemented in remote API, auth.sync.ts L1706).

The empty fromAuthConfig is what makes it undetectable. DiffWithRemote builds its comparison target by cloning the local config and overlaying the remote one:

func (a *auth) DiffWithRemote(remoteConfig v1API.AuthConfigResponse, filter ...func(string) bool) ([]byte, error) {
	copy := a.Clone()
	copy.FromRemoteAuthConfig(remoteConfig)

Since OAuthServer.fromAuthConfig overlays nothing, the copy keeps the local values for that section, so local and "remote" are equal by construction. A no-change diff is the guaranteed output whatever the project's real state is.

This was introduced deliberately in #4207, whose description says "The feature isn't in GA yet in the platform, so skipping updating the remote config for now." That was reasonable at the time — the request is that it no longer matches reality.

Why this is worth revisiting now

The remote side appears ready:

  • PATCH /v1/projects/{ref}/config/auth accepts oauth_server_enabled, oauth_server_allow_dynamic_registration and oauth_server_authorization_path (they are in the OpenAPI spec and in the generated API types, non-optional on the response).
  • Studio ships a UI for it at Authentication > OAuth Server with no feature flag or plan gate — only an RBAC permission check.
  • The docs describe the feature as "free to use during the beta period on all Supabase plans".

I switched all three on via the Dashboard on a Free-tier project and they took effect immediately, which suggests the "behind a feature flag in the remote API" comment is now stale.

Note the field names are not the TOML key names: authorization_url_pathoauth_server_authorization_path.

Suggested fix

Implement the two functions. If that is still premature, warn instead of staying silent — a single line on push saying [auth.oauth_server] is local-only and was not pushed would have made this a five-second diagnosis instead of a production outage that nothing detected.

The docs page could also help: its "CLI" tab describes config.toml plus supabase start/stop and never mentions config push, which is technically accurate but easy to read as "the CLI path deploys this".

System information

  • CLI version: reproduced on 2.111.0, stubs still present on main (2.116.0) and in every release since 2.47.0
  • Hosted project, Free tier

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions