Google Oauth2 verifyIdToken 返回具有有效 id_token 的无效令牌签名

Posted

技术标签:

【中文标题】Google Oauth2 verifyIdToken 返回具有有效 id_token 的无效令牌签名【英文标题】:Google Oauth2 verifyIdToken return invalid token signature with valid id_token 【发布时间】:2014-05-31 01:08:05 【问题描述】:

我正在尝试使用 google Oauth2 api 的 php 客户端来验证 id_token。 id_token 由用户登录其 google 帐户的 javascript 应用程序提供,我将此令牌提供给我的 php api 服务器,以便对其进行验证并从我的 bdd 检索正确的信息。

javascript 登录成功,访问和 id_token 似乎正确,但是当我尝试使用 Google_Client->verifyIdToken() 进行验证时

$client = new Google_Client();
$ticket = $client->verifyIdToken(myToken);

,它返回一个无效的令牌签名异常(尝试使用谷歌证书验证令牌时失败)。

我的第一个假设是认为令牌无效,所以为了确保它是有效的,我将它提交到谷歌验证 url https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=token

它返回用户信息,所以我的令牌似乎是有效的:


issuer: "accounts.google.com",
issued_to: "id",
audience: "id",
user_id: "id",
expires_in: 2149,
issued_at: 1397636222,
email: "mail",
verified_email: true

尝试了我能想到的一切,但无法解决这个问题。 有人能帮我吗 ?

编辑:我只传递我在我的 javascript 应用程序上进行身份验证时获得的 id_token

access_token: "ya ... Es"
authuser: "1"
client_id: "81 ... .apps.googleusercontent.com"
code: "4/9... gI"
cookie_policy: "single_host_origin"
expires_at: "1397723048"
expires_in: "3600"
g-oauth-window: Window
g_user_cookie_policy: "single_host_origin"
hd: "dmic.fr"
id_token: "ey... d8E" <====================================
issued_at: "1397719448"
num_sessions: "2"
prompt: "none"
response_type: "code token id_token gsession"
scope: "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/plus.me"
session_state: "9 ... 2162..936b"
state: ""
status: Object
token_type: "Bearer"

在某些时候,我还尝试将整个 access_token 传递给 $client->setAccessToken() 并在没有参数的情况下调用 $client->verifyIdToken()(从 access_token 自己提取 id_token),结果相同。

我用的代码都已经贴出来了,我也试过设置apikey、c​​lient_id、client_secret,没有结果

【问题讨论】:

你到底传递给verifyIdToken的是什么?你能发布一些代码吗? @ViniciusPinto 我编辑了我的帖子 我刚刚做了一个小测试,效果很好,不知道你的代码可能出了什么问题。我会仔细检查id_token PHP 接收到的是否与 JS 库返回的完全相同。 我已经这样做了,完全一样 【参考方案1】:

我遇到了类似的问题,我从 oauth2client 收到“无效的令牌签名”错误,但它与 tokeninfo API 调用一起工作。

在我的情况下,这可能是由 oauth2client 使用的加密库引起的,因为当我用 pyopenssl 0.15.1 替换 pycrypto 2.6 时问题消失了。可能是 PyCrypto 错误?

编辑: 是的,经过验证,这是一个 PyCrypto 错误。它已在 20 小时前关闭:D

https://github.com/google/oauth2client/issues/201

【讨论】:

顺便说一句,如果有人在寻找c# client library solution,它也有类似的问题【参考方案2】:

您提供给 verifyIdToken 函数的参数应该是一个对象,而不仅仅是一个令牌字符串,但您可能想尝试不同的方法。

尝试将您在上面发布的 Javascript 对象的 code 属性传递给 PHP 客户端的 authenticate 函数。这应该在服务器端对用户进行身份验证,并为您填充 PHP 客户端对象的访问令牌。然后,您可以不带任何参数地调用 verifyIdToken。像这样的:

$client = new Google_Client();

// Setup Client Id and secret
...

//Authenticate client with the code posted via javascript
$client->authenticate($code);

// Verify the id token
$verifiedToken = $client->verifyIdToken();

您可能还需要更新您的 Google API PHP 库,我认为他们最近更改了从这些 API 返回的对象的格式。

【讨论】:

不能再测试这个答案了,但是请您抽时间【参考方案3】:

如果您传递给函数的 idToken 来自您的移动/网络应用程序的日志,由于通用打印函数的限制,您可能无法在日志中打印整个 idToken。

我使用下面的代码 sn-p 打印出 idToken 并在 API 中使用它,这给了我一个成功的响应。

print('ID TOKEN');
String token = googleAuth.idToken;
while (token.length > 0) 
    int initLength = (token.length >= 500 ? 500 : token.length);
    print(token.substring(0, initLength));
    int endLength = token.length;
    token = token.substring(initLength, endLength);

注意:代码 sn-p 是 Fl​​utter 特有的,但是登录可以在任何框架中重复使用。

【讨论】:

以上是关于Google Oauth2 verifyIdToken 返回具有有效 id_token 的无效令牌签名的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Google Services oAuth2 转换为 Google Ads API oAuth2 访问权限

如何获取经过 Google 身份验证的用户(oauth2)的 Google 聊天(环聊)ID?

Spring 5,401 返回后带有 Google 刷新访问令牌的 OAuth2

Rest,Spring 拥有 OAuth2 服务器 + OAuth2 提供商,如 Facebook、Google、Yahoo

Google oAuth2 令牌越来越失效

用于配置 OAuth2 同意和凭据的 Google Cloud Platform API