如何使用 Google API 进行离线访问

Posted

技术标签:

【中文标题】如何使用 Google API 进行离线访问【英文标题】:How to get offline-access with Google APIs 【发布时间】:2017-09-19 15:39:15 【问题描述】:

我正在尝试使用 Google API 获取 offline access。我必须从 Google 日历中提取数据,而无需用户每次都登录。

我已将此添加到我的 Gemfile 中:

gem 'google-api-client', '~> 0.9'

...并将其添加到我的控制器中:

require 'google/api_client/client_secrets'
class Api::V1::CalendarAccountsController < Api::V1::BaseController
...

在我的行动中:

client_secrets = Google::APIClient::ClientSecrets.load(
  File.join(
    Rails.root,
    'config',
    'client_secrets.json')
  )

@auth_client = client_secrets.to_authorization

@auth_client.update!(
    :scope => 'https://www.googleapis.com/auth/calendar.readonly',
    :redirect_uri => '/callback URL',

    :additional_parameters => 
      "access_type" => "offline",
      "include_granted_scopes" => "true"
    
)
redirect_to @auth_client.authorization_uri.to_s

问题是 -- 即使我将 "access_type" 指定为 "offline",我仍然没有被问到获取 Google 权限列表中的离线访问权限(我在下面附上了屏幕截图)。

这是 Google 加载的页面(不能离线访问):

这是我调用@auth_client.authorization_uri.to_s时生成的网址

https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=[ID]&redirect_uri=[callback]&response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.readonly&from_login=1&as=-23788065e9c098d9&pli=1&authuser=0

我错过了什么吗?

【问题讨论】:

【参考方案1】:

你可以试试这样的:

client = Signet::OAuth2::Client.new(
  client_id: your_client_id,
  client_secret: your_secret_id,
  authorization_uri: 'https://accounts.google.com/o/oauth2/auth',
  scope: Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY,
  redirect_uri: your_callback_url
)

client.update!(
  additional_parameters: 
    access_type: 'offline',
    prompt: 'consent'
  
)

redirect_to client.authorization_uri.to_s

请注意,我使用的是更新版本的 google-api-client gem,配置方式如下:

gem 'google-api-client', '~> 0.11', require: 'google/apis/calendar_v3'

这样,Google 会要求您授予与日历 API 交互的权限,并正确设置 access_type 参数以授予您对相同 API 的离线访问权限。

这种方法会在您每次调用代码时提示用户授权。如果你想防止这种情况,你必须这样改变它:

client.update!(
  additional_parameters: 
    access_type: 'offline'
  
)

如果您已经在没有access_type: 'offline' 参数的情况下授权了您的应用,Google 将在没有离线许可的情况下授予您一个身份验证令牌。要重置这种情况,只需进入your Google profile permissions 并撤销对您的应用程序的先前授权即可。然后再试一次。

(注意:signet gem 是 googleauth 的依赖项,而 google-api-client 又是 google-api-client 的依赖项,因此您可以免费获得此代码,而无需向 Gemfile 添加更多 gem )

【讨论】:

【参考方案2】:

尝试添加此代码。如果您的应用需要离线访问 Google API,请将 API 客户端的访问类型设置为 offline:

auth_client.update!(
  :additional_parameters => "access_type" => "offline"
)

在用户授予对所请求范围的离线访问权限后,您可以在用户离线时继续使用 API 客户端代表用户访问 Google API。客户端对象将根据需要刷新访问令牌。

还可以使用 Google 客户端库,这将帮助您刷新访问令牌(离线访问)。

希望这会有所帮助。

【讨论】:

谢谢@Mr.Rebot -- 我已经添加了access_type 参数,但我仍然没有在谷歌的登录权限页面上得到离线访问提示(它只是要求read-only access to calendars),我也没有在回复中得到refresh_token

以上是关于如何使用 Google API 进行离线访问的主要内容,如果未能解决你的问题,请参考以下文章

如何长时间访问(离线)Google API?

如何让服务器访问Google Calendar API?

Google 刷新访问令牌(离线访问)api 中的“unsupported_grant_type”

Google API:如何增加访问令牌到期日期?

我如何使Figma API与Google App脚本API一起使用?

Google Api Php 客户端的刷新令牌