[Admin UI] Login not possible due to securecookie error (#7374)

* [Admin UI] Login not possible due to securecookie error

* avoid 404 favicon

* Update weed/admin/dash/auth_middleware.go

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* address comments

* avoid variable over shadowing

* log session save error

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
Chris Lu
2025-10-24 12:48:59 -07:00
committed by GitHub
parent bf58c5a688
commit 9f4075441c
3 changed files with 87 additions and 27 deletions

View File

@@ -191,31 +191,7 @@ func startAdminServer(ctx context.Context, options AdminOptions) error {
r := gin.New()
r.Use(gin.Logger(), gin.Recovery())
// Session store - always auto-generate session key
sessionKeyBytes := make([]byte, 32)
_, err := rand.Read(sessionKeyBytes)
if err != nil {
return fmt.Errorf("failed to generate session key: %w", err)
}
store := cookie.NewStore(sessionKeyBytes)
// Configure session options to ensure cookies are properly saved
store.Options(sessions.Options{
Path: "/",
MaxAge: 3600 * 24, // 24 hours
})
r.Use(sessions.Sessions("admin-session", store))
// Static files - serve from embedded filesystem
staticFS, err := admin.GetStaticFS()
if err != nil {
log.Printf("Warning: Failed to load embedded static files: %v", err)
} else {
r.StaticFS("/static", http.FS(staticFS))
}
// Create data directory if specified
// Create data directory first if specified (needed for session key storage)
var dataDir string
if *options.dataDir != "" {
// Expand tilde (~) to home directory
@@ -236,6 +212,35 @@ func startAdminServer(ctx context.Context, options AdminOptions) error {
fmt.Printf("Data directory created/verified: %s\n", dataDir)
}
// Detect TLS configuration to set Secure cookie flag
cookieSecure := viper.GetString("https.admin.key") != ""
// Session store - load or generate session key
sessionKeyBytes, err := loadOrGenerateSessionKey(dataDir)
if err != nil {
return fmt.Errorf("failed to get session key: %w", err)
}
store := cookie.NewStore(sessionKeyBytes)
// Configure session options to ensure cookies are properly saved
store.Options(sessions.Options{
Path: "/",
MaxAge: 3600 * 24, // 24 hours
HttpOnly: true, // Prevent JavaScript access
Secure: cookieSecure, // Set based on actual TLS configuration
SameSite: http.SameSiteLaxMode,
})
r.Use(sessions.Sessions("admin-session", store))
// Static files - serve from embedded filesystem
staticFS, err := admin.GetStaticFS()
if err != nil {
log.Printf("Warning: Failed to load embedded static files: %v", err)
} else {
r.StaticFS("/static", http.FS(staticFS))
}
// Create admin server
adminServer := dash.NewAdminServer(*options.masters, nil, dataDir)
@@ -331,6 +336,46 @@ func GetAdminOptions() *AdminOptions {
return &AdminOptions{}
}
// loadOrGenerateSessionKey loads an existing session key from dataDir or generates a new one
func loadOrGenerateSessionKey(dataDir string) ([]byte, error) {
const sessionKeyLength = 32
if dataDir == "" {
// No persistence, generate random key
log.Println("No dataDir specified, generating ephemeral session key")
key := make([]byte, sessionKeyLength)
_, err := rand.Read(key)
return key, err
}
sessionKeyPath := filepath.Join(dataDir, ".session_key")
// Try to load existing key
if data, err := os.ReadFile(sessionKeyPath); err == nil {
if len(data) == sessionKeyLength {
log.Printf("Loaded persisted session key from %s", sessionKeyPath)
return data, nil
}
log.Printf("Warning: Invalid session key file (expected %d bytes, got %d), generating new key", sessionKeyLength, len(data))
} else if !os.IsNotExist(err) {
log.Printf("Warning: Failed to read session key from %s: %v. A new key will be generated.", sessionKeyPath, err)
}
// Generate new key
key := make([]byte, sessionKeyLength)
if _, err := rand.Read(key); err != nil {
return nil, err
}
// Save key for future use
if err := os.WriteFile(sessionKeyPath, key, 0600); err != nil {
log.Printf("Warning: Failed to persist session key: %v", err)
} else {
log.Printf("Generated and persisted new session key to %s", sessionKeyPath)
}
return key, nil
}
// expandHomeDir expands the tilde (~) in a path to the user's home directory
func expandHomeDir(path string) (string, error) {
if path == "" {