- Login/Register ставят cookie (HttpOnly, Secure, SameSite=Lax) - Middleware читает cookie первым - CORS: AllowCredentials=true - Для прямых API-вызовов остался Authorization Bearer - Legacy ?_t= query fallback
53 lines
1.3 KiB
Go
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")
|
|
}
|