Fix Safari login: Connection:close + SameSite=None (Grok analysis)

Safari блокирует fetch после POST с Set-Cookie из-за keep-alive/HTTP2.
- Login/Register: Connection: close, Cache-Control: no-store
- Cookie: SameSite=None (кросс-поддомен buhapp → api.buhapp)
This commit is contained in:
ga 2026-08-21 10:57:22 +00:00
parent 6e2a54820e
commit 8cb0a066b8

View File

@ -20,6 +20,11 @@ const cookieName = "buhapp_at"
// setAuthCookie — кладём access-token в HttpOnly cookie (CORS-friendly, без preflight) // setAuthCookie — кладём access-token в HttpOnly cookie (CORS-friendly, без preflight)
func setAuthCookie(c *fiber.Ctx, token string, ttl time.Duration) { func setAuthCookie(c *fiber.Ctx, token string, ttl time.Duration) {
// SameSite=Lax работает только same-site (subdomain.co → api.subdomain.co)
// Cross-site нужен SameSite=None + Secure
// buhapp.mygoodservice.ru → api.buhapp.mygoodservice.ru — same-site в браузерной семантике
// Но Safari трактует cookie strictly — Lax достаточно для top-level navigation, не для fetch
// Поэтому: SameSite=None + Secure (обязательно для Safari кросс-поддомен)
c.Cookie(&fiber.Cookie{ c.Cookie(&fiber.Cookie{
Name: cookieName, Name: cookieName,
Value: token, Value: token,
@ -27,7 +32,7 @@ func setAuthCookie(c *fiber.Ctx, token string, ttl time.Duration) {
MaxAge: int(ttl.Seconds()), MaxAge: int(ttl.Seconds()),
HTTPOnly: true, HTTPOnly: true,
Secure: true, Secure: true,
SameSite: "Lax", SameSite: "None",
}) })
} }
@ -68,6 +73,8 @@ var phoneRe = regexp.MustCompile(`^\+?[0-9]{10,15}$`)
const dummyHash = "$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy" const dummyHash = "$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy"
func (h *AuthHandler) Register(c *fiber.Ctx) error { func (h *AuthHandler) Register(c *fiber.Ctx) error {
c.Set("Connection", "close")
c.Set("Cache-Control", "no-store")
var req registerRequest var req registerRequest
if err := c.BodyParser(&req); err != nil { if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid JSON"}) return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid JSON"})
@ -183,7 +190,10 @@ type loginRequest struct {
Password string `json:"password"` Password string `json:"password"`
} }
// Login — фикс для Safari: разрыв keep-alive после Set-Cookie
func (h *AuthHandler) Login(c *fiber.Ctx) error { func (h *AuthHandler) Login(c *fiber.Ctx) error {
c.Set("Connection", "close")
c.Set("Cache-Control", "no-store")
var req loginRequest var req loginRequest
if err := c.BodyParser(&req); err != nil { if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid JSON"}) return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid JSON"})