我想从谷歌获取访问令牌。谷歌API说,要获得访问令牌,将代码和其他参数发送到令牌生成页面,响应将是一个JSON对象,如:

{
"access_token" : "ya29.AHES6ZTtm7SuokEB-RGtbBty9IIlNiP9-eNMMQKtXdMP3sfjL1Fc",
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : "1/HKSmLFXzqP0leUihZp2xUt3-5wkU7Gmu2Os_eBnzw74"
}

但是,我没有收到刷新令牌。我的回答是:

{
 "access_token" : "ya29.sddsdsdsdsds_h9v_nF0IR7XcwDK8XFB2EbvtxmgvB-4oZ8oU",
"token_type" : "Bearer",
"expires_in" : 3600
}

当前回答

为了在每次验证时获得新的refresh_token,在仪表板中创建的OAuth 2.0凭据类型应该是“Other”。同样如上所述,在生成authURL时应该使用access_type='offline'选项。

当使用类型为“Web application”的凭据时,prompt/approval_prompt变量的组合将不起作用——您仍然只能在第一个请求上获得refresh_token。

其他回答

为了在每次验证时获得新的refresh_token,在仪表板中创建的OAuth 2.0凭据类型应该是“Other”。同样如上所述,在生成authURL时应该使用access_type='offline'选项。

当使用类型为“Web application”的凭据时,prompt/approval_prompt变量的组合将不起作用——您仍然只能在第一个请求上获得refresh_token。

refresh_token仅在用户第一次授权时提供。后续的授权,比如您在测试OAuth2集成时所做的授权,将不会再次返回refresh_token。:)

进入可以访问您帐户的应用程序页面: https://myaccount.google.com/u/0/permissions。 在第三方应用程序菜单下,选择您的应用程序。 单击“删除访问”,然后单击“确定”确认 下一个OAuth2请求将返回一个refresh_token(前提是它还包括'access_type=offline'查询参数)。

或者,您可以将查询参数prompt=consent&access_type=offline添加到OAuth重定向(参见谷歌的OAuth 2.0 for Web服务器应用程序页面)。

这将提示用户再次授权应用程序,并总是返回一个refresh_token。

这给我带来了一些困惑,所以我想分享一下我艰难的经历:

当您使用access_type=offline和approval_prompt=force参数请求访问时,您应该收到一个访问令牌和一个刷新令牌。访问令牌在收到后不久就会过期,您需要刷新它。

您正确地发出了获取新访问令牌的请求,并收到了具有新访问令牌的响应。我还对没有获得新的刷新令牌感到困惑。然而,这就是它的意义所在,因为您可以反复使用相同的刷新令牌。

我认为其他一些答案假设您出于某种原因想要获得一个新的刷新令牌,并建议您重新授权用户,但实际上,您不需要这样做,因为您拥有的刷新令牌将一直工作,直到用户撤销。

在我意识到添加access_type=offline是在前端客户端对授权代码的请求上完成的,而不是在将该代码交换为access_token的后端请求上完成的之后,Rich Sutton的回答终于对我有用了。我给他的回答加上了一条评论,并在谷歌上添加了这个链接,以获取有关刷新令牌的更多信息。

注:如果你正在使用Satellizer,下面是如何将该选项添加到$authProvider。AngularJS中的谷歌。

为了获得刷新令牌,你必须同时添加approval_prompt=force和access_type="offline" 如果您正在使用谷歌提供的java客户端,它将看起来像这样:

GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
            HTTP_TRANSPORT, JSON_FACTORY, getClientSecrets(), scopes)
            .build();

AuthorizationCodeRequestUrl authorizationUrl =
            flow.newAuthorizationUrl().setRedirectUri(callBackUrl)
                    .setApprovalPrompt("force")
                    .setAccessType("offline");