mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-08-12 15:59:04 +00:00
The csrf_token double-submit cookie is set without max_age (a session cookie), while the access_token cookie is persistent over HTTPS (max_age = token_expiry_days, see _set_session_cookie). The two cookies represent one session but had different lifetimes. iOS Safari home-screen PWAs evict session cookies when iOS terminates the standalone web app, but keep persistent ones. On reopen the user still appears logged in (the persistent access_token survives and GET /api/v1/auth/me is CSRF-exempt), but the session-only csrf_token is gone, so the frontend's readCsrfCookie() returns null and sends no X-CSRF-Token header. The first state-changing request then fails with 403 "CSRF token missing. Include X-CSRF-Token header." Only re-login restored it. This only manifests over HTTPS, which is why plain-HTTP local dev never sees it. Give csrf_token the same max_age as access_token at both mint sites -- CSRFMiddleware (auth POSTs) and _set_csrf_cookie (OIDC GET callback) -- mirroring _set_session_cookie's `... if is_https else None` guard so the double-submit pair always shares a lifetime: persistent together over HTTPS, session-only together over plain HTTP. Regression tests in tests/test_auth_type_system.py: - test_csrf_cookie_persistent_on_https - test_csrf_cookie_session_only_on_http - test_oidc_callback_csrf_cookie_persistent_on_https Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>