Зависимости под контур: PyJWT[crypto] 2.8.0, cryptography 43.0.3 (и правка JwksVerifier) #43

Closed
opened 2026-10-07 17:08:12 +03:00 by aep · 0 comments
Owner

Откуда

Запрос разработчика, который переносит сервисы в контур РАИСА: в arm-core должны стоять pyjwt[crypto]==2.8.0 и cryptography==43.0.3. Сейчас api/requirements.txt: PyJWT[crypto]==2.15.1, cryptography==50.0.2; api/requirements-dev.txt: PyJWT[crypto] ≥ 2.9.

Что проверено (07.10.2026, отдельный venv)

  • Вся requirements.txt с этими версиями разрешается без конфликтов (uv pip compile, кроме raisa_*).
  • Dev-аутентификация (DevHs256Verifier, POST /api/v1/dev/token) на 2.8.0 работает: encode/decode HS256, require: [exp, sub], чужая подпись → InvalidSignatureError.
  • Параметры PyJWKClient(cache_keys, cache_jwk_set, lifespan, timeout) на 2.8.0 принимаются.
  • Ломается JwksVerifier: src/core/auth.py, _signing_key отдаёт в jwt.decode сам объект PyJWK — это поддерживается только с PyJWT 2.10. На 2.8.0 TypeError: Expecting a PEM-formatted key → перехватывается → 401 «недействительный токен» на любой токен из JWKS. Статический AUTH_PUBLIC_KEY работает.

Что сделать

  1. api/requirements.txt: PyJWT[crypto]==2.8.0, cryptography==43.0.3; api/requirements-dev.txt: убрать нижнюю границу 2.9 (согласовать с 2.8.0).
  2. JwksVerifier._signing_key: в jwt.decode передавать signing_key.key, а допустимый алгоритм выводить из типа ключа самим (RSA → RS256, EC P-256 → ES256 — как уже сделано для AUTH_PUBLIC_KEY в _load_static_key), чтобы сохранить поведение «ключ одного типа не принимает токен другого алгоритма» (Срез 0, решение #72).
  3. Тесты api/tests/test_auth_core.py (блок JwksVerifier, _FakeJwkClient) — зелёные на 2.8.0; добавить случай RSA-ключ + ES256-токен → 401 (а не 500). Проверить, что PyJWKClientConnectionError есть в 2.8.0 (импортируется в тестах).
  4. make check-full зелёный на новых версиях.

Контекст

В контуре пока разворачиваем без платформенной аутентификации, только dev-заглушка (DEBUG=true, AUTH_DEV_ISSUER=true, AUTH_DEV_SECRET) — она с 2.8.0 работает и без этой задачи. JWKS-путь понадобится, когда подключим SSO РАИСА (OQ-54: параметры Keycloak, iss/aud, claim с email; не выяснено, используется ли на платформе raisa_fastapi_protected_api — в коде он импортируется, но не подключён). Возможно, версии 2.8.0 / 43.0.3 — требование самого raisa_fastapi_protected_api; уточнить у разработчика.

Bounded-задача. Если requirements.txt трогает Срез 3b (#36) — начинать после его слияния.

## Откуда Запрос разработчика, который переносит сервисы в контур РАИСА: в arm-core должны стоять `pyjwt[crypto]==2.8.0` и `cryptography==43.0.3`. Сейчас `api/requirements.txt`: `PyJWT[crypto]==2.15.1`, `cryptography==50.0.2`; `api/requirements-dev.txt`: `PyJWT[crypto]` ≥ 2.9. ## Что проверено (07.10.2026, отдельный venv) - Вся `requirements.txt` с этими версиями разрешается без конфликтов (`uv pip compile`, кроме `raisa_*`). - Dev-аутентификация (`DevHs256Verifier`, `POST /api/v1/dev/token`) на 2.8.0 работает: encode/decode HS256, `require: [exp, sub]`, чужая подпись → `InvalidSignatureError`. - Параметры `PyJWKClient(cache_keys, cache_jwk_set, lifespan, timeout)` на 2.8.0 принимаются. - **Ломается `JwksVerifier`**: `src/core/auth.py`, `_signing_key` отдаёт в `jwt.decode` сам объект `PyJWK` — это поддерживается только с PyJWT 2.10. На 2.8.0 `TypeError: Expecting a PEM-formatted key` → перехватывается → 401 «недействительный токен» на **любой** токен из JWKS. Статический `AUTH_PUBLIC_KEY` работает. ## Что сделать 1. `api/requirements.txt`: `PyJWT[crypto]==2.8.0`, `cryptography==43.0.3`; `api/requirements-dev.txt`: убрать нижнюю границу 2.9 (согласовать с 2.8.0). 2. `JwksVerifier._signing_key`: в `jwt.decode` передавать `signing_key.key`, а допустимый алгоритм выводить из типа ключа самим (RSA → RS256, EC P-256 → ES256 — как уже сделано для `AUTH_PUBLIC_KEY` в `_load_static_key`), чтобы сохранить поведение «ключ одного типа не принимает токен другого алгоритма» (Срез 0, решение #72). 3. Тесты `api/tests/test_auth_core.py` (блок JwksVerifier, `_FakeJwkClient`) — зелёные на 2.8.0; добавить случай RSA-ключ + ES256-токен → 401 (а не 500). Проверить, что `PyJWKClientConnectionError` есть в 2.8.0 (импортируется в тестах). 4. `make check-full` зелёный на новых версиях. ## Контекст В контуре пока разворачиваем **без платформенной аутентификации**, только dev-заглушка (`DEBUG=true`, `AUTH_DEV_ISSUER=true`, `AUTH_DEV_SECRET`) — она с 2.8.0 работает и без этой задачи. JWKS-путь понадобится, когда подключим SSO РАИСА (OQ-54: параметры Keycloak, `iss`/`aud`, claim с email; не выяснено, используется ли на платформе `raisa_fastapi_protected_api` — в коде он импортируется, но не подключён). Возможно, версии 2.8.0 / 43.0.3 — требование самого `raisa_fastapi_protected_api`; уточнить у разработчика. Bounded-задача. Если `requirements.txt` трогает Срез 3b (#36) — начинать после его слияния.
aep closed this issue 2026-10-07 17:41:38 +03:00
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RSHB/arm-core#43
No description provided.