问题
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