【问题标题】:Google OAuth returning invalid_grant Incorrect token typeGoogle OAuth 返回 invalid_grant 不正确的令牌类型
【发布时间】:2017-05-16 10:21:07
【问题描述】:

我使用 angularJS Oauth 模块 GAuth.checkAuth() 在我的应用程序的客户端登录中获得了有效代码。然后是 GAuth.getToken()。

该代码仅1小时有效,1小时后访问的任何API(如GoogleDocs,Gmail)都失败并需要重新登录。

为了克服这个问题,我尝试将代码发送到服务器以在服务器上获取 AccessCode,以便我可以将相同的请求发送到 GoogleDocs、Gmail 等

GoogleAuthorizationCodeTokenRequest req =
 new GoogleAuthorizationCodeTokenRequest(
  new NetHttpTransport(),
  JacksonFactory.getDefaultInstance(),
  "https://www.googleapis.com/oauth2/v4/token",
  // "https://accounts.google.com/o/oauth2/token",
  "901142925530-21ia7dqnsdsdsndnsnnnfdc9cm2u07.apps.googleusercontent.com",
  "6NSvw0efghyuuG8YGOBWPln79n",
  authCode,
  "http://localhost:8080");
req.setGrantType("authorization_code");
//req.put("refresh_token", authCode);
//req.put("access_type", "offline");
GoogleTokenResponse tokenResponse =
 req.execute();

tokenResponse.getAccessToken()

其中 authCode 是我在 GAuth Token 中收到的代码

但通话失败,我得到了回应

400 Bad Request
{
  "error" : "invalid_grant",
  "error_description" : "Incorrect token type."
}

非常感谢任何帮助!

【问题讨论】:

  • 为什么不在客户端使用刷新令牌?
  • 我正在阅读 API,它说刷新令牌在客户端不起作用。所以没有花太多时间探索它。在客户端使用它是否可行?可以告诉我步骤吗?

标签: java angularjs google-api google-oauth google-api-js-client


【解决方案1】:

当用户首次验证您的应用程序时,您将获得一个授权码。然后,您需要获取此授权代码并将其交换为访问令牌和刷新令牌。授权码一经使用就不能再使用了。

grant_type=authorization_code

表示您要求 Google 验证您的授权码并为您提供新的访问令牌和刷新令牌。

在我看来,您正在获取从该请求返回的访问令牌并将其发送到 grant_type=authorization_code 端点,该端点无法使用错误类型的代码。母鸡你得到的错误

400 Bad Request { "error" : "invalid_grant", "error_description" : "令牌类型不正确。" }

您将需要获取给定的刷新令牌。如果有的话,我不确定您是否可以从 AngularJs 获得刷新令牌。不过,你可以使用 java 获得一个。

在纯粹的休息中刷新访问令牌将如下所示

  https://accounts.google.com/o/oauth2/token
  client_id={ClientId}.apps.googleusercontent.com&client_secret={ClientSecret}&refresh_token=1/ffYmfI0sjR54Ft9oupubLzrJhD1hZS5tWQcyAvNECCA&grant_type=refresh_token

注意&grant_type=refresh_token。如果您使用的是 Google api java 客户端库,它应该会为您处理所有这些。但是,如果您尝试在 java 或 angularjs 中执行此操作,您的标记有点令人困惑,我不相信这会允许您使用刷新令牌。再说一次,我不是一个有角度的开发者,在这一点上我可能是错的。

回答者:

您发送的代码不是授权代码。只有授权码可以发送到 grant_type=authorization_code。解决方案:发送authorization_code

Google 代码和令牌的类型:

使用 Oauth2,您应该注意三种类型的代码或令牌。

  1. 授权码。
  2. 刷新令牌
  3. 访问令牌

当您请求用户访问并且他们授予您的应用程序访问权限时,您将获得一个Authorization code。授权码的寿命很短,可能不到 10 分钟,而且只能使用一次。

授权码用于从谷歌认证服务器获取初始访问令牌和刷新令牌。通过使用grant_type=authorization_code

访问令牌可以使用大约一个小时。它们用于调用 google APIs

https://www.googleapis.com/plus/v1/people/me?access_token={your access token}

假设您没有耗尽某些配额,您可以在该小时内尽可能频繁地使用访问令牌。

当您当前拥有的访问令牌已过期或您只是想要一个新的访问令牌时,刷新令牌用于从 Google 身份验证服务器请求一个新的访问令牌。这里grant_type=refresh_token 用于请求新的访问令牌,您实际上是在告诉谷歌我正在向您发送一个刷新令牌,您知道该怎么做。

补充阅读

我有一些教程可以帮助你解决 Google 3 Legged OAuth2 FlowGoogle Developer Console Oauth2 credentials

在学习 Oauth 时也很有帮助:The OAuth 2.0 Authorization Framework

【讨论】:

  • 谢谢!抱歉,但我的假设是,当我通过 JAPI/AngularJS 登录时,我会获得授权码并将其发送到服务器进行交换。您能否解释一下前两段中提到的访问令牌和授权码之间的区别。可能对我有帮助。所以基本上我正在使用 GAPI(和 AngularJS)在客户端进行身份验证,并尝试在服务器端获取访问代码以供重用。由于Ours是一个网络应用程序,发现它更可行。您是否建议在服务器端进行身份验证?
  • 我有一个教程解释了原始 HTTP 调用中的 oauth 流。 daimto.com/google-3-legged-oauth2-flow您应该在服务器端而不是客户端进行身份验证我不确定 Gapi 是否会给您一个可以使用的刷新令牌。
  • 再次感谢!但我有这个疑问。我们如何在服务器上进行身份验证?它与网络浏览器集成,请求直接发送到谷歌服务器。谷歌不会允许我们(或者即使可行也不会是明智的)将用户凭据存储在我们的服务器上。目前弹出一个新的谷歌窗口,在认证时我们在回调函数中获得访问代码。
  • 是的,然后你交换它并获得一个只能使用一个小时的访问令牌。然后,您将不得不要求用户再次对您进行身份验证。尝试用谷歌搜索刷新令牌和 gapi 我不是 javascript 程序员,所以无法真正提供帮助,尽管developers.google.com/api-client-library/javascript/help/… 我发现了这个
  • 注意:您需要每隔一小时询问用户访问权限,或者弄清楚如何获取刷新令牌。没有解决办法,这是您仅有的两个选择。您现在正在做的事情是行不通的,您只能使用一次授权代码,并且您不能使用访问令牌来请求新的访问令牌。您需要找到刷新令牌并刷新它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-27
  • 1970-01-01
  • 2015-02-09
  • 1970-01-01
  • 2013-04-09
  • 2014-07-23
  • 1970-01-01
相关资源
最近更新 更多