invalid_grant尝试从谷歌获得oAuth令牌

我不断尝试从Google获取oAuth令牌以连接到他们的联系人API时发生invalid_grant错误。 所有的信息是正确的,我有tripple检查这种如此难倒。

有谁知道可能是什么原因造成这个问题? 我曾尝试设置一个不同的客户端ID,但我得到了相同的结果,我试图连接许多不同的方式,包括尝试强制authentication,但仍然是相同的结果。

我遇到这个问题时,当我没有明确要求“脱机”访问时,将用户发送到OAuth“你想给这个应用程序权限触摸你的东西? 页。

确保在请求中指定access_type = offline。

详情请参阅: https : //developers.google.com/accounts/docs/OAuth2WebServer#offline

(另外:我认为谷歌在2011年底join了这个限制。如果你之前有旧的代币,你需要把你的用户发送到权限页面授权离线使用。)

我遇到了同样的问题,尽pipe根据bonkydog的回答在我的请求中指定了“offline” access_type 。 长话短说我发现这里描述的解决scheme为我工作:

https://groups.google.com/forum/#!topic/google-analytics-data-export-api/4uNaJtquxCs

实质上,当您在Google API控制台中添加OAuth2客户端时,Google会为您提供“客户端ID”和“电子邮件地址”(假设您select“webapp”作为您的客户端types)。 尽pipeGoogle误导了命名约定,但他们希望您在访问其OAuth2 API时将“电子邮件地址”作为client_id参数的值发送。

这在调用这两个URL时适用:

请注意,如果您使用“客户ID”而不是“电子邮件地址”调用第一个URL,则调用将会成功 。 但是,尝试从第二个URL获取不记名标记时,使用从该请求返回的代码将不起作用。 相反,你会得到一个“错误400”和“invalid_grant”消息。

虽然这是一个老问题,但似乎很多人仍然遇到了这个问题 – 我们花了好几天的时间来终止自己。

在OAuth2规范中,“invalid_grant”对于与无效/过期/撤销令牌(auth grant或refresh token)有关的所有错误都是一个全面的方法。

对我们来说,这个问题是双重的:

  1. 用户已经主动撤销对我们的应用程序的访问
    有道理,但得到这个:撤销12小时后, 谷歌停止发送错误消息的响应: “error_description” : “Token has been revoked.”
    这是相当具有误导性的,因为你会认为错误信息在任何时候都存在,而事实并非如此。 您可以检查您的应用程序是否仍然可以在应用程序权限页面上访问。

  2. 用户已重置/恢复其Google密码
    2015年12月, Google更改了其默认行为,以便非Google Apps用户重置密码会自动撤消所有用户的应用刷新标记。 在撤销时,错误消息遵循与之前相同的规则,所以你只能在头12个小时内得到“error_description”。 似乎没有任何方法可以知道用户手动撤销了访问(意图)还是因密码重置(副作用)而发生的。

除此之外,还有其他很多可能导致错误的潜在原因:

  1. 服务器时钟/时间不同步
  2. 未经授权可以离线访问
  3. 由Google限制
  4. 使用过期的刷新令牌
  5. 用户已停用6个月
  6. 使用服务人员电子邮件而不是客户端ID
  7. 在短时间内访问令牌太多
  8. 客户端SDK可能已过时
  9. 不正确/不完整的刷新标记

我写了一篇简短的文章总结每个项目的一些debugging指导,以帮助find罪魁祸首。 希望能帮助到你。

我遇到了同样的问题。 对于我,我通过使用电子邮件地址(以@ developer.gserviceaccount.com结尾的string)代替client_id参数值的客户端ID来解决此问题。 Google设定的命名令人困惑。

我有同样的错误消息'invalid_grant',这是因为从客户端JavaScript发送的authResult ['code']在服务器上没有正确接收。

尝试从服务器输出它,看看它是否正确,而不是一个空string。

我的问题是,我用这个url:

 https://accounts.google.com/o/oauth2/token 

当我应该使用这个URL:

 https://www.googleapis.com/oauth2/v4/token 

这是testing一个服务帐户,要求离线访问存储引擎 。

如果你正在使用抄写库,只需设置离线模式,就像这里提供的bonkydog是代码:

 OAuthService service = new ServiceBuilder().provider(Google2Api.class).apiKey(clientId).apiSecret(apiSecret) .callback(callbackUrl).scope(SCOPE).offline(true) .build(); 

https://github.com/codolutions/scribe-java/

在这个网站console.developers.google.com

这个控制台板select你的项目input宣誓的url。 当oauth成功时,oauthcallbackurl会redirect

使用Android clientId(无client_secret)我得到以下错误响应:

 { "error": "invalid_grant", "error_description": "Missing code verifier." } 

我找不到字段“code_verifier”的任何文档,但是我发现如果您在授权和令牌请求中将其设置为相等的值,则会删除此错误。 我不确定预期的价值应该是什么,或者应该是安全的。 它有一些最小长度(16个字符),但我发现设置为null也可以。

我正在使用AppAuth在我的Android客户端中具有setCodeVerifier()函数的授权请求。

 AuthorizationRequest authRequest = new AuthorizationRequest.Builder( serviceConfiguration, provider.getClientId(), ResponseTypeValues.CODE, provider.getRedirectUri() ) .setScope(provider.getScope()) .setCodeVerifier(null) .build(); 

以下是节点中的示例标记请求:

 request.post( 'https://www.googleapis.com/oauth2/v4/token', { form: { 'code': '4/xxxxxxxxxxxxxxxxxxxx', 'code_verifier': null, 'client_id': 'xxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com', 'client_secret': null, 'redirect_uri': 'com.domain.app:/oauth2redirect', 'grant_type': 'authorization_code' } }, function (error, response, body) { if (!error && response.statusCode == 200) { console.log('Success!'); } else { console.log(response.statusCode + ' ' + error); } console.log(body); } ); 

我testing过,并且可以与https://www.googleapis.com/oauth2/v4/tokenhttps://accounts.google.com/o/oauth2/token

如果您使用GoogleAuthorizationCodeTokenRequest改为:

 final GoogleAuthorizationCodeTokenRequest req = new GoogleAuthorizationCodeTokenRequest( TRANSPORT, JSON_FACTORY, getClientId(), getClientSecret(), code, redirectUrl ); req.set("code_verifier", null); GoogleTokenResponse response = req.execute(); 

这是一个愚蠢的答案,但我的问题是,我没有意识到我已经发出了我的谷歌用户,我没有存储一个积极的oAuth令牌。 在这种情况下,解决scheme是转到api控制台并重置客户端密钥。

有很多其他的答案,例如重置客户端秘密OAuth2 – 客户端是否需要重新授予访问权限?

您可能需要删除陈旧/无效的OAuth响应。

信用: node.js谷歌oauth2示例停止工作invalid_grant

注意 :如果初始授权中使用的密码已更改,则OAuth响应也将失效。

如果在bash环境中,可以使用以下命令来删除陈旧的响应:

rm /Users/<username>/.credentials/<authorization.json>

在考虑和尝试所有其他的方法之后,下面是我在nodejs中用googleapis模块和request模块(我用来取代所提供的getToken()方法获取令牌)来解决问题:

 const request = require('request'); //SETUP GOOGLE AUTH var google = require('googleapis'); const oAuthConfigs = rootRequire('config/oAuthConfig') const googleOAuthConfigs = oAuthConfigs.google //for google OAuth: https://github.com/google/google-api-nodejs-client var OAuth2 = google.auth.OAuth2; var googleOAuth2Client = new OAuth2( process.env.GOOGLE_OAUTH_CLIENT_ID || googleOAuthConfigs.clientId, process.env.GOOGLE_OAUTH_CLIENT_SECRET || googleOAuthConfigs.clientSecret, process.env.GOOGLE_OAUTH_CLIENT_REDIRECT_URL || googleOAuthConfigs.callbackUrl); /* generate a url that asks permissions for Google+ and Google Calendar scopes https://developers.google.com/identity/protocols/googlescopes#monitoringv3*/ var googleOAuth2ClientScopes = [ 'https://www.googleapis.com/auth/plus.me', 'https://www.googleapis.com/auth/userinfo.email' ]; var googleOAuth2ClientRedirectURL = process.env.GOOGLE_OAUTH_CLIENT_REDIRECT_URL || googleOAuthConfigs.callbackUrl; var googleOAuth2ClientAuthUrl = googleOAuth2Client.generateAuthUrl({ access_type: 'offline', // 'online' (default) or 'offline' (gets refresh_token) scope: googleOAuth2ClientScopes // If you only need one scope you can pass it as string }); //AFTER SETUP, THE FOLLOWING IS FOR OBTAINING TOKENS FROM THE AUTHCODE const ci = process.env.GOOGLE_OAUTH_CLIENT_ID || googleOAuthConfigs.clientId const cs = process.env.GOOGLE_OAUTH_CLIENT_SECRET || googleOAuthConfigs.clientSecret const ru = process.env.GOOGLE_OAUTH_CLIENT_REDIRECT_URL || googleOAuthConfigs.callbackUrl var oauth2Client = new OAuth2(ci, cs, ru); var hostUrl = "https://www.googleapis.com"; hostUrl += '/oauth2/v4/token?code=' + authCode + '&client_id=' + ci + '&client_secret=' + cs + '&redirect_uri=' + ru + '&grant_type=authorization_code', request.post({url: hostUrl}, function optionalCallback(err, httpResponse, data) { // Now tokens contains an access_token and an optional refresh_token. Save them. if(!err) { //SUCCESS! We got the tokens const tokens = JSON.parse(data) oauth2Client.setCredentials(tokens); //AUTHENTICATED PROCEED AS DESIRED. googlePlus.people.get({ userId: 'me', auth: oauth2Client }, function(err, response) { // handle err and response if(!err) { res.status(200).json(response); } else { console.error("/google/exchange 1", err.message); handleError(res, err.message, "Failed to retrieve google person"); } }); } else { console.log("/google/exchange 2", err.message); handleError(res, err.message, "Failed to get access tokens", err.code); } }); 

我简单地使用request来通过HTTP进行api请求,如下所述: https : //developers.google.com/identity/protocols/OAuth2WebServer#offline

 POST /oauth2/v4/token HTTP/1.1 Host: www.googleapis.com Content-Type: application/x-www-form-urlencoded code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7& client_id=8819981768.apps.googleusercontent.com& client_secret={client_secret}& redirect_uri=https://oauth2.example.com/code& grant_type=authorization_code 

尝试更改您的url为要求

 https://www.googleapis.com/oauth2/v4/token 

刷新令牌和访问令牌的POST请求之前,您必须注意invalid_grant错误的两个主要原因。

  1. 请求头必须包含“content-type:application / x-www-form-urlencoded”
  2. 你的请求负载应该是URL编码的Form Data,不要作为json对象发送。

RFC 6749 OAuth 2.0将invalid_grant定义为: 提供的授权许可(例如,授权代码,资源所有者凭据)或刷新令牌无效,过期,撤销,与授权请求中使用的redirectURI不匹配,或者已颁发给另一客户端。

我发现了另一篇好文章, 在这里你会发现这个错误的其他许多原因。

https://blog.timekit.io/google-oauth-invalid-grant-nightmare-and-how-to-fix-it-9f4efaf1da35