PyJWT (Python)JWT 库
错误信息
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
含义
PyJWT 的 `ImmatureSignatureError`:令牌的 `iat`(签发时间)或 `nbf`(生效时间)晚于验证方的当前时间。括号中的名称指明是哪个声明。PyJWT 会拒绝“在未来”签发的令牌,因为正确的颁发者不可能生成这样的令牌;实际上,这几乎总是意味着颁发者的时钟比你的快。
原因
颁发者的时钟走快了
常见在时钟快了几秒的主机上生成的令牌,在每个时钟准确的验证方那里都会验证失败,直到这几秒过去为止。这个问题看起来是间歇性的,因为大多数请求到达时,这段偏差已经过去。
颁发者设置了未来的 nbf
偶见稍后才生效的令牌(定时访问、延迟激活)在 `nbf` 之前都会被拒绝。这是预期的行为。
以毫秒为单位的时间戳
罕见JWT 中的时间以秒为单位。如果颁发者写入 `time.time() * 1000` 或 JavaScript 的 `Date.now()`,生成的令牌要到几万年后才会生效。
修复方法
- 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