Google登录网站,导致JWT PHP库“签名验证失败”

时间:2017-08-02 00:08:04

标签: javascript php google-api-php-client google-signin

Google网络登录让我感到非常疯狂......

我正在构建一个简单的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 Client API库,但在将id_token值发布到我的PHP后端系统时,我始终如一收到以下错误:

Firebase\JWT\SignatureInvalidException
File: .\vendor\firebase\php-jwt\src\JWT.php:112 
Message: Signature verification failed

Stack trace:
#0 .\vendor\google\apiclient\src\Google\AccessToken\Verify.php(103): Firebase\JWT\JWT::decode('eyJhbGciOiJSUzI...', '-----BEGIN PUBL...', Array)
#1 .\vendor\google\apiclient\src\Google\Client.php(712): Google_AccessToken_Verify->verifyIdToken('eyJhbGciOiJSUzI...', '10...')

我还在Google的“tokeninfo”端点(https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=ABC123)上使用了id_token值,id_token完美地验证了,所以我确定它不是{{1}这是错的。它也通过POST变量完美地传递给PHP脚本,所以我有点不知所措。

这是我的代码:

使用Javascript:

id_token

...我的PHP抓住了POST:

<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>

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

6 个答案:

答案 0 :(得分:11)

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

如果您执行以下操作更容易:

composer require firebase/php-jwt:4.0

答案 1 :(得分:3)

幸运的是,您可以在没有Google图书馆的情况下验证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 \GuzzleHttp\Client())->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 \GuzzleHttp\Psr7\Response $resp */
                $resp = $e->getResponse();
                $error = json_decode($resp->getBody()->getContents(), true)['error_description'];
                throw new \Exception($error, $resp->getStatusCode());
            }
        }
    }

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

答案 2 :(得分:2)

这是php-jwt的一个问题。最新版本不适用于Google Api客户端。

尝试使用php-jwt版本4。

我在我的composer.json文件中放了“firebase / php-jwt”:“&lt; 5.0”。

充当魅力!

答案 3 :(得分:1)

我昨天使用google / apiclient 2.2.0和2.1.3进行了Google登录后端身份验证。

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

首先,&#34; idToken&#34;谷歌给我的客户端不是有效的JWT:openssl_verify()在Firebase \ JWT \ JWT中拒绝它,抛出Firebase \ JWT \ SignatureInvalidException。我按照你的建议,安装了google / apiclient 2.1.3,这个异常不再被抛出,但结果有效负载为空(所以idToken仍然无效)。

几个小时之后,我遇到了apiclient 2.3.0的间歇性结果:有时签名验证无效(并抛出签名异常),有时令牌加密有效但返回的有效负载为空。偶尔,令牌有效(!)。

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

当我开始遇到这些问题时,我尝试修复它生成新的OAuth2密钥,恢复到我知道正在运行的代码库(服务器端和客户端)的先前版本,删除所有浏览器数据并尝试使用Sign In for Android在Cordova上获取令牌。没有任何效果。此外,开发人员控制台中没有消息,没有可见限制,没有安全电子邮件。

如果它不是错误而是功能,则错误处理非常苛刻:)

答案 4 :(得分:1)

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

相关讨论herehere

答案 5 :(得分:0)

如果您不使用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服务