diff --git a/internal/utils/app_utils.go b/internal/utils/app_utils.go index 76044c9..3da6be2 100644 --- a/internal/utils/app_utils.go +++ b/internal/utils/app_utils.go @@ -90,27 +90,19 @@ func IsRedirectSafe(redirectURL string, domain string) bool { return false } - parsedURL, err := url.Parse(redirectURL) + parsed, err := url.Parse(redirectURL) if err != nil { return false } - if !parsedURL.IsAbs() { - return false - } + hostname := parsed.Hostname() - host := parsedURL.Hostname() - if host == domain { + if strings.HasSuffix(hostname, domain) { return true } - cookieDomain, err := GetCookieDomain(redirectURL) - if err != nil { - return false - } - - return cookieDomain == domain + return hostname == domain } func GetLogLevel(level string) zerolog.Level { diff --git a/internal/utils/app_utils_test.go b/internal/utils/app_utils_test.go index e6cdaeb..c7f8dc3 100644 --- a/internal/utils/app_utils_test.go +++ b/internal/utils/app_utils_test.go @@ -176,6 +176,11 @@ func TestIsRedirectSafe(t *testing.T) { result = utils.IsRedirectSafe(redirectURL, domain) assert.Equal(t, true, result) + // Case with sub-subdomain + redirectURL = "http://a.b.example.com/home" + result = utils.IsRedirectSafe(redirectURL, domain) + assert.Equal(t, true, result) + // Case with empty redirect URL redirectURL = "" result = utils.IsRedirectSafe(redirectURL, domain) @@ -202,41 +207,6 @@ func TestIsRedirectSafe(t *testing.T) { assert.Equal(t, false, result) } -func TestIsRedirectSafeMultiLevel(t *testing.T) { - // Setup - cookieDomain := "tinyauth.example.com" - - // Case with 3rd level domain - redirectURL := "http://tinyauth.example.com/welcome" - result := utils.IsRedirectSafe(redirectURL, cookieDomain) - assert.Equal(t, true, result) - - // Case with root domain - redirectURL = "http://example.com/unsafe" - result = utils.IsRedirectSafe(redirectURL, cookieDomain) - assert.Equal(t, false, result) - - // Case with 4th level domain - redirectURL = "http://auth.tinyauth.example.com/post-login" - result = utils.IsRedirectSafe(redirectURL, cookieDomain) - assert.Equal(t, true, result) - - // Case with 5th level domain (should be unsafe) - redirectURL = "http://x.auth.tinyauth.example.com/deep" - result = utils.IsRedirectSafe(redirectURL, cookieDomain) - assert.Equal(t, false, result) - - // Case with different subdomain - redirectURL = "http://auth.tinyauth.example.net/attack" - result = utils.IsRedirectSafe(redirectURL, cookieDomain) - assert.Equal(t, false, result) - - // Case with malformed URL - redirectURL = "http://[::1]:namedport" - result = utils.IsRedirectSafe(redirectURL, cookieDomain) - assert.Equal(t, false, result) -} - func TestGetOAuthProvidersConfig(t *testing.T) { env := []string{"PROVIDERS_CLIENT1_CLIENT_ID=client1-id", "PROVIDERS_CLIENT1_CLIENT_SECRET=client1-secret"} args := []string{"/tinyauth/tinyauth", "--providers-client2-client-id=client2-id", "--providers-client2-client-secret=client2-secret"}