Google API Server-to-Server Communication not working (Ruby implementation)

混江龙づ霸主 提交于 2021-01-29 08:05:59

问题


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

This class returns me this hash

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

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

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

Any ideas what's missing here?


回答1:


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

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


来源:https://stackoverflow.com/questions/55129649/google-api-server-to-server-communication-not-working-ruby-implementation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!