Access Google Calendar API after setting up omniau

2019-09-04 04:41发布

问题:

I have a rails app that is using the gem 'omniauth-google-oauth2'. Everything is working so far. Now I am trying to pull a users calendar after they link their Google account.

I have followed several tutorials, but it seems that I am not able to pull the calendar information. All the tutorials used:

gem 'google-api-client', '~> 0.7.0', require: 'google/api_client'

Problem is, I've tried so many times for so long, I am confused as to what the problem could be.

Starting after setting up Omniauth, how do I pull Google Calendar information in my rails app?

回答1:

I finally got it to work.

I added :google_access_token, :google_refresh_token, and :google_expires_at to my user model. and used:

@user.google_access_token  = request.env["omniauth.auth"]["credentials"]["token"]
@user.google_refresh_token = request.env["omniauth.auth"]["credentials"]["refresh_token"]
@user.google_expires_at    = Time.at request.env["omniauth.auth"]["credentials"]["expires_at"]
@user.save

in my omniauth callbacks controller to store it and this to access it.

client = Google::APIClient.new(:auto_refresh_token => true)
client.authorization.access_token = current_user.google_access_token
client.authorization.refresh_token = current_user.google_refresh_token
client.authorization.client_id = ENV.fetch('google_id')
client.authorization.client_secret = ENV.fetch('google_secret')

if client.authorization.refresh_token && client.authorization.expired?
  client.authorization.fetch_access_token!
end

service = client.discovered_api('calendar' , 'v3')

response = client.execute(api_method: service.events.list,
        parameters: { 'calendarId' => 'primary' },
          headers: { 'Content-Type' => 'application/json' })

@items = response.data['items']


回答2:

I've been looking so hard for the correct solution to this using google-api-client version 0.9 and I was very grateful to run into Sophie's blog post with Josh' comment. Here's the quick recap of how I got it to work with their input:

require 'google/apis/calendar_v3'
require 'google/api_client/client_secrets.rb'

secrets = Google::APIClient::ClientSecrets.new(
  { "web" => 
    { "access_token" => "YOUR_ACCESS_TOKEN", 
      "refresh_token" => "YOUR_REFRESH_TOKEN", 
      "client_id" => "YOUR_CLIENT_ID", 
      "client_secret" => "YOUR_CLIENT_SECRET"
    }
  }
)
cal = Google::Apis::CalendarV3::CalendarService.new
cal.authorization = secrets.to_authorization
cal.authorization.refresh!

data = cal.list_calendar_lists

It might also help to read the migration to 0.9 manual to see how things have changed with this advent of this new gem version.



回答3:

Assuming user has authorized your application and you have the access token and refresh token stored and the access token has the scope to access the user' calendar.

  • First intialize the client and get a new access_token and specify the service you want to use and its version

    client=Google::APIClient.new(:auto_refresh_token => true)

    client.authorization.access_token = token

    client.authorization.refresh_token = refresh_token

    client.authorization.client_id = client_id

    client.authorization.client_secret = client_secret

    token = client.authorization.fetch_access_token["access_token"]

    service = client.discovered_api('calendar' , 'v3')

  • use the client object to invoke any api method, here I'm calling 'events.list' to get user events from the calendar

    response = client.execute(api_method: service.events.list, parameters: { 'calendarId' => 'primary' }, headers: { 'Content-Type' => 'application/json' })



回答4:

Could sby tell me, what's the difference between Sebhastien's and my solutions? (My code is not ready yet and don't know yet if I can get the new access_token with my solution.)

1.I just don't get it when and how I can get the new access token and if I need to deal with refresh_token and expires_at attributes.

2.How the (:auto_refresh_token => true) and fetch_access_token! exactly works?

client = Google::APIClient.new
#next 4 lines get the data from app/db
client.authorization.access_token = google_account.token
client.authorization.client_id = ENV['GOOGLE_API_KEY']
client.authorization.client_secret = ENV['GOOGLE_API_SECRET']
client.authorization.refresh_token = google_account.refresh_token

old_token = client.authorization.access_token
service = client.discovered_api('calendar', 'v3')
result = client.execute(
  :api_method => service.calendar_list.list,
  :parameters => {},
  :headers => {'Content-Type' => 'application/json'})

new_token = client.authorization.access_token
if old_token != new_token
  Social.update_attribute(token: new_token) #saving new token to db
end

@items = result.data['items']