firebase/php-jwt (PHP)PHP
错误信息
"kid" invalid, unable to lookup correct key
也可能输出为
- "kid" empty, unable to lookup correct key
传入密钥数组时,如果令牌头部中没有 `kid`,就会抛出“\"kid\" empty, unable to lookup correct key”。
firebase/php-jwt (PHP) — UnexpectedValueException from JWT::decode with a key array
含义
你向 `JWT::decode` 传入了一个密钥数组(通常来自 `JWK::parseKeySet`),但数组中没有与令牌头部中的 `kid` 对应的条目。php-jwt 严格按 `kid` 选择密钥,不会尝试其他密钥。与之相关的另一个错误“\"kid\" empty”表示令牌根本没有 `kid`,这种情况下密钥数组无法确定该用哪个密钥。
原因
缓存的密钥集早于密钥轮换
常见把 JWKS 保存在文件、数据库或长期缓存中的应用,在提供商轮换密钥后仍保留着旧的密钥 ID。Google 和 Firebase 每隔几天就会轮换一次令牌签名密钥。
来自其他颁发者或其他项目的密钥集
偶见另一个租户的 JWKS URL,或者用 Google 的 OAuth 证书来验证 Firebase ID 令牌(Firebase 使用单独的密钥 URL)。
颁发者没有设置 kid
偶见没有 `kid` 的令牌只能用单个 `Key` 对象验证,不能用密钥数组验证。
修复方法
- 1.
使用 CachedKeySet
它通过 PSR-6 缓存 JWKS,遇到未知的 `kid` 时重新获取,还可以选择启用限流,防止随机的 `kid` 值向颁发者发起大量请求。
php use Firebase\JWT\CachedKeySet; // Refetches the JWKS when a token names a kid the cache does not have (rate-limited). $keys = new CachedKeySet($jwksUri, $httpClient, $httpFactory, $cachePool, 3600, true); $claims = JWT::decode($token, $keys); - 2.
对不设置 kid 的颁发者,传入单个 Key
如果颁发者只有一个密钥且不设置 `kid`,就直接传入该密钥。
php // Issuer without kid and with exactly one key: pass a Key object, not an array. $claims = JWT::decode($token, new Key($publicKeyPem, 'ES256'));