diff options
| author | mo khan <mo@mokhan.ca> | 2025-05-08 11:01:44 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-05-08 11:01:44 -0600 |
| commit | d4758497b63644b2baaef2115984fe7ba14fff2a (patch) | |
| tree | 3b14c93d7fc261ff9eb8067885342011abcf466b /app/controllers | |
| parent | b7a520b8ef410d422db653d2680a2aafe3341013 (diff) | |
feat: test out a redirect page in staging
Diffstat (limited to 'app/controllers')
| -rw-r--r-- | app/controllers/sessions/controller.go | 96 | ||||
| -rw-r--r-- | app/controllers/sessions/controller_test.go | 27 | ||||
| -rw-r--r-- | app/controllers/sessions/dto.go | 5 |
3 files changed, 48 insertions, 80 deletions
diff --git a/app/controllers/sessions/controller.go b/app/controllers/sessions/controller.go index 61fdaf8..d5b2ba6 100644 --- a/app/controllers/sessions/controller.go +++ b/app/controllers/sessions/controller.go @@ -2,12 +2,12 @@ package sessions import ( "net/http" - "time" "github.com/xlgmokha/x/pkg/cookie" - "github.com/xlgmokha/x/pkg/log" + "github.com/xlgmokha/x/pkg/env" "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/cfg" "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/middleware" + "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/views" "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/oidc" "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/pls" "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/web" @@ -36,14 +36,8 @@ func (c *Controller) New(w http.ResponseWriter, r *http.Request) { } url, nonce := c.svc.GenerateRedirectURL() - // This cookie must be sent as part of a redirect that originates from the OIDC Provider - cookie.Write(w, web.NewCookie( - cfg.CSRFCookie, - nonce, - cookie.WithSameSite(http.SameSiteLaxMode), - cookie.WithExpiration(time.Now().Add(10*time.Minute)), - )) - http.Redirect(w, r, url, http.StatusFound) + cookie.Write(w, web.NewCookie(cfg.CSRFCookie, nonce)) + c.redirectTo(w, r, url) } /* @@ -78,53 +72,6 @@ When it is decoded it has the following form: } ``` - -The `id_token` is a JWT that looks like the following body when it is decoded: - -```json - - { - "iss": "http://gdk.test:3000", - "sub": "1", - "aud": "e31e1da0b8f6b6e35ca70c790b13c0406e44aca6b2bf67f55de7355a979a224f", - "exp": 1745595639, - "iat": 1745595519, - "auth_time": 1745503338, - "sub_legacy": "2474cf0b2211688a57297ace0e260a15944754d16b1bd42c9d6779c900367807", - "name": "Administrator", - "nickname": "root", - "preferred_username": "root", - "email": "admin@example.com", - "email_verified": true, - "profile": "http://gdk.test:3000/root", - "picture": "https://www.gravatar.com/avatar/258d8dc916db8cea2cafb6c3cd0cb0246efe061421dbd83ec3a350428cabda4f?s=80&d=identicon", - "groups_direct": [ - "gitlab-org", - "toolbox", - "mass_insert_group__0_100", - "custom-roles-root-group/aa", - "custom-roles-root-group/aa/aaa", - "gnuwget", - "Commit451", - "jashkenas", - "flightjs", - "twitter", - "gitlab-examples", - "gitlab-examples/security", - "412708", - "gitlab-examples/demo-group", - "custom-roles-root-group", - "434044-group-1", - "434044-group-2", - "gitlab-org1", - "gitlab-org/secure", - "gitlab-org/secure/managers", - "gitlab-org/security-products", - "gitlab-org/security-products/analyzers" - ] - } - -``` */ func (c *Controller) Create(w http.ResponseWriter, r *http.Request) { tokens, err := c.svc.Exchange(r) @@ -141,21 +88,28 @@ func (c *Controller) Create(w http.ResponseWriter, r *http.Request) { return } - ck := web.NewCookie(cfg.SessionCookie, encoded, - cookie.WithSameSite(http.SameSiteLaxMode), - cookie.WithExpiration(tokens.Expiry), - ) - log.WithFields(r.Context(), log.Fields{"cookie": ck, "error": ck.Valid()}) - if err := web.WriteCookie(w, ck); err != nil { - pls.LogError(r.Context(), err) - w.WriteHeader(http.StatusBadRequest) - return - } - web.ExpireCookie(w, "oauth_state") - http.Redirect(w, r, "/dashboard", http.StatusFound) + web.ExpireCookie(w, cfg.CSRFCookie) + web.WriteCookie(w, web.NewCookie(cfg.SessionCookie, encoded)) + + c.redirectTo(w, r, "/dashboard") } func (c *Controller) Destroy(w http.ResponseWriter, r *http.Request) { - web.ExpireCookie(w, "session") - http.Redirect(w, r, "/", http.StatusFound) + web.ExpireCookie(w, cfg.CSRFCookie) + web.ExpireCookie(w, cfg.SessionCookie) + c.redirectTo(w, r, "/") +} + +func (c *Controller) redirectTo(w http.ResponseWriter, r *http.Request, location string) { + if env.Fetch("APP_ENV", "development") == "production" { + w.WriteHeader(http.StatusOK) + w.Header().Add("Content-Type", "text/html") + + if err := views.Render(w, "sessions/redirect", &RedirectDTO{URL: location}); err != nil { + pls.LogError(r.Context(), err) + w.WriteHeader(http.StatusInternalServerError) + } + } else { + http.Redirect(w, r, location, http.StatusFound) + } } diff --git a/app/controllers/sessions/controller_test.go b/app/controllers/sessions/controller_test.go index 82c56d5..6dcb3f3 100644 --- a/app/controllers/sessions/controller_test.go +++ b/app/controllers/sessions/controller_test.go @@ -6,7 +6,6 @@ import ( "net/http" "net/url" "testing" - "time" "github.com/oauth2-proxy/mockoidc" "github.com/stretchr/testify/assert" @@ -65,7 +64,8 @@ func TestSessions(t *testing.T) { cookie, err := http.ParseSetCookie(w.Header().Get("Set-Cookie")) require.NoError(t, err) require.NotZero(t, cookie) - assert.Equal(t, http.SameSiteLaxMode, cookie.SameSite) + + assert.Equal(t, xcfg.CSRFCookie, cookie.Name) }) }) @@ -124,10 +124,16 @@ func TestSessions(t *testing.T) { mux.ServeHTTP(w, r) - setCookieValue := w.Header().Get("Set-Cookie") - cookie, err := http.ParseSetCookie(setCookieValue) - require.NoError(t, err) - require.NotZero(t, cookie) + cookieValues := w.Header().Values("Set-Cookie") + cookies := x.Map(cookieValues, func(line string) *http.Cookie { + ck, err := http.ParseSetCookie(line) + require.NoError(t, err) + return ck + }) + + cookie := x.Find(cookies, func(item *http.Cookie) bool { + return item.Name == xcfg.SessionCookie + }) data, err := base64.URLEncoding.DecodeString(web.CookieValueFrom(cookie)) require.NoError(t, err) tokens := map[string]interface{}{} @@ -177,8 +183,6 @@ func TestSessions(t *testing.T) { t.Run("applies the appropriate cookie settings", func(t *testing.T) { assert.Equal(t, "/", cookie.Path) assert.Equal(t, xcfg.SessionCookie, cookie.Name) - assert.Equal(t, http.SameSiteLaxMode, cookie.SameSite) - assert.Equal(t, x.Must(time.Parse(time.RFC3339, tokens["expiry"].(string))).Unix(), cookie.Expires.Unix()) assert.True(t, cookie.HttpOnly) assert.True(t, cookie.Secure) assert.NotEmpty(t, cookie.Value) @@ -195,7 +199,12 @@ func TestSessions(t *testing.T) { require.Equal(t, http.StatusFound, w.Code) assert.Equal(t, "/", w.Header().Get("Location")) - assert.Equal(t, "session=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; HttpOnly; Secure", w.Header().Get("Set-Cookie")) + + expected := []string{ + "__csrf=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; HttpOnly; Secure", + "__s=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; HttpOnly; Secure", + } + assert.ElementsMatch(t, expected, w.Header().Values("Set-Cookie")) }) }) } diff --git a/app/controllers/sessions/dto.go b/app/controllers/sessions/dto.go new file mode 100644 index 0000000..4bb959f --- /dev/null +++ b/app/controllers/sessions/dto.go @@ -0,0 +1,5 @@ +package sessions + +type RedirectDTO struct { + URL string +} |
