Сообщение об ошибке
Not enough segments
Также выводится как
- jwt.exceptions.DecodeError: Not enough segments
PyJWT (Python) — jwt.exceptions.DecodeError
Что это означает
PyJWT не смог разделить входные данные на `header.payload.signature`: в них меньше двух точек. Строка — не компактный JWS, поэтому ни ключ, ни алгоритм даже не использовались. В `jwt.decode()` приходит не JWT, а что-то другое, либо JWT, который по пути потерял хвост.
Почему это происходит
Непрозрачный токен доступа, а не JWT
частоМногие провайдеры OAuth выпускают непрозрачные токены доступа (`ya29.…` у Google, `gho_…` у GitHub). Такие токены предназначены для проверки у провайдера через интроспекцию или userinfo, а не для декодирования. Гарантированно JWT только `id_token` из OpenID Connect.
Декодирована не та переменная
частоИдентификатор сессии, API-ключ, `str(None)` или строка «undefined» из фронтенда. Если перед декодированием записать в журнал `repr(token)[:40]`, поиски обычно на этом и заканчиваются.
Токен обрезан
иногдаСлишком короткий столбец в базе данных, ограничение длины строки журнала или ручное копирование, оборванное раньше времени, могут отрезать последний сегмент вместе с точкой перед ним.
Как исправить
- 1.
Проверьте структуру перед декодированием
В компактном JWS ровно две точки. Всё остальное отклоняйте с кодом 401 на границе вашего API, чтобы некорректные входные данные никогда не доходили до декодера.
python def bearer_token(headers: dict) -> str | None: scheme, _, token = headers.get("Authorization", "").partition(" ") if scheme.lower() != "bearer" or token.count(".") != 2: return None # not a compact JWS: answer 401 instead of decoding return token - 2.
Проверяйте непрозрачные токены у издателя
Если провайдер выпускает непрозрачные токены доступа, обращайтесь к его эндпоинту интроспекции токенов (RFC 7662) или настройте провайдер так, чтобы он выпускал для вашего API токены доступа в формате JWT (часто для этого нужно запросить аудиторию).
python import requests # Opaque tokens are validated by the authorization server (RFC 7662), not by decoding them. resp = requests.post( "https://issuer.example.com/oauth2/introspect", data={"token": token}, auth=(CLIENT_ID, CLIENT_SECRET), timeout=5, ) active = resp.json().get("active", False)