From 8cb0a066b8f1353526fff8c97c5475a30a1b35c4 Mon Sep 17 00:00:00 2001 From: ga Date: Fri, 21 Aug 2026 10:57:22 +0000 Subject: [PATCH] Fix Safari login: Connection:close + SameSite=None (Grok analysis) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Safari блокирует fetch после POST с Set-Cookie из-за keep-alive/HTTP2. - Login/Register: Connection: close, Cache-Control: no-store - Cookie: SameSite=None (кросс-поддомен buhapp → api.buhapp) --- internal/handlers/auth.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/internal/handlers/auth.go b/internal/handlers/auth.go index 60dd7dc..aa5fefe 100644 --- a/internal/handlers/auth.go +++ b/internal/handlers/auth.go @@ -20,6 +20,11 @@ const cookieName = "buhapp_at" // setAuthCookie — кладём access-token в HttpOnly cookie (CORS-friendly, без preflight) 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{ Name: cookieName, Value: token, @@ -27,7 +32,7 @@ func setAuthCookie(c *fiber.Ctx, token string, ttl time.Duration) { MaxAge: int(ttl.Seconds()), HTTPOnly: true, Secure: true, - SameSite: "Lax", + SameSite: "None", }) } @@ -68,6 +73,8 @@ var phoneRe = regexp.MustCompile(`^\+?[0-9]{10,15}$`) const dummyHash = "$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy" func (h *AuthHandler) Register(c *fiber.Ctx) error { + c.Set("Connection", "close") + c.Set("Cache-Control", "no-store") var req registerRequest if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid JSON"}) @@ -183,7 +190,10 @@ type loginRequest struct { Password string `json:"password"` } +// Login — фикс для Safari: разрыв keep-alive после Set-Cookie func (h *AuthHandler) Login(c *fiber.Ctx) error { + c.Set("Connection", "close") + c.Set("Cache-Control", "no-store") var req loginRequest if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid JSON"})