Сообщение об ошибке
The token is not yet valid (iat)
Также выводится как
- The token is not yet valid (nbf)
- jwt.exceptions.ImmatureSignatureError: The token is not yet valid (iat)
В скобках указано утверждение: `iat` или `nbf`. PyJWT 2.0–2.5 принимал `iat` из будущего; начиная с версии 2.6.0 такие токены отклоняются, поэтому после обновления со старой версии может проявиться расхождение часов, которое существовало всё это время.
PyJWT (Python) — jwt.exceptions.ImmatureSignatureError
Что это означает
`ImmatureSignatureError` в PyJWT: `iat` (время выдачи) или `nbf` (не ранее) токена позже текущего времени проверяющей стороны. Имя в скобках говорит, о каком утверждении речь. PyJWT отклоняет токены, выпущенные «в будущем», потому что корректный издатель не может создать такой токен; на практике это почти всегда означает, что часы издателя спешат относительно ваших.
Почему это происходит
Часы издателя спешат
частоТокены, выпущенные на хосте, часы которого спешат на несколько секунд, не проходят проверку ни у одной проверяющей стороны с правильными часами, пока не пройдёт столько же секунд. Сбой выглядит случайным, потому что большинство запросов приходит уже после того, как эти секунды прошли.
Издатель задал nbf в будущем
иногдаТокены, которые становятся действительными позже (доступ по расписанию, отложенная активация), отклоняются до наступления `nbf`. Так и задумано.
Метки времени в миллисекундах
редкоВремя в JWT указывается в секундах. Издатель, который записывает `time.time() * 1000` или `Date.now()` из JavaScript, выпускает токены, которые станут действительными только через десятки тысяч лет.
Как исправить
- 1.
Задайте небольшой допуск
`leeway` (секунды или `timedelta`) сглаживает расхождение часов для `exp`, `nbf` и `iat`. Ограничьтесь несколькими десятками секунд, а уход часов устраните синхронизацией по NTP.
python from datetime import timedelta claims = jwt.decode( token, signing_key, algorithms=["ES256"], audience="https://api.example.com", leeway=timedelta(seconds=30), # applies to exp, nbf and iat ) - 2.
Измерьте расхождение часов
Выведите каждое временное утверждение относительно локальных часов. Небольшая положительная разница по `iat` означает расхождение часов, огромная — ошибку с единицами измерения у издателя.
python import time c = jwt.decode(token, options={"verify_signature": False}) now = int(time.time()) print({k: c[k] - now for k in ("iat", "nbf", "exp") if k in c}) # seconds relative to this host