From db538f6deed257ff034649b65bb339135f35fb75 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 5 Nov 2025 13:26:24 +0000 Subject: [PATCH] Fix authentication: redirect to login page instead of showing JSON errors The auth middleware was returning JSON error messages ("No authentication token provided") for web UI requests, which displayed as plain text in the browser. Changes: - Added isAPIRequest check to detect if request is for /api/* or web UI - For web UI requests without auth: redirect to /login (HTTP 302) - For API requests without auth: return JSON error (HTTP 401) - Applied same logic for all auth failure scenarios (no token, invalid token, invalid claims, user not found) This fixes the issue where users see JSON errors in the browser instead of being properly redirected to the login page when authentication fails. --- internal/middleware/auth.go | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/internal/middleware/auth.go b/internal/middleware/auth.go index 0d054cbb..b9d7e084 100644 --- a/internal/middleware/auth.go +++ b/internal/middleware/auth.go @@ -21,6 +21,9 @@ type Claims struct { // AuthMiddleware validates JWT tokens and sets the current user func AuthMiddleware(jwtSecret string) gin.HandlerFunc { return func(c *gin.Context) { + // Determine if this is an API request or web UI request + isAPIRequest := strings.HasPrefix(c.Request.URL.Path, "/api/") + // Try to get token from Authorization header authHeader := c.GetHeader("Authorization") var tokenString string @@ -47,7 +50,11 @@ func AuthMiddleware(jwtSecret string) gin.HandlerFunc { } if tokenString == "" { - c.JSON(http.StatusUnauthorized, gin.H{"error": "No authentication token provided"}) + if isAPIRequest { + c.JSON(http.StatusUnauthorized, gin.H{"error": "No authentication token provided"}) + } else { + c.Redirect(http.StatusFound, "/login") + } c.Abort() return } @@ -61,14 +68,22 @@ func AuthMiddleware(jwtSecret string) gin.HandlerFunc { }) if err != nil || !token.Valid { - c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid or expired token"}) + if isAPIRequest { + c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid or expired token"}) + } else { + c.Redirect(http.StatusFound, "/login") + } c.Abort() return } claims, ok := token.Claims.(*Claims) if !ok { - c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token claims"}) + if isAPIRequest { + c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token claims"}) + } else { + c.Redirect(http.StatusFound, "/login") + } c.Abort() return } @@ -76,7 +91,11 @@ func AuthMiddleware(jwtSecret string) gin.HandlerFunc { // Load user from database var user models.User if err := database.DB.First(&user, claims.UserID).Error; err != nil { - c.JSON(http.StatusUnauthorized, gin.H{"error": "User not found"}) + if isAPIRequest { + c.JSON(http.StatusUnauthorized, gin.H{"error": "User not found"}) + } else { + c.Redirect(http.StatusFound, "/login") + } c.Abort() return }