buhapp-backend/internal/auth/middleware.go
ga 5b70bc3137 Auth: HttpOnly cookie buhapp_at (без CORS preflight)
- Login/Register ставят cookie (HttpOnly, Secure, SameSite=Lax)
- Middleware читает cookie первым
- CORS: AllowCredentials=true
- Для прямых API-вызовов остался Authorization Bearer
- Legacy ?_t= query fallback
2026-08-20 21:50:28 +00:00

53 lines
1.3 KiB
Go

package auth
import (
"errors"
"strings"
"github.com/gofiber/fiber/v2"
)
const UserIDKey = "user_id"
func Middleware(svc *Service) fiber.Handler {
return func(c *fiber.Ctx) error {
var token string
// 1. HttpOnly cookie (основной способ — без CORS preflight)
token = c.Cookies("buhapp_at")
// 2. Authorization: Bearer <token> (для прямых API-вызовов)
if token == "" {
h := c.Get("Authorization")
if h != "" {
parts := strings.SplitN(h, " ", 2)
if len(parts) == 2 && strings.ToLower(parts[0]) == "bearer" {
token = parts[1]
}
}
}
// 3. Fallback — query param ?_t=<token> (legacy)
if token == "" {
token = c.Query("_t")
}
if token == "" {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "missing token"})
}
claims, err := svc.Parse(c.UserContext(), token)
if err != nil {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "invalid token"})
}
c.Locals(UserIDKey, claims.UserID)
return c.Next()
}
}
func UserID(c *fiber.Ctx) (string, error) {
v := c.Locals(UserIDKey)
if v == nil {
return "", errors.New("no user in context")
}
if id, ok := v.(interface{ String() string }); ok {
return id.String(), nil
}
return "", errors.New("invalid user id type")
}