Google表格API v4 service_account - 禁止:来电者没有权限(Google :: Apis :: ClientError)

时间:2016-08-29 22:18:21

标签: ruby-on-rails google-oauth google-sheets-api google-api-ruby-client

Ruby:2.3.1

Rails:5.0.0

我需要通过Google表格API访问和更新我的私人Google表格。 最终,这应该由我的Rails应用程序中的重复后台作业完成。因此,我在Google云端控制台中设置了服务帐户。

但是要开始使用Google表格API,我创建了一个脚本:

require 'google/apis/sheets_v4'

ENV["GOOGLE_ACCOUNT_TYPE"] = 'service_account'
ENV["GOOGLE_CLIENT_EMAIL"] = '<client_email_from_downloaded_json_here>'
ENV["GOOGLE_PRIVATE_KEY"] = "<private_key_from_downloaded_json_here>"

SCOPE = Google::Apis::SheetsV4::AUTH_SPREADSHEETS

authorization = Google::Auth.get_application_default(SCOPE)

# Initialize the API
service = Google::Apis::SheetsV4::SheetsService.new
service.authorization = authorization

spreadsheet_id = '<MY SPREADSHEET ID HERE>'

sheet_name = 'Sheet1'

range = "#{sheet_name}!A2:B"

response = service.get_spreadsheet_values(spreadsheet_id, range)

puts 'No data found.' if response.values.empty?

response.values.each do |row|
  # Print columns A and B, which correspond to indices 0 and 1.
  puts "#{row[0]}, #{row[1]}"
end

当我运行该脚本时

$ rails runner -e development lib/scripts/google_sheets_api_demo.rb
/home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/google-api-client-0.9.12/lib/google/apis/core/http_command.rb:211:in `check_status': forbidden: The caller does not have permission (Google::Apis::ClientError)
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/google-api-client-0.9.12/lib/google/apis/core/api_command.rb:102:in `check_status'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/google-api-client-0.9.12/lib/google/apis/core/http_command.rb:179:in `process_response'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/google-api-client-0.9.12/lib/google/apis/core/http_command.rb:286:in `execute_once'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/google-api-client-0.9.12/lib/google/apis/core/http_command.rb:107:in `block (2 levels) in execute'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/retriable-2.1.0/lib/retriable.rb:54:in `block in retriable'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/retriable-2.1.0/lib/retriable.rb:48:in `times'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/retriable-2.1.0/lib/retriable.rb:48:in `retriable'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/google-api-client-0.9.12/lib/google/apis/core/http_command.rb:104:in `block in execute'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/retriable-2.1.0/lib/retriable.rb:54:in `block in retriable'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/retriable-2.1.0/lib/retriable.rb:48:in `times'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/retriable-2.1.0/lib/retriable.rb:48:in `retriable'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/google-api-client-0.9.12/lib/google/apis/core/http_command.rb:96:in `execute'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/google-api-client-0.9.12/lib/google/apis/core/base_service.rb:346:in `execute_or_queue_command'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/google-api-client-0.9.12/generated/google/apis/sheets_v4/service.rb:322:in `get_spreadsheet_values'
  from lib/scripts/google_sheets_api_demo.rb:35:in `<top (required)>'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/railties-5.0.0/lib/rails/commands/runner.rb:60:in `load'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/railties-5.0.0/lib/rails/commands/runner.rb:60:in `<top (required)>'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/railties-5.0.0/lib/rails/commands/commands_tasks.rb:138:in `require'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/railties-5.0.0/lib/rails/commands/commands_tasks.rb:138:in `require_command!'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/railties-5.0.0/lib/rails/commands/commands_tasks.rb:104:in `runner'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/railties-5.0.0/lib/rails/commands/commands_tasks.rb:49:in `run_command!'
  from /home/jignesh/.rvm/gems/ruby-2.3.1@my_integrations/gems/railties-5.0.0/lib/rails/commands.rb:18:in `<top (required)>'
  from bin/rails:9:in `require'
  from bin/rails:9:in `<main>'

如果我尝试访问公共工作表,它可以工作。我已经尝试了很多,但无法弄清楚导致这种情况的原因。最初我使用API​​ Key方法进行授权,但根据https://developers.google.com/api-client-library/ruby/auth/api-keys上的文档说明

  

调用不访问私有用户数据的API时,可以使用   简单的API密钥。这些密钥用于验证您的应用程序   用于会计目的。 Google Developers Console文档   还描述了API密钥。

     

注意:如果确实需要访问私人用户数据,则必须使用OAuth   2.0。请参阅将OAuth 2.0用于Web服务器应用程序,将OAuth 2.0用于已安装的应用程序,以及将OAuth 2.0用于服务器到服务器   申请更多信息。

因此我改用服务帐户方法。但它没有帮助。

任何人都可以让我知道我错过了什么?

其他调查结果:

以下帖子https://stackoverflow.com/a/38530755/936494看起来很有帮助,但根据我的要求,我想避免使用3-legged oauth,原因是应该通过后台作业访问和更新工作表。

1 个答案:

答案 0 :(得分:3)

这已经解决了。感谢Steve Bazyl (Google member)提供了以下有价值的建议,直接解决了问题:

  

您是否与服务帐户共享了表格?服务帐户实际上是单独的用户,需要在ACL上与任何其他用户相同。

参考:https://github.com/google/google-api-ruby-client/issues/461#issuecomment-243328234