summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-04-28 16:23:19 -0600
committermo khan <mo@mokhan.ca>2025-04-28 16:23:19 -0600
commit62fdf88cbdec6dbf248bea13611521667112f5e1 (patch)
tree2632236a73a674aa86f8efe46f3553f8d81e5328 /app
parent3b942be3d49830b80689a5c7b9f0fda4b3deb44b (diff)
feat: generate a nonce to validate the OAuth callback
Diffstat (limited to 'app')
-rw-r--r--app/controllers/sessions/controller.go7
-rw-r--r--app/controllers/sessions/controller_test.go20
2 files changed, 20 insertions, 7 deletions
diff --git a/app/controllers/sessions/controller.go b/app/controllers/sessions/controller.go
index 7e706e7..7549dc7 100644
--- a/app/controllers/sessions/controller.go
+++ b/app/controllers/sessions/controller.go
@@ -3,9 +3,11 @@ package sessions
import (
"context"
"net/http"
+ "time"
"github.com/xlgmokha/x/pkg/log"
"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/cookie"
"golang.org/x/oauth2"
)
@@ -29,8 +31,9 @@ func (c *Controller) MountTo(mux *http.ServeMux) {
}
func (c *Controller) New(w http.ResponseWriter, r *http.Request) {
- // TODO:: Generate and store nonce and use as state param to compare as a CSRF token
- url := c.cfg.Config.AuthCodeURL("todo-csrf-token", oauth2.SetAuthURLParam("audience", "todo"))
+ nonce := pls.GenerateNonce(32)
+ url := c.cfg.Config.AuthCodeURL(nonce, oauth2.SetAuthURLParam("audience", c.cfg.Config.ClientID))
+ http.SetCookie(w, cookie.New("oauth_state", nonce, time.Now().Add(10*time.Minute)))
http.Redirect(w, r, url, http.StatusFound)
}
diff --git a/app/controllers/sessions/controller_test.go b/app/controllers/sessions/controller_test.go
index e325afc..64c9fc1 100644
--- a/app/controllers/sessions/controller_test.go
+++ b/app/controllers/sessions/controller_test.go
@@ -37,11 +37,11 @@ func TestSessions(t *testing.T) {
t.Run("GET /session/new", func(t *testing.T) {
t.Run("without an authenticated session", func(t *testing.T) {
- t.Run("redirect to the OIDC Provider", func(t *testing.T) {
- r, w := test.RequestResponse("GET", "/session/new")
+ r, w := test.RequestResponse("GET", "/session/new")
- mux.ServeHTTP(w, r)
+ mux.ServeHTTP(w, r)
+ t.Run("redirect to the OIDC Provider", func(t *testing.T) {
require.Equal(t, http.StatusFound, w.Code)
require.NotEmpty(t, w.Header().Get("Location"))
redirectURL, err := url.Parse(w.Header().Get("Location"))
@@ -50,12 +50,22 @@ func TestSessions(t *testing.T) {
assert.NotEmpty(t, redirectURL.Query().Get("state"))
assert.Equal(t, srv.MockOIDC.Config().ClientID, redirectURL.Query().Get("client_id"))
assert.Equal(t, "openid profile email", redirectURL.Query().Get("scope"))
- assert.Equal(t, "todo", redirectURL.Query().Get("audience"))
+ assert.Equal(t, cfg.Config.ClientID, redirectURL.Query().Get("audience"))
assert.Equal(t, cfg.Config.RedirectURL, redirectURL.Query().Get("redirect_uri"))
assert.Equal(t, "code", redirectURL.Query().Get("response_type"))
})
- t.Run("generates a CSRF token", func(t *testing.T) {})
+ t.Run("generates a CSRF token", func(t *testing.T) {
+ cookieHeader := w.Header().Get("Set-Cookie")
+ require.NotEmpty(t, cookieHeader)
+
+ cookies, err := http.ParseCookie(cookieHeader)
+ require.NoError(t, err)
+ cookie := x.Find(cookies, func(item *http.Cookie) bool {
+ return item.Name == "oauth_state"
+ })
+ require.NotZero(t, cookie)
+ })
})
t.Run("with an active authenicated session", func(t *testing.T) {})