From 2122cfe75bb89f0c0713859009ba81d784924d99 Mon Sep 17 00:00:00 2001 From: mo khan Date: Sun, 11 May 2025 15:42:52 -0600 Subject: feat: add endpoint to reflect JWT body --- app/controllers/sessions/controller.go | 20 ++++++++++++++++++++ app/controllers/sessions/controller_test.go | 27 +++++++++++++++++++++++++++ app/controllers/sessions/service.go | 11 +++++++++++ 3 files changed, 58 insertions(+) (limited to 'app/controllers') diff --git a/app/controllers/sessions/controller.go b/app/controllers/sessions/controller.go index e8409a3..bf7d813 100644 --- a/app/controllers/sessions/controller.go +++ b/app/controllers/sessions/controller.go @@ -24,6 +24,7 @@ func New(cfg *oidc.OpenID, http *http.Client) *Controller { func (c *Controller) MountTo(mux *http.ServeMux) { mux.HandleFunc("GET /session/new", c.New) + mux.HandleFunc("GET /session", c.Show) mux.HandleFunc("GET /session/callback", c.Create) mux.HandleFunc("POST /session/destroy", c.Destroy) } @@ -39,6 +40,25 @@ func (c *Controller) New(w http.ResponseWriter, r *http.Request) { c.redirectTo(w, r, url) } +func (c *Controller) Show(w http.ResponseWriter, r *http.Request) { + cookie, err := r.Cookie(cfg.IDTokenCookie) + if err != nil { + pls.LogError(r.Context(), err) + w.WriteHeader(http.StatusNotFound) + return + } + + token, err := c.svc.JWTBody(r.Context(), oidc.RawToken(cookie.Value)) + if err != nil { + pls.LogError(r.Context(), err) + w.WriteHeader(http.StatusNotFound) + return + } + + w.WriteHeader(http.StatusOK) + w.Write(token) +} + /* This is the callback endpoint from the OIDC Provider: diff --git a/app/controllers/sessions/controller_test.go b/app/controllers/sessions/controller_test.go index 6dcb3f3..9b701d6 100644 --- a/app/controllers/sessions/controller_test.go +++ b/app/controllers/sessions/controller_test.go @@ -3,6 +3,7 @@ package sessions import ( "encoding/base64" "encoding/json" + "fmt" "net/http" "net/url" "testing" @@ -10,6 +11,7 @@ import ( "github.com/oauth2-proxy/mockoidc" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/xlgmokha/x/pkg/serde" "github.com/xlgmokha/x/pkg/test" "github.com/xlgmokha/x/pkg/x" xcfg "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/cfg" @@ -190,6 +192,31 @@ func TestSessions(t *testing.T) { }) }) + t.Run("GET /session", func(t *testing.T) { + t.Run("with an id_token cookie", func(t *testing.T) { + user := mockoidc.DefaultUser() + _, rawIDToken := srv.CreateTokensFor(user) + cookie := &http.Cookie{Name: xcfg.IDTokenCookie, Value: rawIDToken} + r, w := test.RequestResponse("GET", "/session", test.WithCookie(cookie)) + + mux.ServeHTTP(w, r) + + require.Equal(t, http.StatusOK, w.Code) + items, err := serde.FromJSON[map[string]interface{}](w.Body) + require.NoError(t, err) + fmt.Printf("%v\n", items) + assert.Equal(t, srv.Issuer(), items["iss"]) + }) + + t.Run("without an id_token cookie", func(t *testing.T) { + r, w := test.RequestResponse("GET", "/session") + + mux.ServeHTTP(w, r) + + require.Equal(t, http.StatusNotFound, w.Code) + }) + }) + t.Run("POST /session/destroy", func(t *testing.T) { t.Run("clears the session cookie", func(t *testing.T) { cookie := web.NewCookie(xcfg.SessionCookie, "value") diff --git a/app/controllers/sessions/service.go b/app/controllers/sessions/service.go index 9e74bfb..79ffad6 100644 --- a/app/controllers/sessions/service.go +++ b/app/controllers/sessions/service.go @@ -2,9 +2,11 @@ package sessions import ( "context" + "encoding/base64" "errors" "net/http" "net/url" + "strings" "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/cfg" "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/oidc" @@ -60,6 +62,15 @@ func (svc *Service) Exchange(r *http.Request) (*oidc.Tokens, error) { return tokens, nil } +func (svc *Service) JWTBody(ctx context.Context, raw oidc.RawToken) ([]byte, error) { + sections := strings.SplitN(raw.String(), ".", 3) + if len(sections) != 3 { + return nil, errors.New("Invalid JWT") + } + + return base64.RawURLEncoding.DecodeString(sections[1]) +} + func (svc *Service) redirectURIFor(r *http.Request) string { if len(svc.cfg.Config.RedirectURL) > 0 { return svc.cfg.Config.RedirectURL -- cgit v1.2.3