package sessions import ( "context" "net/http" "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/web/cookie" "golang.org/x/oauth2" ) type Controller struct { cfg *oidc.OpenID http *http.Client } func New(cfg *oidc.OpenID, http *http.Client) *Controller { return &Controller{ cfg: cfg, http: http, } } func (c *Controller) MountTo(mux *http.ServeMux) { mux.HandleFunc("GET /session/new", c.New) mux.HandleFunc("GET /session/callback", c.Create) } 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")) http.Redirect(w, r, url, http.StatusFound) } func (c *Controller) Create(w http.ResponseWriter, r *http.Request) { ctx := context.WithValue(r.Context(), oauth2.HTTPClient, c.http) token, err := c.cfg.Config.Exchange(ctx, r.URL.Query().Get("code")) if err != nil { log.WithFields(ctx, log.Fields{"error": err}) w.WriteHeader(http.StatusBadRequest) return } tokens := &oidc.Tokens{Token: token} if rawIDToken, ok := token.Extra("id_token").(string); ok { tokens.IDToken = rawIDToken } encoded, err := tokens.ToBase64String() if err != nil { w.WriteHeader(http.StatusBadRequest) return } http.SetCookie(w, cookie.New("session", encoded, tokens.Expiry)) http.Redirect(w, r, "/dashboard", http.StatusFound) }