谷歌登录导致使用JWT PHP库"Signature verification failed"的网站



谷歌网络登录让我非常疯狂......

我正在构建一个简单的Web应用程序,并尝试将Google的登录功能集成到网站中(https://developers.google.com/identity/sign-in/web/(。

JavaScript似乎进展得相当顺利,下一步是验证我收到的后端服务器id_token(再次,反对Google的建议:https://developers.google.com/identity/sign-in/web/backend-auth(。

这是一个基于 PHP 的 Web 应用程序,我已经使用 composer:composer require google/apiclient成功安装了 Google 客户端 API 库,但是当将我的id_token值发布到我的 PHP 后端系统时,我不断收到以下错误:

FirebaseJWTSignatureInvalidException
File: .vendorfirebasephp-jwtsrcJWT.php:112 
Message: Signature verification failed
Stack trace:
#0 .vendorgoogleapiclientsrcGoogleAccessTokenVerify.php(103): FirebaseJWTJWT::decode('eyJhbGciOiJSUzI...', '-----BEGIN PUBL...', Array)
#1 .vendorgoogleapiclientsrcGoogleClient.php(712): Google_AccessToken_Verify->verifyIdToken('eyJhbGciOiJSUzI...', '10...')

我还在Google的"tokeninfo"端点(https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=ABC123(上使用了id_token值,并且id_token验证完美,因此我确定不是id_token值是错误的。它也通过 POST 变量完美地将其传递给 PHP 脚本,所以我有点不知所措。

这是我的代码:

Javascript:

<script src="https://apis.google.com/js/platform.js?onload=googleAppStart" async defer></script>
<script>
var googleAppStart  = function(){gapi.load('auth2', initGoogleSignIn);};
var auth            = false;
function initGoogleSignIn(){
auth = gapi.auth2.init({
client_id   : 'client-id-is-here',
scope       : 'profile'
});
auth.attachClickHandler(document.getElementById('my-button'));
auth.isSignedIn.listen(googleSignInChanged);
auth.currentUser.listen(googleCurrentUserChanged);
if (auth.isSignedIn.get() == true)
auth.signIn();
}
function googleSignInChanged(signed_in){}
function googleCurrentUserChanged(user){
var auth_response   = user.getAuthResponse();
var id_token        = auth_response.id_token;
if (id_token != undefined){
var url     = '/verify-google-signin';
var params  = {id_token: id_token};
jQuery.post(url, params, function(data){}, 'json');
}
}
</script>

。和我的PHP抓住了POST:

<?php
require_once '/vendor/autoload.php';
$credentials = array("client_id" => "client-id-is-here");
$client = new Google_Client($credentials);
$data = $_POST;
if (isset($data['id_token'])) {
$id_token = trim($data['id_token']);
// Exception generated here...
$payload = $client->verifyIdToken($id_token);
}
?>

非常感谢您抽出宝贵时间阅读本文,并提供任何帮助!非常感谢!

我今天遇到了同样的问题。

如果你只是执行,更容易:

作曲家需要 Firebase/PHP-JWT:4.0

幸运的是,您可以在没有谷歌图库的情况下验证id_token,如此处所述 https://developers.google.com/identity/sign-in/web/backend-auth#calling-the-tokeninfo-endpoint

if (isset($data['id_token'])) {
$id_token = trim($data['id_token']);
try {
$res = (new GuzzleHttpClient())->request('GET',
'https://www.googleapis.com/oauth2/v3/tokeninfo', [
'query' => ['id_token' => $id_token],
]);
$payload = json_decode($res->getBody()->getContents(), true);
//you still need to check that the aud claim contains one of your app's client IDs
if ($payload['aud'] != "client-id-is-here") {
throw new Exception("App Isn't valid", 422);
}
} catch (RequestException $e) {
//IF token isn't valid you will be here
if ($e->hasResponse()) {
/** @var GuzzleHttpPsr7Response $resp */
$resp = $e->getResponse();
$error = json_decode($resp->getBody()->getContents(), true)['error_description'];
throw new Exception($error, $resp->getStatusCode());
}
}
}

如果您没有例外,那么您的令牌是有效的

这是php-jwt的问题。最新版本不适用于谷歌 API 客户端。

尝试使用 php-jwt 版本 4。

我把"firebase/php-jwt":"<5.0"放在我的composer.json文件中。

作为魅力工作!

此问题已在 google/apiclient 的 v2.2.1 中修复,因此请确保您运行的是此版本或更高版本,如果其他人遇到此问题。

相关讨论 这里 和 这里.

昨天我使用 google/apiclient 2.2.0 和 2.1.3 在 Google 登录后端身份验证时遇到了问题。

tl;博士,这很可能是谷歌方面的故障或我不知道的一些模糊限制(开发人员控制台中没有任何关于此的内容(。

首先,谷歌给我的客户端"idToken"不是一个有效的JWT:openssl_verify((在Firebase\JWT\JWT中拒绝了它,抛出了一个Firebase\JWT\SignatureInvalidException。我听从了您的建议,安装了 google/apiclient 2.1.3,并且不再抛出此异常,但生成的有效负载为空(因此 idToken 仍然无效(。

几个小时后,我在使用 apiclient 2.3.0 时遇到了间歇性的结果:有时令牌通过签名验证(并引发签名异常(失效,有时令牌在加密上有效,但返回的有效负载为空。偶尔,令牌是有效的(!

最后,后端身份验证过程每次都成功。

当我开始遇到这些问题时,我试图修复它生成新的 OAuth2 密钥,恢复到我知道正在工作的我的代码库(服务器端和客户端(的先前版本,删除所有浏览器数据并尝试通过 Android 登录在 Cordova 上获取令牌。什么都没用。开发人员控制台中也没有消息,没有可见的限制,没有安全电子邮件。

如果它不是一个错误而是一个功能,那么错误处理是非常苛刻的:)

如果您没有使用Firebase(取自 https://github.com/googleapis/google-api-php-client(

rm -r vendor/google/apiclient-services

将此添加到 composer.json

"scripts": {
"post-update-cmd": "Google\Task\Composer::cleanup"
},
"extra": {
"google/apiclient-services": [
"Drive"  ,
"... any other services here ...",
]
}

最后

composer install

这将解决错误消息,并具有大幅减少已安装软件包的额外好处。如前所述,GAPI 至少有 200 个 API 服务

相关内容

最新更新