Google API服务器到服务器的通信不起作用(Ruby实现)

问题描述:

我已按照所有步骤设置了域范围的授权( https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority ),我最终在Ruby中创建了此类.>

I have followed all the steps to set up a Domain-Wide Delegation of Authority (https://developers.google.com/admin-sdk/reports/v1/guides/delegation) and followed this link too (https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority) and I ended up creating this class in Ruby.

class Gsuite::ServiceAccount

def initialize(person: nil)
end 

def authorized_client
      Google::Auth::ServiceAccountCredentials.make_creds(
    authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
      json_key_io: StringIO.new(File.read AppConfig[:gsuite_service_account] 
 [:credentials_file]),
      scope: AppConfig[:gsuite_service_account][:scope])
    client = authorizer.fetch_access_token!
  end
end

此类向我返回此哈希

{"access_token"=>"a_long_token_string_here", "expires_in"=>3600, "token_type"=>"Bearer"}

然后,我已经在Admin类中创建了此方法以连接到Gmail服务

Then, I've created this method (within my Admin class) to connect to Gmail Service

def gsuite_client_access
    @client ||= Gsuite::ServiceAccount.new(person: self.email.to_s).authorized_client
    authorized_client = Google::Apis::GmailV1::GmailService.new
    authorized_client.authorization = @client
    authorized_client
  end

因此,当我尝试在代码的另一部分中用此行列出我的Gmail邮件时

So, when I try to list my Gmail Messages with this line in another part of the code

inbox = current_admin.gsuite_client_access.list_user_messages('me', max_results: 10)

我收到以下错误消息=>

I get the following error message =>

Sending HTTP get https://www.googleapis.com/gmail/v1/users/me/messages?maxResults=10
401
#<Hurley::Response GET https://www.googleapis.com/gmail/v1/users/me/messages?maxResults=10 == 401 (238 bytes) 645ms>
Caught error Unauthorized
Error - #<Google::Apis::AuthorizationError: Unauthorized>

Retrying after authentication failure
Google::Apis::AuthorizationError: Unauthorized

有什么想法吗?

最后,我开始使用它了.事实证明,您需要使用此行对模拟用户"使用子方法才能进行连接.

Finally, I got it working. Turns out, you need to use this line to use the sub method to the "impersonated user" to be able to connect.

authorizer.sub = @person

而且,令您高兴的是,这是用于阅读Gmail邮件的更新的测试代码,以便您在有需要的时候使用.只需记住将credits.json文件保存在项目文件夹中以使其正常工作,并使用与在GSuite仪表板中添加的作用域相同的作用域即可.

And, for your delight, here is the updated test code for reading Gmail messages so you can follow in case you want to use it. Just remember to save the credentials.json file in your project folder to make it work and use the same scope you added in the GSuite Dashboard.

class Gsuite::ServiceAccount

  def initialize(person: nil)
    @person = person
  end

  def read_messages
    client = service_account_access
    inbox = client.list_user_messages(@person, max_results: 5, label_ids: "INBOX" )
    if inbox.result_size_estimate.nonzero?
      inbox.messages.each do |message|
        response = client.get_user_message(@person, message.id)
      end
    end
  end

private

  def service_account_access
    token = authorized_client
    client = Signet::OAuth2::Client.new(access_token: token['access_token'])
    client.expires_in = Time.current + token["expires_in"]
    auth_client = Google::Apis::GmailV1::GmailService.new
    auth_client.authorization = client
    auth_client
  end

  def authorized_client
    authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
      json_key_io: StringIO.new(File.read AppConfig[:credentials_file]),
      scope: AppConfig[:gsuite_scope]).dup
    authorizer.sub = @person
    authorizer.fetch_access_token!
  end
end