Skip to content

fix: preserve "//" in redirect URLs with empty authority#2484

Open
vatsalpatel wants to merge 2 commits into
supabase:masterfrom
vatsalpatel:fix/redirect-url-empty-authority
Open

fix: preserve "//" in redirect URLs with empty authority#2484
vatsalpatel wants to merge 2 commits into
supabase:masterfrom
vatsalpatel:fix/redirect-url-empty-authority

Conversation

@vatsalpatel
Copy link
Copy Markdown

@vatsalpatel vatsalpatel commented Apr 17, 2026

What kind of change does this PR introduce?

Bug fix

What is the current behavior?

Custom-scheme PKCE redirect URIs with empty authority get the // stripped when serialized. Go's net/url normalizes scheme:// with no host down to scheme: on String():

input: "myapp://"             → "myapp:?code=ABC"           ❌
input: "com.example.app://"   → "com.example.app:?code=..." ❌
input: "myapp://host"         → "myapp://host?code=ABC"     ✅
input: "https://example.com"  → "https://example.com?..."   ✅

iOS/Android clients registered for the scheme:// form don't match scheme:?..., so native Sign in with Apple / Google deep links via PKCE fail silently. Affects every redirect URL builder that round-trips through url.Parse → mutate → u.String():

  • internal/api/verify.goprepErrorRedirectURL, prepRedirectURL, prepPKCERedirectURL
  • internal/api/oauthserver/authorize.gobuildSuccessRedirectURL, buildErrorRedirectURL

This is RFC 3986 §3.2 behavior (authority component is optional but // only appears when authority is present), not a Go bug - net/url is correct to normalize. The fix preserves the original input shape rather than fighting the standard.

What is the new behavior?

Adds utilities.PreserveEmptyAuthority which detects when the original input used scheme:// with empty authority and restores the // that net/url drops. Applied at all five build sites above.

Leaves already-correct inputs untouched (including intentional scheme: without slashes, and any URL with a host or path).

Test plan

  • go test -run TestPreserveEmptyAuthority ./internal/utilities — table-driven coverage for empty authority, host+path, triple-slash, existing query, fragment, reverse-DNS schemes, plain scheme: (unchanged), and https:// (unchanged).
  • go vet ./... clean
  • Existing test suite still passes

Closes #2423

Go's net/url normalizes "scheme://" with empty authority to "scheme:" on String(), breaking iOS/Android custom-scheme deep links like "myapp://" emitted as "myapp:?code=...".

Adds utilities.PreserveEmptyAuthority and applies it in all redirect URL builders in internal/api/verify.go and oauthserver/authorize.go.

Closes supabase#2423
@vatsalpatel vatsalpatel requested a review from a team as a code owner April 17, 2026 16:23
@vatsalpatel
Copy link
Copy Markdown
Author

Hi @cstockton, would you have a few minutes to take a look at this when you get a chance? Happy to rebase or adjust if anything needs changing.

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.

prepPKCERedirectURLdrops // from custom scheme URIs, corrupting PKCE auth code on iOS (%23)

1 participant