aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lu <chrislusf@users.noreply.github.com>2025-10-24 12:48:59 -0700
committerGitHub <noreply@github.com>2025-10-24 12:48:59 -0700
commit9f4075441ca3adff84fd8a4d88b03330c35db951 (patch)
treeb4d4e6d09cdee0da398bc4be99ac333a56d09279
parentbf58c5a6880728961456e9123ae0b196474fe7e1 (diff)
downloadseaweedfs-9f4075441ca3adff84fd8a4d88b03330c35db951.tar.xz
seaweedfs-9f4075441ca3adff84fd8a4d88b03330c35db951.zip
[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>
-rw-r--r--weed/admin/dash/auth_middleware.go14
-rw-r--r--weed/admin/handlers/admin_handlers.go5
-rw-r--r--weed/command/admin.go95
3 files changed, 87 insertions, 27 deletions
diff --git a/weed/admin/dash/auth_middleware.go b/weed/admin/dash/auth_middleware.go
index 986a30290..87da65659 100644
--- a/weed/admin/dash/auth_middleware.go
+++ b/weed/admin/dash/auth_middleware.go
@@ -5,6 +5,7 @@ import (
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
+ "github.com/seaweedfs/seaweedfs/weed/glog"
)
// ShowLogin displays the login page
@@ -31,9 +32,16 @@ func (s *AdminServer) HandleLogin(username, password string) gin.HandlerFunc {
if loginUsername == username && loginPassword == password {
session := sessions.Default(c)
+ // Clear any existing invalid session data before setting new values
+ session.Clear()
session.Set("authenticated", true)
session.Set("username", loginUsername)
- session.Save()
+ if err := session.Save(); err != nil {
+ // Log the detailed error server-side for diagnostics
+ glog.Errorf("Failed to save session for user %s: %v", loginUsername, err)
+ c.Redirect(http.StatusSeeOther, "/login?error=Unable to create session. Please try again or contact administrator.")
+ return
+ }
c.Redirect(http.StatusSeeOther, "/admin")
return
@@ -48,6 +56,8 @@ func (s *AdminServer) HandleLogin(username, password string) gin.HandlerFunc {
func (s *AdminServer) HandleLogout(c *gin.Context) {
session := sessions.Default(c)
session.Clear()
- session.Save()
+ if err := session.Save(); err != nil {
+ glog.Warningf("Failed to save session during logout: %v", err)
+ }
c.Redirect(http.StatusSeeOther, "/login")
}
diff --git a/weed/admin/handlers/admin_handlers.go b/weed/admin/handlers/admin_handlers.go
index 215e2a4e5..b1f465d2e 100644
--- a/weed/admin/handlers/admin_handlers.go
+++ b/weed/admin/handlers/admin_handlers.go
@@ -48,6 +48,11 @@ func (h *AdminHandlers) SetupRoutes(r *gin.Engine, authRequired bool, username,
// Health check (no auth required)
r.GET("/health", h.HealthCheck)
+ // Favicon route (no auth required) - redirect to static version
+ r.GET("/favicon.ico", func(c *gin.Context) {
+ c.Redirect(http.StatusMovedPermanently, "/static/favicon.ico")
+ })
+
if authRequired {
// Authentication routes (no auth required)
r.GET("/login", h.authHandlers.ShowLogin)
diff --git a/weed/command/admin.go b/weed/command/admin.go
index 8321aad80..e85b2e431 100644
--- a/weed/command/admin.go
+++ b/weed/command/admin.go
@@ -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 == "" {