package middleware import ( "fmt" "strings" "github.com/golang-jwt/jwt/v5" echojwt "github.com/labstack/echo-jwt/v4" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" "gitlab.com/texm/shokku/internal/env" "gitlab.com/texm/shokku/internal/server/auth" ) const ( tokenContextKey = "user-token" usedCookieAuthContextKey = "cookie-auth" ) func skipDuringSetup(e *env.Env, c echo.Context) bool { reqPath := c.Request().URL.Path return !e.SetupCompleted && strings.HasPrefix(reqPath, "/api/setup") } func ProvideUserContext(e *env.Env) echo.MiddlewareFunc { logger := middlewareLogger("userContext") return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { if skipDuringSetup(e, c) { return next(c) } if err := e.Auth.SetUserContext(c, tokenContextKey); err != nil { logger.Error().Err(err).Msg("failed to set context") return echo.ErrInternalServerError } return next(c) } } } func tokenAuthSkipper(e *env.Env) middleware.Skipper { return func(c echo.Context) bool { return skipDuringSetup(e, c) } } func TokenAuth(e *env.Env) echo.MiddlewareFunc { config := echojwt.WithConfig(echojwt.Config{ NewClaimsFunc: func(c echo.Context) jwt.Claims { // &auth.User{} return jwt.MapClaims{} }, SigningKey: e.Auth.GetSigningKey(), TokenLookupFuncs: []middleware.ValuesExtractor{SplitTokenLookup}, TokenLookup: "header:Authorization", ContextKey: tokenContextKey, Skipper: tokenAuthSkipper(e), }) return config } func SplitTokenLookup(c echo.Context) ([]string, error) { dataCookie, err := c.Request().Cookie(auth.DataCookieName) if err != nil { return nil, fmt.Errorf("no data cookie: %w", err) } signatureCookie, err := c.Request().Cookie(auth.SignatureCookieName) if err != nil { return nil, fmt.Errorf("no signature cookie: %w", err) } c.Set(usedCookieAuthContextKey, true) authToken := dataCookie.Value + "." + signatureCookie.Value return []string{authToken}, nil } func CheckCookieAuthUsed(c echo.Context) bool { v, ok := c.Get(usedCookieAuthContextKey).(bool) return ok && v }