OAuth2.0令牌的奇怪行为(无效凭据401)

41
通常情况下,Google OAuth2.0机制运行良好。
1. 用户确认选择的范围以访问Google帐户的权限。 2. 检索并保存刷新令牌以进行长期存储。 3. 每次需要(如果访问令牌过期)检索访问令牌并用于访问API。
但有时候(迄今为止只有两次超过6个月),我遇到了奇怪的行为:
对Google API的请求返回无效凭据(401)错误。使用存储的刷新令牌刷新访问令牌无法解决问题。
以下是在测试此问题时获得的一些结构化输出:

我也尝试通过向https://www.googleapis.com/oauth2/v1/tokeninfo发送请求来验证“新鲜”的访问令牌。

    + ------------------------------------------------------------------------- + 
    | 1. 尝试检查令牌。                                                      |
    | 2. 完成检查令牌。                                                      |
    + ------------------------------------------------------------------------- + 
    |       issued_to:                  ************.apps.googleusercontent.com |
    |        audience:                  ************.apps.googleusercontent.com |
    |         user_id:                                             ************ |
    |      expires_in:                                                     3600 |
    |           email:                                     **********@gmail.com |
    |  verified_email:                                                        1 |
    |     access_type:                                                  offline |
    |         scopes::                                                          |
    + ------------------------------------------------------------------------- + 
    | https://www.googleapis.com/auth/userinfo.email                            |
    | https://www.googleapis.com/auth/userinfo.profile                          |
    | https://www.googleapis.com/auth/plus.me                                   |
    | https://www.googleapis.com/auth/drive                                     |
    + ------------------------------------------------------------------------- + 

但是,当我尝试访问驱动器源时,响应是:

调用GET https://www.googleapis.com/drive/v2/files 时出错 (401) 凭据无效
域名: 全局 原因: authError 消息: 凭据无效 位置类型: 头部 位置: 授权
我们在日历中也遇到了同样的问题。 所以:
  1. 令牌之前是有效的(一切正常)。
  2. 刷新令牌仍然有效。
  3. 请求反应为“凭据无效”错误。
  4. 所有其他令牌仍然很好地工作,这意味着代码是有效的。
通常当令牌被撤销时,“invalid_grant”错误会在尝试刷新令牌时返回。 问题
  1. 这种行为的原因是什么?如果刷新令牌被撤销或以其他方式无效,请求新访问令牌是否应该产生错误?
  2. 有没有办法验证刷新令牌?

1
在多次连续请求后,我遇到了相同的奇怪行为。 - ageorgios
13个回答

23

根据Google API文档中有关错误和错误代码的说明:

https://developers.google.com/drive/handle-errors#401_invalid_credentials

401: Invalid Credentials

Invalid authorization header. The access token you're using is either expired or invalid.

error: {
  errors: [
   {
  "domain": "global",
  "reason": "authError",
  "message": "Invalid Credentials",
  "locationType": "header",
  "location": "Authorization",
  }
  ],
  "code": 401,
  "message": "Invalid Credentials"
  }
}

这与您的错误版本完全匹配,很可能就是Google认为您请求有问题的原因。

但正如您所知,Google API请求可能会返回无法真正诊断问题的错误。我曾因为多种原因收到“无效凭据”错误提示。几乎总是因为我做了一些我认为不重要但实际上重要的更改。

我的第一个想法(纯属猜测)是前往Google API控制台:

https://code.google.com/apis/console

Google的身份验证令牌验证器(https://www.googleapis.com/oauth2/v1/tokeninfo)可以返回有效的响应,但客户端秘密或客户端ID可能已被更改。

响应主体中即使微小的更改也可能导致此错误。

我不知道您是通过REST调用还是客户端库发起请求,但我使用Ruby库,它允许使用命令行接口发起API调用。我发现这个库和OAuth2 Playground在诊断Google API调用方面非常有帮助。

只是提醒一下:我只收到过来自Google API的两个错误:“无效凭据”和“权限不足”。后者几乎总是与错误的范围有关。前者则涉及几乎所有其他问题。

我还想说,如果您在6个月内只遇到了2个错误,那么您很幸运!


1
谢谢回复。错误匹配,问题在于refresh_token仍然允许获取新的access_tokens,这也可以进行验证。我也遇到了同样的错误(_401 Invalid Credentials_)其他用户也有,但不同之处在于当请求新的access_token时,会发出_invalid_grant_错误。因此很容易说出令牌已过期或被撤销。 - Darth Flipman
2
当我尝试通过Google Plus登录时,我得到了一个access_token,但是当我使用该access_token获取用户信息时,它会给我返回401错误。如果我的凭据有误,那么我怎么能获得访问令牌?如果我有访问令牌,为什么它不给我任何结果呢?请帮帮我:( - Ajay Sharma

9

当我尝试在Google控制台更改重定向URL并更新服务器上的JSON凭据文件时,遇到了这个问题。在重新开始之前,我必须清除会话变量。因此,在您的项目中,只需执行此操作一次:

session_start(); //starts a session
session_unset(); //flushes out all the contents previously set

记得在测试运行一次后,删除session_unset()


4

我正在开发环境中。 我也遇到了这个问题。

首先,我尝试刷新凭据,但没有结果。然后我删除了我的应用程序(因为我仍在开发环境中,所以这是可以的,但是如果您已经在生产环境中使用,请小心此操作),创建了一个新的应用程序,更新了客户端的凭据JSON…… 仍然没有结果。

我通过在一个从未登录过我的Google帐户的新浏览器实例中打开来解决了这个问题(因为我使用的是Firefox浏览器的私密浏览),再次登录我的Google帐户,并尝试使用我的客户端(它是一个Web应用程序)。 我被重定向到授权屏幕,如预期的那样,之后,它对我而言正常工作。


如果这是一个与账户相关的问题,为什么更换浏览器后会起作用呢?(我现在也遇到了同样的问题) - gedamial
根据我的情况和检查其他人的回复,我不知道是否是与账户相关的问题,因为在更改会话后它可以工作。这对我有用,但我不太清楚到底出了什么问题。 - priki

4
也许这种行为是由于Google的限制造成的,描述如下:

每个用户帐户每个客户端最多只能有50个刷新令牌。如果达到了限制,创建新令牌会自动无警告地使最旧的令牌失效。服务帐户不受此限制。

每个用户帐户或服务帐户在所有客户端上拥有的令牌总数也有更大的限制。大多数普通用户不会超过此限制,但开发者的测试帐户可能会超过。


2
我最近遇到了这个奇怪的错误。我的解决方法是,在重定向到AuthUrl之前,我放置了一个函数来取消所有会话。

1
我遇到了与这个错误相同的问题:

The redirect URI in the request, does not match the ones authorized for the OAuth client.

但是我在这里找到了一个非常简单的解决方案,作者是abhishek77in:

https://coderwall.com/p/fmr5ag/avoid-invalid-credentials-with-google-oauth2

解决方案是:

如果您正在使用https://github.com/zquestz/omniauth-google-oauth2,请确保遵循README中的说明。"您必须通过Google API控制台启用“联系人API”和“Google+ API”。"

在Google API控制台中启用这些API可以为我解决“凭据无效”的问题。

1

userInfo: 凭证无效 我遇到了以下错误,因为我尝试访问的作用域数组元素,即从Google+ API作用域页面获取的profile和email链接,某种程度上是false/invalid,所以我去了我的同意屏幕,在Google APIs的范围下提到了email profile openID,在每个悬停时,我得到了它们各自的URL,将旧的URL替换为这些解决了我的错误。


1
清空 Google Chrome 中的存储空间对我有帮助(不知道“清空存储空间”在清除什么细节):
  1. F12 (Ctrl+Shift+I)
  2. 应用程序 选项卡
  3. 清空存储空间

0

当我需要将我的范围从只读更改为读写所有文件时,我遇到了同样的问题。因此,我将我的范围从文件顶部的只读更新为:

// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/sheets.googleapis.com-nodejs-quickstart.json
var SCOPES = ['https://www.googleapis.com/auth/drive'];

谷歌在其API指南中有这些注释,说每当您更改范围时,必须更新凭据。我相信这意味着,虽然我不确定,令牌必须更新。旧令牌仍由谷歌持有,并认为我只有只读访问权限,因此会返回401错误。因此,我需要重新制作我的令牌,但谷歌从未提供新的同意屏幕,允许我说允许读写所有文件。所以,我需要再次出现那个屏幕,这样它就会创建一个新的令牌来替换旧的令牌:

fs.readFile(TOKEN_PATH, function(err, token) {
    if (err) {
      getNewToken(oauth2Client, callback);
    } else {
        getNewToken(oauth2Client, callback);
    //   oauth2Client.credentials = JSON.parse(token);
    //   callback(oauth2Client);
    }
  });

由于我已经有了一个保存的令牌,所以它从未创建新的令牌。因此,我只是注释掉了旧令牌的使用,并告诉它获取新令牌,无论我们是否有令牌。然后,我去了我的Google连接应用程序并删除了我的旧连接凭据。我不确定这一步是否必要,但我只是想访问我的个人帐户。然后,当我运行程序时,它提示我重新进行身份验证,一切正常,我没有收到身份验证错误。完成后,请确保删除已经制作的令牌的注释行。我在所有这些方面都使用了Google API quickstart.js文件。

因此,当我更新我的范围时,旧令牌仍在使用只读范围,因此我会收到(401)无效凭据的错误。


0

当我取消了特定应用程序对我的Google帐户的访问权限时,我收到了(401) Invalid Credentials。所以我需要做的是再次请求授权URL(以https://accounts.google.com/o/oauth2/auth开头的那个URL)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接