Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-pages.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Shushlin <v.shushlin@gmail.com>2022-03-21 12:11:47 +0300
committerVladimir Shushlin <v.shushlin@gmail.com>2022-03-28 14:33:26 +0300
commit8c7fe1f00874ea94161570c040136c1b1a53d3a2 (patch)
treea0582cec8c229907e6d8aefae062079f2239be4e
parente3cb2d50a9af5594c5acb24adabd0f825d0ac75b (diff)
fix: validate that session was issued on the same host
Currently, sessions are valid across all domains. And our auth tokens are also valid for all pages projects user has access to. This means that cookie from one website can be reused on the another. Attackers can steal cookies in many different ways. The easiest way would be to setup a validated custom domain, then proxy all requests to pages server, but log the cookies. Once you have a cookie for attackers domain, you can reuse it on any other pages domain the target user has access to. This commit saves current domain in the session and validates it when reading the session. Changelog: security
-rw-r--r--internal/auth/auth.go51
-rw-r--r--internal/auth/auth_test.go158
-rw-r--r--internal/auth/session.go61
-rw-r--r--test/acceptance/auth_test.go66
4 files changed, 191 insertions, 145 deletions
diff --git a/internal/auth/auth.go b/internal/auth/auth.go
index acef051b..6ac7eee2 100644
--- a/internal/auth/auth.go
+++ b/internal/auth/auth.go
@@ -85,41 +85,6 @@ type domain interface {
ServeNotFoundAuthFailed(w http.ResponseWriter, r *http.Request)
}
-func (a *Auth) getSessionFromStore(r *http.Request) (*sessions.Session, error) {
- session, err := a.store.Get(r, "gitlab-pages")
-
- if session != nil {
- // Cookie just for this domain
- session.Options.Path = "/"
- session.Options.HttpOnly = true
- session.Options.Secure = request.IsHTTPS(r)
- session.Options.MaxAge = authSessionMaxAge
- }
-
- return session, err
-}
-
-func (a *Auth) checkSession(w http.ResponseWriter, r *http.Request) (*sessions.Session, error) {
- // Create or get session
- session, errsession := a.getSessionFromStore(r)
-
- if errsession != nil {
- // Save cookie again
- errsave := session.Save(r, w)
- if errsave != nil {
- logRequest(r).WithError(errsave).Error(saveSessionErrMsg)
- captureErrWithReqAndStackTrace(errsave, r)
- httperrors.Serve500(w)
- return nil, errsave
- }
-
- http.Redirect(w, r, getRequestAddress(r), http.StatusFound)
- return nil, errsession
- }
-
- return session, nil
-}
-
// TryAuthenticate tries to authenticate user and fetch access token if request is a callback to /auth?
func (a *Auth) TryAuthenticate(w http.ResponseWriter, r *http.Request, domains source.Source) bool {
if a == nil {
@@ -159,7 +124,7 @@ func (a *Auth) TryAuthenticate(w http.ResponseWriter, r *http.Request, domains s
return false
}
-func (a *Auth) checkAuthenticationResponse(session *sessions.Session, w http.ResponseWriter, r *http.Request) {
+func (a *Auth) checkAuthenticationResponse(session *hostSession, w http.ResponseWriter, r *http.Request) {
if !validateState(r, session) {
// State is NOT ok
logRequest(r).Warn("Authentication state did not match expected")
@@ -233,7 +198,7 @@ func (a *Auth) domainAllowed(ctx context.Context, name string, domains source.So
return (domain != nil && err == nil)
}
-func (a *Auth) handleProxyingAuth(session *sessions.Session, w http.ResponseWriter, r *http.Request, domains source.Source) bool {
+func (a *Auth) handleProxyingAuth(session *hostSession, w http.ResponseWriter, r *http.Request, domains source.Source) bool {
// handle auth callback e.g. https://gitlab.io/auth?domain=domain&state=state
if shouldProxyAuthToGitlab(r) {
domain := r.URL.Query().Get("domain")
@@ -354,11 +319,11 @@ func shouldProxyAuthToGitlab(r *http.Request) bool {
return r.URL.Query().Get("domain") != "" && r.URL.Query().Get("state") != ""
}
-func shouldProxyCallbackToCustomDomain(session *sessions.Session) bool {
+func shouldProxyCallbackToCustomDomain(session *hostSession) bool {
return session.Values["proxy_auth_domain"] != nil
}
-func validateState(r *http.Request, session *sessions.Session) bool {
+func validateState(r *http.Request, session *hostSession) bool {
state := r.URL.Query().Get("state")
if state == "" {
// No state param
@@ -424,7 +389,7 @@ func (a *Auth) fetchAccessToken(ctx context.Context, code string) (tokenResponse
return token, nil
}
-func (a *Auth) checkSessionIsValid(w http.ResponseWriter, r *http.Request) *sessions.Session {
+func (a *Auth) checkSessionIsValid(w http.ResponseWriter, r *http.Request) *hostSession {
session, err := a.checkSession(w, r)
if err != nil {
return nil
@@ -438,7 +403,7 @@ func (a *Auth) checkSessionIsValid(w http.ResponseWriter, r *http.Request) *sess
return session
}
-func (a *Auth) checkTokenExists(session *sessions.Session, w http.ResponseWriter, r *http.Request) bool {
+func (a *Auth) checkTokenExists(session *hostSession, w http.ResponseWriter, r *http.Request) bool {
// If no access token redirect to OAuth login page
if session.Values["access_token"] == nil {
logRequest(r).Debug("No access token exists, redirecting user to OAuth2 login")
@@ -473,7 +438,7 @@ func (a *Auth) getProxyAddress(r *http.Request, state string) string {
return fmt.Sprintf(authorizeProxyTemplate, a.redirectURI, getRequestDomain(r), state)
}
-func destroySession(session *sessions.Session, w http.ResponseWriter, r *http.Request) {
+func destroySession(session *hostSession, w http.ResponseWriter, r *http.Request) {
logRequest(r).Debug("Destroying session")
// Invalidate access token and redirect back for refreshing and re-authenticating
@@ -617,7 +582,7 @@ func (a *Auth) CheckResponseForInvalidToken(w http.ResponseWriter, r *http.Reque
return false
}
-func checkResponseForInvalidToken(resp *http.Response, session *sessions.Session, w http.ResponseWriter, r *http.Request) bool {
+func checkResponseForInvalidToken(resp *http.Response, session *hostSession, w http.ResponseWriter, r *http.Request) bool {
if resp.StatusCode == http.StatusUnauthorized {
errResp := errorResponse{}
diff --git a/internal/auth/auth_test.go b/internal/auth/auth_test.go
index d55c5a46..4a2f23fc 100644
--- a/internal/auth/auth_test.go
+++ b/internal/auth/auth_test.go
@@ -8,11 +8,9 @@ import (
"net/http"
"net/http/httptest"
"net/url"
- "strings"
"testing"
"github.com/golang/mock/gomock"
- "github.com/gorilla/sessions"
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitlab-pages/internal/mocks"
@@ -55,17 +53,18 @@ func (dm *domainMock) ServeNotFoundAuthFailed(w http.ResponseWriter, r *http.Req
// Which leads to negative side effects: we can't test encryption, and cookie params
// like max-age and secure are not being properly set
// To avoid that we use fake request, and set only session cookie without copying context
-func setSessionValues(t *testing.T, r *http.Request, store sessions.Store, values map[interface{}]interface{}) {
+func setSessionValues(t *testing.T, r *http.Request, auth *Auth, values map[interface{}]interface{}) {
t.Helper()
- tmpRequest, err := http.NewRequest("GET", "/", nil)
+ tmpRequest, err := http.NewRequest("GET", "http://"+r.Host, nil)
require.NoError(t, err)
result := httptest.NewRecorder()
- session, _ := store.Get(tmpRequest, "gitlab-pages")
+ session, _ := auth.getSessionFromStore(tmpRequest)
session.Values = values
- session.Save(tmpRequest, result)
+ err = session.Save(tmpRequest, result)
+ require.NoError(t, err)
res := result.Result()
defer res.Body.Close()
@@ -111,16 +110,13 @@ func TestTryAuthenticateWithCodeButInvalidState(t *testing.T) {
auth := createTestAuth(t, "", "")
result := httptest.NewRecorder()
- reqURL, err := url.Parse("/auth?code=1&state=invalid")
- require.NoError(t, err)
- reqURL.Scheme = request.SchemeHTTPS
- r := &http.Request{URL: reqURL}
- session, err := auth.store.Get(r, "gitlab-pages")
+ r, err := http.NewRequest("Get", "https://example.com/auth?code=1&state=invalid", nil)
require.NoError(t, err)
- session.Values["state"] = "state"
- session.Save(r, result)
+ setSessionValues(t, r, auth, map[interface{}]interface{}{
+ "state": "state",
+ })
mockCtrl := gomock.NewController(t)
@@ -133,19 +129,15 @@ func TestTryAuthenticateRemoveTokenFromRedirect(t *testing.T) {
auth := createTestAuth(t, "", "")
result := httptest.NewRecorder()
- reqURL, err := url.Parse("/auth?code=1&state=state&token=secret")
- require.NoError(t, err)
- require.Equal(t, reqURL.Query().Get("token"), "secret", "token is present before redirecting")
- reqURL.Scheme = request.SchemeHTTPS
- r := &http.Request{URL: reqURL}
-
- session, err := auth.store.Get(r, "gitlab-pages")
+ r, err := http.NewRequest("Get", "https://example.com/auth?code=1&state=state&token=secret", nil)
+ require.Equal(t, r.URL.Query().Get("token"), "secret", "token is present before redirecting")
require.NoError(t, err)
- session.Values["state"] = "state"
- session.Values["proxy_auth_domain"] = "https://domain.com"
- session.Save(r, result)
+ setSessionValues(t, r, auth, map[interface{}]interface{}{
+ "state": "state",
+ "proxy_auth_domain": "https://domain.com",
+ })
mockCtrl := gomock.NewController(t)
@@ -201,15 +193,15 @@ func testTryAuthenticateWithCodeAndState(t *testing.T, https bool) {
auth := createTestAuth(t, apiServer.URL, "")
- domain := apiServer.URL
+ host := "http://example.com"
if https {
- domain = strings.Replace(apiServer.URL, "http://", "https://", -1)
+ host = "https://example.com"
}
- code, err := auth.EncryptAndSignCode(domain, "1")
+ code, err := auth.EncryptAndSignCode(host, "1")
require.NoError(t, err)
- r, err := http.NewRequest("GET", "/auth?code="+code+"&state=state", nil)
+ r, err := http.NewRequest("GET", host+"/auth?code="+code+"&state=state", nil)
require.NoError(t, err)
if https {
r.URL.Scheme = request.SchemeHTTPS
@@ -217,9 +209,7 @@ func testTryAuthenticateWithCodeAndState(t *testing.T, https bool) {
r.URL.Scheme = request.SchemeHTTP
}
- r.Host = strings.TrimPrefix(apiServer.URL, "http://")
-
- setSessionValues(t, r, auth.store, map[interface{}]interface{}{
+ setSessionValues(t, r, auth, map[interface{}]interface{}{
"uri": "https://pages.gitlab-example.com/project/",
"state": "state",
})
@@ -267,16 +257,10 @@ func TestCheckAuthenticationWhenAccess(t *testing.T) {
auth := createTestAuth(t, apiServer.URL, "")
result := httptest.NewRecorder()
- reqURL, err := url.Parse("/auth?code=1&state=state")
- require.NoError(t, err)
- reqURL.Scheme = request.SchemeHTTPS
- r := &http.Request{URL: reqURL}
-
- session, err := auth.store.Get(r, "gitlab-pages")
+ r, err := http.NewRequest("Get", "https://example.com/", nil)
require.NoError(t, err)
- session.Values["access_token"] = "abc"
- session.Save(r, result)
+ setSessionValues(t, r, auth, map[interface{}]interface{}{"access_token": "abc"})
contentServed := auth.CheckAuthentication(result, r, &domainMock{projectID: 1000})
require.False(t, contentServed)
@@ -304,16 +288,12 @@ func TestCheckAuthenticationWhenNoAccess(t *testing.T) {
w := httptest.NewRecorder()
- reqURL, err := url.Parse("/auth?code=1&state=state")
- require.NoError(t, err)
- reqURL.Scheme = request.SchemeHTTPS
- r := &http.Request{URL: reqURL}
-
- session, err := auth.store.Get(r, "gitlab-pages")
+ r, err := http.NewRequest("Get", "https://example.com/auth?code=1&state=state", nil)
require.NoError(t, err)
- session.Values["access_token"] = "abc"
- session.Save(r, w)
+ setSessionValues(t, r, auth, map[interface{}]interface{}{
+ "access_token": "abc",
+ })
contentServed := auth.CheckAuthentication(w, r, &domainMock{projectID: 1000, notFoundContent: "Generic 404"})
require.True(t, contentServed)
@@ -327,6 +307,43 @@ func TestCheckAuthenticationWhenNoAccess(t *testing.T) {
require.Equal(t, string(body), "Generic 404")
}
+func TestCheckAuthenticationWithSessionFromDifferentHost(t *testing.T) {
+ apiServer := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ switch r.URL.Path {
+ case "/api/v4/projects/1000/pages_access":
+ require.Equal(t, "Bearer abc", r.Header.Get("Authorization"))
+ w.WriteHeader(http.StatusOK)
+ default:
+ t.Logf("Unexpected r.URL.RawPath: %q", r.URL.Path)
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ w.WriteHeader(http.StatusNotFound)
+ }
+ }))
+
+ apiServer.Start()
+ defer apiServer.Close()
+
+ auth := createTestAuth(t, apiServer.URL, "")
+
+ result := httptest.NewRecorder()
+ r, err := http.NewRequest("Get", "https://different.com/", nil)
+ require.NoError(t, err)
+ setSessionValues(t, r, auth, map[interface{}]interface{}{"access_token": "abc"})
+
+ r, err = http.NewRequest("Get", "https://example.com/", nil)
+ require.NoError(t, err)
+ contentServed := auth.CheckAuthentication(result, r, &domainMock{projectID: 1000})
+ require.True(t, contentServed)
+
+ // should redirect to auth
+ require.Equal(t, http.StatusFound, result.Code)
+ redirectURL, err := url.Parse(result.Header().Get("Location"))
+ require.NoError(t, err)
+ require.Equal(t, "pages.gitlab-example.com", redirectURL.Host)
+ require.Equal(t, "/auth", redirectURL.Path)
+ require.Equal(t, "https://example.com", redirectURL.Query().Get("domain"))
+}
+
func TestCheckAuthenticationWhenInvalidToken(t *testing.T) {
apiServer := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
@@ -347,16 +364,13 @@ func TestCheckAuthenticationWhenInvalidToken(t *testing.T) {
auth := createTestAuth(t, apiServer.URL, "")
result := httptest.NewRecorder()
- reqURL, err := url.Parse("/auth?code=1&state=state")
- require.NoError(t, err)
- r := &http.Request{URL: reqURL}
- session, err := auth.store.Get(r, "gitlab-pages")
+ r, err := http.NewRequest("Get", "https://example.com", nil)
require.NoError(t, err)
- session.Values["access_token"] = "abc"
- err = session.Save(r, result)
- require.NoError(t, err)
+ setSessionValues(t, r, auth, map[interface{}]interface{}{
+ "access_token": "abc",
+ })
contentServed := auth.CheckAuthentication(result, r, &domainMock{projectID: 1000})
require.True(t, contentServed)
@@ -382,16 +396,13 @@ func TestCheckAuthenticationWithoutProject(t *testing.T) {
auth := createTestAuth(t, apiServer.URL, "")
result := httptest.NewRecorder()
- reqURL, err := url.Parse("/auth?code=1&state=state")
- require.NoError(t, err)
- reqURL.Scheme = request.SchemeHTTPS
- r := &http.Request{URL: reqURL}
- session, err := auth.store.Get(r, "gitlab-pages")
+ r, err := http.NewRequest("Get", "https://example.com/auth?code=1&state=state", nil)
require.NoError(t, err)
- session.Values["access_token"] = "abc"
- session.Save(r, result)
+ setSessionValues(t, r, auth, map[interface{}]interface{}{
+ "access_token": "abc",
+ })
contentServed := auth.CheckAuthenticationWithoutProject(result, r, &domainMock{projectID: 0})
require.False(t, contentServed)
@@ -418,15 +429,13 @@ func TestCheckAuthenticationWithoutProjectWhenInvalidToken(t *testing.T) {
auth := createTestAuth(t, apiServer.URL, "")
result := httptest.NewRecorder()
- reqURL, err := url.Parse("/auth?code=1&state=state")
- require.NoError(t, err)
- r := &http.Request{URL: reqURL}
- session, err := auth.store.Get(r, "gitlab-pages")
+ r, err := http.NewRequest("Get", "https://example.com/", nil)
require.NoError(t, err)
- session.Values["access_token"] = "abc"
- session.Save(r, result)
+ setSessionValues(t, r, auth, map[interface{}]interface{}{
+ "access_token": "abc",
+ })
contentServed := auth.CheckAuthenticationWithoutProject(result, r, &domainMock{projectID: 0})
require.True(t, contentServed)
@@ -451,15 +460,13 @@ func TestGetTokenIfExistsWhenTokenExists(t *testing.T) {
auth := createTestAuth(t, "", "")
result := httptest.NewRecorder()
- reqURL, err := url.Parse("/")
- require.NoError(t, err)
- r := &http.Request{URL: reqURL}
- session, err := auth.store.Get(r, "gitlab-pages")
+ r, err := http.NewRequest("Get", "https://example.com", nil)
require.NoError(t, err)
- session.Values["access_token"] = "abc"
- session.Save(r, result)
+ setSessionValues(t, r, auth, map[interface{}]interface{}{
+ "access_token": "abc",
+ })
token, err := auth.GetTokenIfExists(result, r)
require.NoError(t, err)
@@ -470,14 +477,11 @@ func TestGetTokenIfExistsWhenTokenDoesNotExist(t *testing.T) {
auth := createTestAuth(t, "", "")
result := httptest.NewRecorder()
- reqURL, err := url.Parse("http://pages.gitlab-example.com/test")
- require.NoError(t, err)
- r := &http.Request{URL: reqURL, Host: "pages.gitlab-example.com", RequestURI: "/test"}
- session, err := auth.store.Get(r, "gitlab-pages")
+ r, err := http.NewRequest("Get", "https://example.com", nil)
require.NoError(t, err)
- session.Save(r, result)
+ setSessionValues(t, r, auth, map[interface{}]interface{}{})
token, err := auth.GetTokenIfExists(result, r)
require.Equal(t, "", token)
diff --git a/internal/auth/session.go b/internal/auth/session.go
new file mode 100644
index 00000000..40ab6467
--- /dev/null
+++ b/internal/auth/session.go
@@ -0,0 +1,61 @@
+package auth
+
+import (
+ "net/http"
+
+ "github.com/gorilla/sessions"
+
+ "gitlab.com/gitlab-org/gitlab-pages/internal/httperrors"
+ "gitlab.com/gitlab-org/gitlab-pages/internal/request"
+)
+
+type hostSession struct {
+ *sessions.Session
+}
+
+const sessionHostKey = "_session_host"
+
+func (s *hostSession) Save(r *http.Request, w http.ResponseWriter) error {
+ s.Session.Values[sessionHostKey] = r.Host
+
+ return s.Session.Save(r, w)
+}
+
+func (a *Auth) getSessionFromStore(r *http.Request) (*hostSession, error) {
+ session, err := a.store.Get(r, "gitlab-pages")
+
+ if session != nil {
+ // Cookie just for this domain
+ session.Options.Path = "/"
+ session.Options.HttpOnly = true
+ session.Options.Secure = request.IsHTTPS(r)
+ session.Options.MaxAge = authSessionMaxAge
+
+ if session.Values[sessionHostKey] == nil || session.Values[sessionHostKey] != r.Host {
+ session.Values = make(map[interface{}]interface{})
+ }
+ }
+
+ return &hostSession{session}, err
+}
+
+func (a *Auth) checkSession(w http.ResponseWriter, r *http.Request) (*hostSession, error) {
+ // Create or get session
+ session, errsession := a.getSessionFromStore(r)
+
+ if errsession != nil {
+ // Save cookie again
+ errsave := session.Save(r, w)
+ if errsave != nil {
+ logRequest(r).WithError(errsave).Error(saveSessionErrMsg)
+ captureErrWithReqAndStackTrace(errsave, r)
+ httperrors.Serve500(w)
+ return nil, errsave
+ }
+
+ http.Redirect(w, r, getRequestAddress(r), http.StatusFound)
+ return nil, errsession
+ }
+
+ return session, nil
+}
diff --git a/test/acceptance/auth_test.go b/test/acceptance/auth_test.go
index d115dba5..18795fee 100644
--- a/test/acceptance/auth_test.go
+++ b/test/acceptance/auth_test.go
@@ -119,7 +119,7 @@ func TestWhenLoginCallbackWithUnencryptedCode(t *testing.T) {
}
// Go to auth page with correct state will cause fetching the token
- authrsp, err := GetPageFromListenerWithHeaders(t, httpsListener, "projects.gitlab-example.com", "/auth?code=1&state="+
+ authrsp, err := GetPageFromListenerWithHeaders(t, httpsListener, "group.auth.gitlab-example.com", "/auth?code=1&state="+
url.Query().Get("state"), header)
require.NoError(t, err)
@@ -152,60 +152,76 @@ func TestAccessControlUnderCustomDomain(t *testing.T) {
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
+ // visit to custom domain
rsp, err := GetRedirectPage(t, httpListener, tt.domain, tt.path)
require.NoError(t, err)
defer rsp.Body.Close()
- cookie := rsp.Header.Get("Set-Cookie")
+ domainCookie := rsp.Header.Get("Set-Cookie")
- url, err := url.Parse(rsp.Header.Get("Location"))
+ projectProxyURL, err := url.Parse(rsp.Header.Get("Location"))
require.NoError(t, err)
- state := url.Query().Get("state")
- require.Equal(t, "http://"+tt.domain, url.Query().Get("domain"))
+ state := projectProxyURL.Query().Get("state")
+ require.Equal(t, "http://"+tt.domain, projectProxyURL.Query().Get("domain"))
- pagesrsp, err := GetRedirectPage(t, httpListener, url.Host, url.Path+"?"+url.RawQuery)
+ // visit projects.gitlab-example.com?state=something
+ projectsProxyRsp, err := GetRedirectPage(t, httpListener,
+ projectProxyURL.Host, projectProxyURL.Path+"?"+projectProxyURL.RawQuery)
require.NoError(t, err)
- defer pagesrsp.Body.Close()
+ defer projectsProxyRsp.Body.Close()
- pagescookie := pagesrsp.Header.Get("Set-Cookie")
+ projectsCookie := projectsProxyRsp.Header.Get("Set-Cookie")
- // Go to auth page with correct state will cause fetching the token
- authrsp, err := GetRedirectPageWithCookie(t, httpListener, tt.domain, "/auth?code=1&state="+
- state, pagescookie)
+ // visit projects.gitlab-example.com?state=something&code=1
+ authRsp, err := GetRedirectPageWithCookie(t, httpListener, projectProxyURL.Host, "/auth?code=1&state="+
+ state, projectsCookie)
require.NoError(t, err)
- defer authrsp.Body.Close()
+ defer authRsp.Body.Close()
- url, err = url.Parse(authrsp.Header.Get("Location"))
+ backDomainURL, err := projectProxyURL.Parse(authRsp.Header.Get("Location"))
require.NoError(t, err)
// Will redirect to custom domain
- require.Equal(t, tt.domain, url.Host)
- code := url.Query().Get("code")
+ require.Equal(t, tt.domain, backDomainURL.Host)
+ code := backDomainURL.Query().Get("code")
require.NotEqual(t, "1", code)
- authrsp, err = GetRedirectPageWithCookie(t, httpListener, tt.domain, "/auth?code="+code+"&state="+
- state, cookie)
+ // visit domain.com/auth?code&state will set the cookie and redirect back to original page
+ selfRedirectRsp, err := GetRedirectPageWithCookie(t, httpListener, tt.domain, "/auth?code="+code+"&state="+
+ state, domainCookie)
require.NoError(t, err)
- defer authrsp.Body.Close()
+ defer selfRedirectRsp.Body.Close()
// Will redirect to the page
- cookie = authrsp.Header.Get("Set-Cookie")
- require.Equal(t, http.StatusFound, authrsp.StatusCode)
+ domainCookie = selfRedirectRsp.Header.Get("Set-Cookie")
+ require.Equal(t, http.StatusFound, selfRedirectRsp.StatusCode)
- url, err = url.Parse(authrsp.Header.Get("Location"))
+ selfRedirectURL, err := projectProxyURL.Parse(selfRedirectRsp.Header.Get("Location"))
require.NoError(t, err)
// Will redirect to custom domain
- require.Equal(t, "http://"+tt.domain+"/"+tt.path, url.String())
+ require.Equal(t, "http://"+tt.domain+"/"+tt.path, selfRedirectURL.String())
// Fetch page in custom domain
- authrsp, err = GetRedirectPageWithCookie(t, httpListener, tt.domain, tt.path, cookie)
+ authRsp, err = GetRedirectPageWithCookie(t, httpListener, tt.domain, tt.path, domainCookie)
require.NoError(t, err)
- defer authrsp.Body.Close()
- require.Equal(t, http.StatusOK, authrsp.StatusCode)
+ defer authRsp.Body.Close()
+ require.Equal(t, http.StatusOK, authRsp.StatusCode)
+
+ // Try to fetch page from another domain
+ // it should restart the auth process ignoring already existing cookie
+ secondAuthRsp, err := GetRedirectPageWithCookie(t, httpListener, "group.auth.gitlab-example.com", "/private.project/", domainCookie)
+ require.NoError(t, err)
+ defer authRsp.Body.Close()
+
+ secondAuthURL, err := url.Parse(secondAuthRsp.Header.Get("Location"))
+ require.NoError(t, err)
+ require.Equal(t, "projects.gitlab-example.com", secondAuthURL.Host)
+ require.Equal(t, "/auth", secondAuthURL.Path)
+ require.Equal(t, "http://group.auth.gitlab-example.com", secondAuthURL.Query().Get("domain"))
})
}
}