Skip to content

Commit a631cd8

Browse files
committed
fix: Cleanup implementation
1 parent 38dc897 commit a631cd8

4 files changed

Lines changed: 13 additions & 10 deletions

File tree

internal/api/oauthserver/authorize.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ func (s *Server) buildSuccessRedirectURL(authorization *models.OAuthServerAuthor
606606
q.Set("state", *authorization.State)
607607
}
608608
u.RawQuery = q.Encode()
609-
return utilities.PreserveEmptyAuthority(authorization.RedirectURI, u, u.String())
609+
return utilities.PreserveEmptyAuthority(authorization.RedirectURI, u)
610610
}
611611

612612
// buildErrorRedirectURL builds an error redirect URL with the given parameters
@@ -619,7 +619,7 @@ func (s *Server) buildErrorRedirectURL(redirectURI, errorCode, errorDescription,
619619
q.Set("state", state)
620620
}
621621
u.RawQuery = q.Encode()
622-
return utilities.PreserveEmptyAuthority(redirectURI, u, u.String())
622+
return utilities.PreserveEmptyAuthority(redirectURI, u)
623623
}
624624

625625
// buildAuthorizationURL safely joins a base URL with a path, handling slashes correctly

internal/api/verify.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ func (a *API) prepErrorRedirectURL(err *HTTPError, r *http.Request, rurl string,
510510
// Add Supabase Auth identifier to help clients distinguish Supabase Auth redirects
511511
hq.Set("sb", "")
512512
u.Fragment = hq.Encode()
513-
return utilities.PreserveEmptyAuthority(rurl, u, u.String()), nil
513+
return utilities.PreserveEmptyAuthority(rurl, u), nil
514514
}
515515

516516
func (a *API) prepRedirectURL(message string, rurl string, flowType models.FlowType) (string, error) {
@@ -528,7 +528,7 @@ func (a *API) prepRedirectURL(message string, rurl string, flowType models.FlowT
528528
// Add Supabase Auth identifier to help clients distinguish Supabase Auth redirects
529529
hq.Set("sb", "")
530530
u.Fragment = hq.Encode()
531-
return utilities.PreserveEmptyAuthority(rurl, u, u.String()), nil
531+
return utilities.PreserveEmptyAuthority(rurl, u), nil
532532
}
533533

534534
func (a *API) prepPKCERedirectURL(rurl, code string) (string, error) {
@@ -539,7 +539,7 @@ func (a *API) prepPKCERedirectURL(rurl, code string) (string, error) {
539539
q := u.Query()
540540
q.Set("code", code)
541541
u.RawQuery = q.Encode()
542-
return utilities.PreserveEmptyAuthority(rurl, u, u.String()), nil
542+
return utilities.PreserveEmptyAuthority(rurl, u), nil
543543
}
544544

545545
func (a *API) emailChangeVerify(r *http.Request, conn *storage.Connection, params *VerifyParams, user *models.User) (*models.User, error) {

internal/utilities/url.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@ import (
99
// an empty authority (e.g. custom-scheme deep links like "myapp://"). Go's
1010
// net/url package normalizes these to "scheme:" on String(), which breaks
1111
// iOS/Android deep-link clients that register for the "scheme://" form.
12-
//
13-
// Call with the original input string, the parsed URL, and the already-
14-
// serialized output of u.String().
15-
func PreserveEmptyAuthority(rurl string, u *url.URL, formatted string) string {
12+
func PreserveEmptyAuthority(rurl string, u *url.URL) string {
13+
formatted := u.String()
1614
if u.Scheme != "" && u.Host == "" && u.Path == "" && strings.HasPrefix(rurl, u.Scheme+"://") {
1715
return strings.Replace(formatted, u.Scheme+":", u.Scheme+"://", 1)
1816
}

internal/utilities/url_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,12 @@ func TestPreserveEmptyAuthority(t *testing.T) {
2323
{"triple slash", "myapp:///callback", "myapp:///callback?code=ABC"},
2424
{"host port path", "myapp://host:1234/callback", "myapp://host:1234/callback?code=ABC"},
2525
{"existing query", "myapp://?x=1", "myapp://?code=ABC&x=1"},
26+
{"existing code param overwrites", "myapp://?code=OLD", "myapp://?code=ABC"},
2627
{"fragment", "myapp://#frag", "myapp://?code=ABC#frag"},
28+
// net/url lowercases the scheme per RFC 3986 §3.1. iOS URL-scheme
29+
// matching is case-sensitive in practice, so mixed-case schemes are
30+
// normalized to lowercase by the time they reach the client.
31+
{"mixed case scheme", "MyApp://callback", "myapp://callback?code=ABC"},
2732
}
2833
for _, c := range cases {
2934
t.Run(c.name, func(t *testing.T) {
@@ -32,7 +37,7 @@ func TestPreserveEmptyAuthority(t *testing.T) {
3237
q := u.Query()
3338
q.Set("code", "ABC")
3439
u.RawQuery = q.Encode()
35-
got := PreserveEmptyAuthority(c.in, u, u.String())
40+
got := PreserveEmptyAuthority(c.in, u)
3641
assert.Equal(t, c.want, got)
3742
})
3843
}

0 commit comments

Comments
 (0)