我想从谷歌获取访问令牌。谷歌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
}

当前回答

My solution was a bit weird..i tried every solution i found on internet and nothing. Surprisely this worked: delete the credentials.json, refresh, vinculate your app in your account again. The new credentials.json file will have the refresh token. Backup this file somewhere. Then keep using your app until the refresh token error comes again. Delete the crendetials.json file that now is only with an error message (this hapenned in my case), then paste you old credentials file in the folder, its done! Its been 1 week since ive done this and had no more problems.

其他回答

为了获得refresh_token,你需要在OAuth请求URL中包含access_type=offline。当一个用户第一次验证时,你会得到一个非空的refresh_token以及一个过期的access_token。

如果遇到这样的情况,用户可能会重新验证您已经拥有身份验证令牌的帐户(如上面提到的@SsjCosty),则需要从谷歌获取令牌用于哪个帐户的信息。要做到这一点,请将概要文件添加到作用域。使用OAuth2 Ruby宝石,你的最终请求可能看起来像这样:

client = OAuth2::Client.new(
  ENV["GOOGLE_CLIENT_ID"],
  ENV["GOOGLE_CLIENT_SECRET"],
  authorize_url: "https://accounts.google.com/o/oauth2/auth",
  token_url: "https://accounts.google.com/o/oauth2/token"
)

# Configure authorization url
client.authorize_url(
  scope: "https://www.googleapis.com/auth/analytics.readonly profile",
  redirect_uri: callback_url,
  access_type: "offline",
  prompt: "select_account"
)

注意,作用域有两个空格分隔的条目,一个用于对谷歌Analytics的只读访问,另一个仅用于配置文件,这是OpenID Connect标准。

这将导致谷歌在get_token响应中提供一个名为id_token的附加属性。要从id_token中获取信息,请查看谷歌文档中的此页面。有一些google提供的库可以为您验证和“解码”这些代码(我使用了Ruby google-id-token gem)。解析后,子参数实际上是唯一的谷歌帐户ID。

值得注意的是,如果您更改了作用域,对于已经使用原始作用域进行身份验证的用户,您将再次获得一个刷新令牌。这很有用,如果你已经有一群用户,不想让他们都在谷歌中取消应用程序的认证。

哦,最后一点注意:您不需要prompt=select_account,但如果您的用户可能想要使用多个谷歌帐户进行身份验证(即,您不使用此帐户进行登录/身份验证),则它很有用。

设置这个将导致刷新令牌每次都被发送:

$client->setApprovalPrompt('force');

下面给出一个例子(php):

$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
$client->addScope("email");
$client->addScope("profile"); 
$client->setAccessType('offline');
$client->setApprovalPrompt('force');

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。

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

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

我正在使用nodejs客户端访问私有数据

解决方案是在oAuth2Client的settings对象中添加值为consent的promp属性。generateAuthUrl函数。 这是我的代码:

const getNewToken = (oAuth2Client, callback) => {
    const authUrl = oAuth2Client.generateAuthUrl({
        access_type: 'offline',
        prompt: 'consent',
        scope: SCOPES,
    })
    console.log('Authorize this app by visiting this url:', authUrl)
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
    })
    rl.question('Enter the code from that page here: ', (code) => {
        rl.close()
        oAuth2Client.getToken(code, (err, token) => {
            if (err) return console.error('Error while trying to retrieve access token', err)
            oAuth2Client.setCredentials(token)
            // Store the token to disk for later program executions
            fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
                if (err) return console.error(err)
                console.log('Token stored to', TOKEN_PATH)
            })
            callback(oAuth2Client)
        })
    })
}

你可以使用在线参数提取器来获取生成令牌的代码:

在线参数提取器

以下是谷歌官方文档的完整代码:

https://developers.google.com/sheets/api/quickstart/nodejs

我希望这些信息对你有用