// auth.go package middleware import ( "api_yal/internal/utils" "api_yal/internal/logger" "context" "net/http" "strings" "go.uber.org/zap" ) type contextKey string const ( UserIDKey contextKey = "userID" UserEmailKey contextKey = "userEmail" UserRoleKey contextKey = "userRole" ) // Cookie конфигурация const ( AuthCookieName = "auth_token" CookieMaxAge = 24 * 60 * 60 // 24 часа ) func AuthMiddleware(next http.Handler) http.Handler { zapLogger := logger.Get() return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { zapLogger.Debug("Debug start AuthMiddleware") var tokenString string // Пробуем получить токен из заголовка Authorization authHeader := r.Header.Get("Authorization") if authHeader != "" { tokenString = strings.Replace(authHeader, "Bearer ", "", 1) zapLogger.Debug("Token from Authorization header", zap.String("token", tokenString)) } // Если токена нет в заголовке, пробуем получить из куки if tokenString == "" { cookie, err := r.Cookie(AuthCookieName) if err == nil && cookie.Value != "" { tokenString = cookie.Value zapLogger.Debug("Token from cookie", zap.String("token", tokenString)) } } if tokenString == "" { http.Error(w, "Authorization required", http.StatusUnauthorized) return } // Валидируем токен jwtUtil := utils.NewJWTUtil("secret") claims, err := jwtUtil.ValidateToken(tokenString) if err != nil { // Если токен невалиден, удаляем куку http.SetCookie(w, &http.Cookie{ Name: AuthCookieName, Value: "", Path: "/", MaxAge: -1, HttpOnly: true, Secure: true, SameSite: http.SameSiteStrictMode, }) http.Error(w, "Invalid token", http.StatusUnauthorized) return } ctx := context.WithValue(r.Context(), UserIDKey, claims.UserID) ctx = context.WithValue(ctx, UserEmailKey, claims.Email) ctx = context.WithValue(ctx, UserRoleKey, claims.Role) zapLogger.Debug("Debug end AuthMiddleware") next.ServeHTTP(w, r.WithContext(ctx)) }) } // Вспомогательная функция для установки auth cookie func SetAuthCookie(w http.ResponseWriter, token string) { http.SetCookie(w, &http.Cookie{ Name: AuthCookieName, Value: token, Path: "/", MaxAge: CookieMaxAge, HttpOnly: true, Secure: true, // В production должно быть true SameSite: http.SameSiteStrictMode, }) } // Вспомогательная функция для удаления auth cookie func ClearAuthCookie(w http.ResponseWriter) { http.SetCookie(w, &http.Cookie{ Name: AuthCookieName, Value: "", Path: "/", MaxAge: -1, HttpOnly: true, Secure: true, SameSite: http.SameSiteStrictMode, }) } func AdminMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { role, ok := r.Context().Value(UserRoleKey).(string) if !ok || role != "admin" { http.Error(w, "Admin access required", http.StatusForbidden) return } next.ServeHTTP(w, r) }) }