无法在Rails应用中刷新Google API令牌

时间:2018-08-10 20:30:08

标签: ruby-on-rails google-calendar-api

我正在尝试在我的Rails(5.2.1)应用程序中使用Google Calendar API,但是在刷新令牌方面确实遇到了麻烦-我对它的理解充其量是微不足道的,即使经过了很多时间也是如此文档。

这是我的代码:

          class CalendarsController < ApplicationController

              def authorize
                client = Signet::OAuth2::Client.new(client_options)
                redirect_to client.authorization_uri.to_s
              end

              def callback
                client = Signet::OAuth2::Client.new(client_options)
                client.code = params[:code]

                response = client.fetch_access_token!

                session[:authorization] = response

                redirect_to root_url
              end

              def get_calendars
                client = Signet::OAuth2::Client.new(client_options)
                client.update!(session[:authorization])
                client.update!(
  additional_parameters: {
    access_type: 'offline',
    prompt: 'consent'
  }
)
                service = Google::Apis::CalendarV3::CalendarService.new
                service.authorization = client
                # here is my attempt to refresh
                begin
                  service.list_calendar_lists
                    rescue Google::Apis::AuthorizationError
                      response = client.refresh!
                      session[:authorization] = session[:authorization].merge(response)
                      retry
                end
              end

              def new
                all_calendars = get_calendars.items
                @calendar_list = all_calendars.select {|calendar| calendar.access_role=="owner"}
           end

          def client_options
            {
              client_id: Rails.application.credentials.web[:client_id],
              client_secret: Rails.application.credentials.web[:client_secret],
              authorization_uri: 'https://accounts.google.com/o/oauth2/auth?access_type=offline&prompt=consent',
              token_credential_uri: 'https://accounts.google.com/o/oauth2/token',
              scope: Google::Apis::CalendarV3::AUTH_CALENDAR,
              redirect_uri: callback_url
            }
          end
    end

如果我转到指向#authorize的URL,我将被定向到OAuth屏幕,并要求获得访问我的日历的权限。获得批准后,该应用程序将按预期运行。一个小时后,令牌到期,我无法刷新它。您可以在上面看到我的尝试:如果没有尝试,我将得到一个Google::Apis::AuthorizationError。有了它,我得到“缺少授权码”。我完全迷路了,在阅读文档时遇到了麻烦。

1 个答案:

答案 0 :(得分:1)

文档非常具有挑战性,并且错误消息没有多大帮助!

您没有显示正在传递的client_options,并且由于其他所有内容看起来都是正确的-我猜这是问题所在。您是否设置了access_type参数以进行脱机访问,以便实际上可以刷新令牌而无需用户重新进行身份验证?

来自documentation

  

如果您的应用程序需要刷新访问权限,则将该值设置为offline   用户不在浏览器中时标记。这是方法   本文档后面部分将介绍的刷新访问令牌的过程。这个   值指示Google授权服务器返回刷新   令牌和访问令牌在您的应用程序首次出现时   交换令牌的授权码。

您可以在authorization_uri中进行此操作。例如:

client = Signet::OAuth2::Client.new({
  client_id: ...,
  client_secret: ...,
  authorization_uri: "https://accounts.google.com/o/oauth2/auth?access_type=offline&prompt=consent",
  scope: Google::Apis::CalendarV3::AUTH_CALENDAR,
  redirect_uri: callback_url
})

或者在致电update!时:

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