Make the Secure cookie attribute configurable for TLS-less dev stands

Session cookies were hardcoded Secure, which is correct for prod but
silently breaks every non-localhost HTTP dev deployment: browsers (and
any spec-compliant HTTP client, verified with curl against a container IP
and against dev.netrunner-vpn.com directly) refuse to store a Secure
cookie received over plain HTTP unless the host is localhost. The dev VPS
serves everything over plain HTTP with no reverse-proxy/TLS by design, so
every login there was silently failing to persist a session at all —
this is a bigger, more fundamental gap than the cookie-sharing-with-the-
landing question that led to finding it.

Added COOKIE_SECURE (defaults true) alongside the existing COOKIE_DOMAIN,
logs a loud warning when disabled, and turned it off for the dev-remote
and local docker-dev env templates. Verified end-to-end against a
non-localhost address that the cookie now actually gets stored and a
follow-up authenticated request succeeds.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-04 19:20:14 +07:00
parent a7607e4b33
commit acfcdbe90e
6 changed files with 62 additions and 8 deletions
+8
View File
@@ -47,6 +47,13 @@ pub struct ApiState {
/// cookie host-only. В проде — `.netrunner-vpn.com`, чтобы одна сессия работала
/// и на лендинге, и на ЛК (общий родительский домен, разные сабдомены).
pub cookie_domain: String,
/// `Secure`-атрибут сессионных cookie. По умолчанию `true` — обязателен для
/// прода (HTTPS). На dev-стендах без TLS (голый HTTP на IP/домен, не
/// `localhost`) браузер и любой нормальный HTTP-клиент **молча отбрасывает**
/// `Secure`-cookie, полученную не по HTTPS, — сессия не переживает вообще ни
/// одного запроса. Для таких стендов явно выставляется `false` через
/// `COOKIE_SECURE=false`.
pub cookie_secure: bool,
/// Origin'ы, с которых разрешён cookie-based доступ к мутирующим ручкам
/// (CSRF-проверка в `auth::guard`). Отдельно от `CORS_ALLOWED_ORIGINS`, т.к. туда
/// же попадают Bearer-клиенты (Tauri), для которых CSRF неактуален.
@@ -66,6 +73,7 @@ impl Clone for ApiState {
bot_token: self.bot_token.clone(),
admin_tg_id: self.admin_tg_id,
cookie_domain: self.cookie_domain.clone(),
cookie_secure: self.cookie_secure,
csrf_allowed_origins: self.csrf_allowed_origins.clone(),
}
}