Skip to main content
 首页 » 编程设计

google-api-ruby-client之Google 服务帐户授权()返回无效授权错误

2024年11月24日28unruledboy

我仔细阅读了 Steve Bazyl 在 https://www.youtube.com/watch?v=iK14bfd6qhs 上的演讲以及 google 上的相关 API 文档。我正在使用我的 gmail 帐户的服务帐户电子邮件 ID,并使用从控制台下载的私钥。

但是当我运行以史蒂夫在他的演示中展示的客户端为模型的测试客户端时,我始终得到

 Signet::AuthorizationError: 
   Authorization failed.  Server message: 
   { 
     "error" : "invalid_grant" 
   } 

如果我向传递给 JWTAsserter 的电子邮件或范围添加垃圾字母,我会收到相同的错误消息。显然出了点问题,但我似乎无法弄清楚如何解决这个问题。

这是我正在运行的客户端代码(在 rails rspec 文件中):

client = Google::APIClient.new 
 
key_file = '/Users/stu/projects/br/rails-app/######-privatekey.p12' 
key = Google::APIClient::KeyUtils.load_from_pkcs12(key_file, 'notasecret') 
Rails.logger.info "Private key? #{key.private?}" 
 
asserter = Google::APIClient::JWTAsserter.new(  
  '#####-#######knp@developer.gserviceaccount.com',  
  "https://www.googleapis.com/auth/calendar",  
  key) 
client.authorization = asserter.authorize() 

我很困惑,非常感谢任何故障排除建议。

谢谢!

更新

感谢 Jack 分享适合您的代码。

我已经转到我站点的开发控制台并创建了一个服务帐户客户端 p12 key 。然后我转到网站的管理控制台并添加我的客户端 ID,以授予对日历 API 的全站授权

在添加授权后的管理控制台中,它看起来像这样: XXXXXXXXXXXhnq.apps.googleusercontent.com 日历(读写)https://www.googleapis.com/auth/calendar

我下载了 p12 key 并在您提供的代码结构中使用了它。我还尝试了 Steve Bazyl 的演示文稿中的方法:

asserter = Google::APIClient::JWTAsserter.new(  
  "XXXXXXXXXXX-hnq@developer.gserviceaccount.com",  
  "https://www.googleapis.com/auth/calendar",  
  key) 
client.authorization = asserter.authorize("stu@XXXXXXXXXX.com") 

在这两种情况下,我得到的输出都和以前一样:

 Signet::AuthorizationError: 
   Authorization failed.  Server message: 
   { 
     "error" : "invalid_grant" 
   } 

如果我输入垃圾而不是“XXXXs://www.googleapis.com/auth/calendar”,我会得到相同的输出。 key 有效,虽然很明显我做错了什么,但我无法在 API 或谷歌中找到任何关于如何辨别它是什么的线索。

有什么解决方法吗?

请您参考如下方法:

您是否已授予服务帐户访问您的 Google Apps 帐户的权限?你可以在这里找到如何做到这一点:https://developers.google.com/+/domains/authentication/delegation#delegate_domain-wide_authority_to_your_service_account

以下代码适合我:

key = Google::APIClient::KeyUtils.load_from_pkcs12('tmp/##########-privatekey.p12', 'notasecret') 
client = Google::APIClient.new({:application_name => "example-app", :application_version => "1.0"}) 
client.authorization = Signet::OAuth2::Client.new( 
  :person => 'name@example.com', 
  :token_credential_uri => 'https://accounts.google.com/o/oauth2/token', 
  :audience => 'https://accounts.google.com/o/oauth2/token', 
  :scope => 'https://www.googleapis.com/auth/drive.readonly', 
  :issuer => '123456789@developer.gserviceaccount.com', 
  :signing_key => key) 
client.authorization.fetch_access_token! 
 
drive = client.discovered_api('drive', 'v2') 
result = client.execute(api_method: drive.files.list)