0.135.0
Security
- PKCE для WebUI (C-SC-9): WebUI переведён с устаревшего
grant_type=password(RFC 6749 §1.3.3, deprecated OAuth 2.0 Security BCP §2.4) на Authorization Code Flow с PKCE (RFC 7636).web/src/lib/api/client.ts:loginRequestреализует 3-шаговый нередиректный SPA-флоу через session cookie:POST /oauth/login→POST /oauth/authorize(сcode_challengeS256 + CSRF double-submit) →POST /oauth/token(сcode_verifier, сервер проверяет PKCE черезverifyPKCE). Access-токен хранится в памяти, refresh-токен в httpOnly cookietc_refresh. - Валидация redirect_uri (code-exfiltration protection):
expectedWebUIRedirectURIвauth.goпроверяет, чтоredirect_uriсовпадает с Origin клиента (RFC 6454 canonicalization, host-match сr.Host). Fail-closed: запросы без валидного Origin дляclient_id="webui"отклоняются (браузеры шлют Origin на same-origin POST; API-скрипты используют password/refresh grant без redirect_uri). Проверка выполняется ДО session-lookup (DoS-amplification prevention). - Deprecation/Sunset headers:
grant_type=passwordостаётся для API-клиентов (curl, скрипты), но ответы помечаютсяDeprecation: true+Sunset(RFC 8594) — удаление запланировано в v1.0. - Cleanup при partial-flow failure: если шаги authorize/token падают после успешного login (включая network errors, malformed JSON), клиент инвалидирует server-side session (
POST /oauth/logout) + чистит cookiestc_session/tc_csrfна клиенте, предотвращая «полу-аутентифицированное» состояние.
Changed
- authLimiter 5→15 req/min/IP: 3-шаговый PKCE-флоу = 3 запроса на попытку входа, поэтому общий лимит
/oauth/*поднят с 5 до 15 (~5 попыток/мин для легитимного пользователя). Account-level lockout (5 неудач → 15 мин блок) остаётся основным заслоном от перебора. - /oauth/logout вынесен из-под authLimiter: logout вызывается как cleanup при ошибках login-флоу; rate-limiting оставил бы stale
tc_session/tc_csrf. Logout идемпотентен (только очищает server-side state). - Doc-комментарий C-SC-9 в
internal/auth/oauth.goобновлён: TODO(C-SC-9) выполнен, описана нередиректная SPA-архитектура.
Added
- PKCE-хелперы
generateCodeVerifier/generateCodeChallenge(S256) вclient.ts, экспортированы для юнит-тестов. - Singleton-de-duplication для
loginRequest(double-click protection — повторный вызов возвращает тот же промис). - Тесты:
web/src/lib/api/pkce.test.ts(RFC 7636 test vector: verifier 43 chars, S256 challenge), интеграционныеauth_test.go:TestPKCEFlow_LoginAuthorizeToken,TestPKCEFlow_RejectsWrongVerifier,TestPasswordGrant_DeprecationHeader,TestAuthorizationCodeGrant_NoDeprecationHeader,TestAuthorize_RejectsRedirectURIMismatch,TestAuthorize_AcceptsMatchingRedirectURI. ОбновлёнTestOAuthToken_RateLimited(лимит 15).