我正试图用谷歌和OpenID连接来实现一个联邦登录系统,我不得不验证和解析我从谷歌获得的JWT令牌。我跟着Google文档来了。
根据docs的建议,我尝试使用现有的JWT库。GitHub上最流行的PHP版本似乎是JWT。问题似乎是JWK键的格式。
上面链接的谷歌文档,比如从jwks_uri
端点获取密钥,如他们的发现文档所示。该端点返回以下内容:
{
"keys": [
{
"kty": "RSA",
"alg": "RS256",
"use": "sig",
"kid": "1771931eb0eb64eb97733e857685be153e079bb9",
"n": "AMNFQMNJw/EVwrYsyPTnEHWkaPinPb4ngc/SqD701aisFhbU9/wWoKADeFtwfBcWl1qjzIqhPorQElB+2mtiqUh3Qtaazt1x5wA9XnJDe6kjtMGm9nNLMilSVNBilAE8GIdbciMycISfOfL0WRaJrqpNxewNEVZjuYiGzOWahiDP",
"e": "AQAB"
},
{
"kty": "RSA",
"alg": "RS256",
"use": "sig",
"kid": "7b3bc600209875d3c42ae277a0d018d1d21986ec",
"n": "AN2UvG5+hNEMIPIbnpPm+JQi6LFWXBPzg3Ltb3xkVmSTjVaCFWppw/ZYRBgpToGKZP9XJstlOE88SDUFSMZIkIqtLpnUqmZax2Zc2gjEB9PhmHSH3/tTmtZ1U0X6V+crqitZ2uc3NV78vCn9/s+WuPwk/gfKBG8Cirb0fgLmsPd9",
"e": "AQAB"
}
]
}
查看JWT类的来源的decode
和verify
方法,似乎$keys
参数可以是一个数组,但是他们希望数组键是kid
,数组值是:@param string|resource $key for HS*, a string key works. for RS*, must be a resource of an openssl public key
。提取kid
属性并将其用作数组键非常简单,但是应该使用什么作为数组值呢?
从谷歌的JWK文档来看,我们似乎在使用RS*
,但我不知道关键对象的哪一部分是resource of an openssl public key
。我尝试使用整个stdClass对象,只使用n
字符串,但都在openssl_verify
步骤中失败。该函数发出一个通知:“警告: openssl_verify():提供的密钥param不能强制进入公钥”。
所以,很明显,我传递的是错误的键,但是正确的键是什么呢?
为此,谷歌图书馆似乎使用不同端点来获取密钥。该端点似乎返回了一个证书数组。我需要用这样的东西代替吗?如果是这样,为什么文档会告诉您使用jwks_uri
端点?
发布于 2014-08-01 16:08:53
两个端点包含相同的信息,但格式不同。
jwks_uri
端点给出了RSA公钥的模和指数值。您可以使用这两个值来生成在https://www.googleapis.com/oauth2/v1/certs获得的PEM文件。
发布于 2015-01-16 05:13:21
对于那些将来尝试这样做的人,我想给出一个完整的答案;
n
和e
部分在jwks_uri
JSON密钥中给出了模数和指数,可以用来检索公钥(验证签名所需的全部内容)。本文详细介绍了在纯PHP中是如何做到这一点的:
--但是,您应该知道,谷歌jwks_uri
提供的JSON文档使用的是base64安全编码(即,替换+和/字符的普通base64 )。如果没有考虑到这一点,可能仍然会给出一个无效的证书。由于您提到使用php-jwt
,从模数中获取公钥的工作代码和使用phpseclib的指数是:
$modulus = 'someencodedmodulusvalue';
$exponent = 'someencodedexponentvalue';
$rsa = new Crypt_RSA();
$modulus = new Math_BigInteger(JWT::urlsafeB64Decode($modulus), 256);
$exponent = new Math_BigInteger(JWT::urlsafeB64Decode($exponent), 256);
$rsa->loadKey(array('n' => $modulus, 'e' => $exponent));
$rsa->setPublicKey();
$pubKey = $rsa->getPublicKey();
https://stackoverflow.com/questions/25086410
复制相似问题