Bug report
Describe the bug
When I create a custom OAuth2 provider in the supabase app and then want to update/delete is, it always fails with an error like this: "Failed to delete custom OAuth provider: identifier must start with 'custom:' prefix, e.g. 'custom:custom%3Aseznam-cz'". So it is impossible to delete or update the provider. It's identifier is of course correct as I created it through the UI where it's impossible to create a provider with invalid identifier.
To Reproduce
Steps to reproduce the behavior, please provide code snippets or a repository:
- Go to auth providers "https://supabase.com/dashboard/project/< projectId>/auth/providers"
- Create a custom OAuth2 provider with an identifier (e.g. seznam-cz)
- Submit the creation form
- Try to update or delete the existing provider
- See error
Expected behavior
The provider is updated/deleted without any issues.
Screenshots
System information
- OS: macOS
- Browser chromium based
Additional context
I was able to delete the provider manually calling the API with raw identifier (without url encoding the : character).
AI issue analysis (I don't know Go so take this part with a grain of salt, but it might be useful)
Root cause
- supabase-js GoTrueAdminApi.ts (https://github.com/supabase/supabase-js/blob/main/packages/core/auth-js/src/GoTrueAdminApi.ts#L1166) encodes the identifier via encodeURIComponent,
turning custom:seznam-cz into custom%3Aseznam-cz. Request path: /admin/custom-providers/custom%3Aseznam-cz.
- In internal/api/custom_oauth_admin.go (https://github.com/supabase/auth/blob/main/internal/api/custom_oauth_admin.go) the handlers read the path param with chi.URLParam(r,
"identifier"), which returns the raw, percent-encoded value custom%3Aseznam-cz (chi does not auto-decode path params).
- strings.HasPrefix(identifier, "custom:") is then false (%3A ≠ :), and the handler returns the validation error — the format string "... e.g. 'custom:%s'" substitutes the still-encoded
identifier, producing the self-referential custom:custom%3Aseznam-cz example.
Affects: adminCustomOAuthProviderGet, adminCustomOAuthProviderUpdate, adminCustomOAuthProviderDelete (all three have the same check at lines ~117, ~253, ~356).
Suggested fix
Decode the path param before validation:
identifier := chi.URLParam(r, "identifier")
if decoded, err := url.PathUnescape(identifier); err == nil {
identifier = decoded
}
if !strings.HasPrefix(identifier, "custom:") { ... }
Alternative: fix in supabase-js by not encoding : (valid pchar per RFC 3986 §3.3), but the backend fix is safer — it handles any compliant client.
Bug report
Describe the bug
When I create a custom OAuth2 provider in the supabase app and then want to update/delete is, it always fails with an error like this: "Failed to delete custom OAuth provider: identifier must start with 'custom:' prefix, e.g. 'custom:custom%3Aseznam-cz'". So it is impossible to delete or update the provider. It's identifier is of course correct as I created it through the UI where it's impossible to create a provider with invalid identifier.
To Reproduce
Steps to reproduce the behavior, please provide code snippets or a repository:
Expected behavior
The provider is updated/deleted without any issues.
Screenshots
System information
Additional context
I was able to delete the provider manually calling the API with raw identifier (without url encoding the : character).
AI issue analysis (I don't know Go so take this part with a grain of salt, but it might be useful)
Root cause
turning custom:seznam-cz into custom%3Aseznam-cz. Request path: /admin/custom-providers/custom%3Aseznam-cz.
"identifier"), which returns the raw, percent-encoded value custom%3Aseznam-cz (chi does not auto-decode path params).
identifier, producing the self-referential custom:custom%3Aseznam-cz example.
Affects: adminCustomOAuthProviderGet, adminCustomOAuthProviderUpdate, adminCustomOAuthProviderDelete (all three have the same check at lines ~117, ~253, ~356).
Suggested fix
Decode the path param before validation:
identifier := chi.URLParam(r, "identifier")
if decoded, err := url.PathUnescape(identifier); err == nil {
identifier = decoded
}
if !strings.HasPrefix(identifier, "custom:") { ... }
Alternative: fix in supabase-js by not encoding : (valid pchar per RFC 3986 §3.3), but the backend fix is safer — it handles any compliant client.