package handler import ( "encoding/gob" "net/http" "os" "github.com/gorilla/sessions" "github.com/labstack/gommon/log" ) // Session wraps gorilla session type Session struct { *sessions.Session } // SessionStore wraps gorilla session store type SessionStore struct { store *sessions.CookieStore } // InitSessionStore creates a new session store with a secret key func (h *Handler) InitSessionStore() error { // Generate or get session secret from environment secret := []byte(h.GetSessionSecret()) // Create cookie store store := sessions.NewCookieStore(secret) // Configure session options store.Options = &sessions.Options{ Path: "/", MaxAge: 24 * 60 * 60, // 24 hours default HttpOnly: true, Secure: false, // Will be set to true per-request if HTTPS SameSite: http.SameSiteStrictMode, } h.SessionStore = &SessionStore{store: store} // Register types for session encoding gob.Register(map[string]interface{}{}) gob.Register([]interface{}{}) return nil } // Get retrieves a session func (s *SessionStore) Get(r *http.Request, name string) (*Session, error) { sess, err := s.store.Get(r, name) if err != nil { return nil, err } return &Session{Session: sess}, nil } // GetSessionSecret returns the session secret key // Uses environment variable or generates a random one func (h *Handler) GetSessionSecret() string { // Try to get from environment secret := h.GetEnv("DDNS_SESSION_SECRET", "") if secret != "" { return secret } // If not set, generate a warning and use admin password as base log.Warn("DDNS_SESSION_SECRET not set! Using derived key. Set this in production!") // Use admin login hash as base for session secret return h.Config.AdminLogin + "-session-secret-key" } // GetEnv gets environment variable with default func (h *Handler) GetEnv(key, defaultValue string) string { value := os.Getenv(key) if value == "" { return defaultValue } return value }