From ecfcbcb19fb460353588f60d9549a3625df80631 Mon Sep 17 00:00:00 2001 From: oliverpool Date: Thu, 7 Mar 2024 10:50:04 +0100 Subject: [PATCH 1/2] [BUG] prevent removing session cookie when redirect_uri query contains :// --- tests/integration/oauth_test.go | 58 +++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/tests/integration/oauth_test.go b/tests/integration/oauth_test.go index fed73696e..1da1c6f9c 100644 --- a/tests/integration/oauth_test.go +++ b/tests/integration/oauth_test.go @@ -470,6 +470,64 @@ func TestSignInOAuthCallbackSignIn(t *testing.T) { assert.Greater(t, userAfterLogin.LastLoginUnix, userGitLab.LastLoginUnix) } +func TestSignInOAuthCallbackRedirectToEscaping(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + // + // OAuth2 authentication source GitLab + // + gitlabName := "gitlab" + gitlab := addAuthSource(t, authSourcePayloadGitLabCustom(gitlabName)) + + // + // Create a user as if it had been previously been created by the GitLab + // authentication source. + // + userGitLabUserID := "5678" + userGitLab := &user_model.User{ + Name: "gitlabuser", + Email: "gitlabuser@example.com", + Passwd: "gitlabuserpassword", + Type: user_model.UserTypeIndividual, + LoginType: auth_model.OAuth2, + LoginSource: gitlab.ID, + LoginName: userGitLabUserID, + } + defer createUser(context.Background(), t, userGitLab)() + + // + // A request for user information sent to Goth will return a + // goth.User exactly matching the user created above. + // + defer mockCompleteUserAuth(func(res http.ResponseWriter, req *http.Request) (goth.User, error) { + return goth.User{ + Provider: gitlabName, + UserID: userGitLabUserID, + Email: userGitLab.Email, + }, nil + })() + req := NewRequest(t, "GET", fmt.Sprintf("/user/oauth2/%s/callback?code=XYZ&state=XYZ", gitlabName)) + req.AddCookie(&http.Cookie{ + Name: "redirect_to", + Value: "/login/oauth/authorize?redirect_uri=https%3A%2F%2Ftranslate.example.org", + Path: "/", + }) + resp := MakeRequest(t, req, http.StatusSeeOther) + + hasNewSessionCookie := false + sessionCookieName := setting.SessionConfig.CookieName + for _, c := range resp.Result().Cookies() { + if c.Name == sessionCookieName { + hasNewSessionCookie = true + break + } + t.Log("Got cookie", c.Name) + } + + assert.True(t, hasNewSessionCookie, "Session cookie %q is missing", sessionCookieName) + assert.Equal(t, "/login/oauth/authorize?redirect_uri=https://translate.example.org", test.RedirectURL(resp)) +} + func TestSignUpViaOAuthWithMissingFields(t *testing.T) { defer tests.PrepareTestEnv(t)() // enable auto-creation of accounts via OAuth2 From 7444f9981e3df243865f66572eac8a25ffb8c2f1 Mon Sep 17 00:00:00 2001 From: oliverpool Date: Thu, 7 Mar 2024 10:53:43 +0100 Subject: [PATCH 2/2] implement fix --- services/context/base.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/context/base.go b/services/context/base.go index c4aa467ff..25ff93505 100644 --- a/services/context/base.go +++ b/services/context/base.go @@ -256,7 +256,7 @@ func (b *Base) Redirect(location string, status ...int) { code = status[0] } - if strings.Contains(location, "://") || strings.HasPrefix(location, "//") { + if httplib.IsRiskyRedirectURL(location) { // Some browsers (Safari) have buggy behavior for Cookie + Cache + External Redirection, eg: /my-path => https://other/path // 1. the first request to "/my-path" contains cookie // 2. some time later, the request to "/my-path" doesn't contain cookie (caused by Prevent web tracking)