Files
tp/main_dc/yalarba/api_yal/internal/middleware/auth.go
T
valitovgaziz 8b40d1bfe5 On branch main
modified:   internal/domain/auth/dto.go
	modified:   internal/domain/auth/handler.go
	modified:   internal/domain/auth/router.go
	modified:   internal/domain/auth/servcie.go
	modified:   internal/middleware/auth.go
	modified:   internal/router/router.go
auth implemented without reset password
2026-03-31 04:22:54 +05:00

143 lines
4.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// middleware/auth.go (обновленная версия с логированием)
package middleware
import (
"context"
"fmt"
"net/http"
"strings"
"api_yal/internal/logger"
"github.com/golang-jwt/jwt/v5"
"go.uber.org/zap"
)
type contextKey string
const (
UserIDKey contextKey = "userID"
UserEmailKey contextKey = "userEmail"
UserRoleKey contextKey = "userRole"
)
// AuthMiddleware создает middleware для проверки JWT токена
func AuthMiddleware(jwtSecret string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
l := logger.Get()
l.Info("=== AUTH MIDDLEWARE START ===")
l.Info("Request path", zap.String("path", r.URL.Path))
// Получаем токен из заголовка Authorization
authHeader := r.Header.Get("Authorization")
l.Info("Authorization header", zap.String("header", authHeader))
if authHeader == "" {
l.Warn("Отсутствует заголовок Authorization")
http.Error(w, "Authorization header required", http.StatusUnauthorized)
return
}
// Ожидаем формат "Bearer <token>"
parts := strings.Split(authHeader, " ")
if len(parts) != 2 || strings.ToLower(parts[0]) != "bearer" {
l.Warn("Неверный формат заголовка Authorization",
zap.Int("parts_count", len(parts)),
zap.String("first_part", parts[0]))
http.Error(w, "Invalid authorization header format", http.StatusUnauthorized)
return
}
tokenString := parts[1]
l.Info("Token extracted", zap.String("token_preview", tokenString[:min(20, len(tokenString))]+"..."))
// Парсим и валидируем токен
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
// Проверяем метод подписи
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
l.Error("Unexpected signing method",
zap.String("method", token.Method.Alg()))
return nil, jwt.ErrSignatureInvalid
}
return []byte(jwtSecret), nil
})
if err != nil {
l.Error("Token parse error", zap.Error(err))
http.Error(w, "Invalid token: "+err.Error(), http.StatusUnauthorized)
return
}
if !token.Valid {
l.Error("Token is not valid")
http.Error(w, "Invalid token", http.StatusUnauthorized)
return
}
l.Info("Token is valid")
// Извлекаем claims
claims, ok := token.Claims.(jwt.MapClaims)
if !ok {
l.Error("Failed to extract claims")
http.Error(w, "Invalid token claims", http.StatusUnauthorized)
return
}
l.Info("Claims extracted", zap.Any("claims", claims))
// Проверяем тип токена (должен быть access)
if tokenType, exists := claims["type"]; exists {
l.Info("Token type", zap.String("type", tokenType.(string)))
if tokenType != "access" {
l.Error("Wrong token type, expected access", zap.String("type", tokenType.(string)))
http.Error(w, "Invalid token type", http.StatusUnauthorized)
return
}
}
// Добавляем информацию о пользователе в контекст
ctx := r.Context()
// Извлекаем userID из sub (subject)
// В claims sub хранится как string, а не float64
if userID, ok := claims["sub"].(string); ok {
l.Info("User ID from claims", zap.String("user_id_str", userID))
// Конвертируем string в uint
var userIDUint uint
if _, err := fmt.Sscan(userID, &userIDUint); err == nil {
ctx = context.WithValue(ctx, UserIDKey, userIDUint)
l.Info("User ID added to context", zap.Uint("user_id", userIDUint))
}
} else {
l.Error("sub claim not found or wrong type")
}
// Извлекаем email
if email, ok := claims["email"].(string); ok {
ctx = context.WithValue(ctx, UserEmailKey, email)
l.Info("Email added to context", zap.String("email", email))
}
// Извлекаем роль
if role, ok := claims["role"].(string); ok {
ctx = context.WithValue(ctx, UserRoleKey, role)
l.Info("Role added to context", zap.String("role", role))
}
l.Info("=== AUTH MIDDLEWARE END ===")
// Передаем управление дальше с обновленным контекстом
next.ServeHTTP(w, r.WithContext(ctx))
})
}
}
func min(a, b int) int {
if a < b {
return a
}
return b
}