sonr/internal/ctx/session.go

91 lines
2.1 KiB
Go

package ctx
import (
"context"
"errors"
"net/http"
"time"
"github.com/gorilla/sessions"
"github.com/labstack/echo/v4"
"github.com/segmentio/ksuid"
)
var store sessions.Store
type ctxKeySessionID struct{}
// SessionMiddleware establishes a Session Cookie.
func SessionMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
store = sessions.NewCookieStore([]byte("SESSION_KEY"))
return func(c echo.Context) error {
ctx := c.Request().Context()
// Attempt to read the session ID from the "session" cookie
sessionID, err := readSessionIDFromCookie(c)
if err != nil {
// Generate a new KSUID if the session cookie is missing or invalid
sessionID = ksuid.New().String()
// Write the new session ID to the "session" cookie
err = writeSessionIDToCookie(c, sessionID)
if err != nil {
return c.JSON(
http.StatusInternalServerError,
map[string]string{"error": "Failed to set session cookie"},
)
}
}
// Inject the session ID into the context
ctx = context.WithValue(ctx, ctxKeySessionID{}, sessionID)
// Update the request with the new context
c.SetRequest(c.Request().WithContext(ctx))
return next(c)
}
}
func defaultSession(id string, s *sessions.Session) *session {
return &session{
session: s,
id: id,
origin: "",
address: "",
chainID: "",
}
}
func getSessionID(ctx context.Context) (string, error) {
sessionID, ok := ctx.Value(ctxKeySessionID{}).(string)
if !ok || sessionID == "" {
return "", errors.New("session ID not found in context")
}
return sessionID, nil
}
func readSessionIDFromCookie(c echo.Context) (string, error) {
cookie, err := c.Cookie("session")
if err != nil {
// Cookie not found or other error
return "", err
}
if cookie == nil || cookie.Value == "" {
// Cookie is empty
return "", http.ErrNoCookie
}
return cookie.Value, nil
}
func writeSessionIDToCookie(c echo.Context, sessionID string) error {
cookie := &http.Cookie{
Name: "session",
Value: sessionID,
Expires: time.Now().Add(24 * time.Hour),
HttpOnly: true,
Path: "/",
// Add Secure and SameSite attributes as needed
}
c.SetCookie(cookie)
return nil
}