// backend/internal/session.go package internal import ( "net/http" "os" "time" "github.com/golang-jwt/jwt/v5" ) // Claims are the signed session fields Pegasus stores in the browser cookie. type Claims struct { Username string `json:"u"` JFToken string `json:"t"` jwt.RegisteredClaims } var sessionKey = []byte(os.Getenv("PEGASUS_SESSION_KEY")) var cookieSecure = os.Getenv("PEGASUS_COOKIE_INSECURE") != "1" var signJWT = func(tok *jwt.Token) (string, error) { return tok.SignedString(sessionKey) } // CookieName is the session cookie name used by Pegasus. const CookieName = "pegasus_session" // SetSession signs and writes a Pegasus session cookie. func SetSession(w http.ResponseWriter, username, jfToken string) error { now := time.Now() tok := jwt.NewWithClaims(jwt.SigningMethodHS256, Claims{ Username: username, JFToken: jfToken, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(now.Add(7 * 24 * time.Hour)), IssuedAt: jwt.NewNumericDate(now), }, }) signed, err := signJWT(tok) if err != nil { return err } http.SetCookie(w, &http.Cookie{ Name: CookieName, Value: signed, Path: "/", HttpOnly: true, Secure: cookieSecure, SameSite: http.SameSiteLaxMode, }) return nil } // ClearSession expires the Pegasus session cookie immediately. func ClearSession(w http.ResponseWriter) { http.SetCookie(w, &http.Cookie{ Name: CookieName, Value: "", Expires: time.Unix(0, 0), MaxAge: -1, Path: "/", HttpOnly: true, Secure: cookieSecure, SameSite: http.SameSiteLaxMode, }) }