Google-api-ruby-client: problem with authorization

Created on 20 Jan 2016  路  5Comments  路  Source: googleapis/google-api-ruby-client

Admittedly, this is probably not an issue specifically with the ruby client, but I am having it with the ruby client and am not sure where else to ask:

I am trying to write a server process that calls the Google Directory Admin API to determine groups memberships for a given user in my domain.

With the following scope...
https://www.googleapis.com/auth/admin.directory.group.readonly

...this call works (returns a 200) in the API Playground:
GET /admin/directory/v1/groups?userKey=my.[email protected] HTTP/1.1

However, I am unable to get authorization right outside of the playground.

I have done the following:

(1) Added "Admin SDK" to the "Enabled APIs" in Google Developers Console

(2) Created a "service account" for my app in Google Developers Console

(3) Checked "Enable Google Apps Domain-wide Delegation" for this service account

(4) Checked "Furnish a new private key" for this service account

(5) Downloaded the JSON credentials for this service account

(6) In "admin.google.com" --> Security --> Advanced Settings --> Authentication --> Manage API client access, I have added entered the (numeric) ClientID for my service account in the "Client Name" field, and entered the following scope in the "One or More API Scopes" field and pressed authorize: https://www.googleapis.com/auth/admin.directory.group.readonly

However, with the following Ruby code, authorization fails (Google::Apis::ClientError: forbidden: Not Authorized to access this resource/api):

require 'google/apis/admin_directory_v1'
require 'googleauth'
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = 'secrets.json'
scope = [ 'https://www.googleapis.com/auth/admin.directory.group.readonly' ]
authorization = Google::Auth.get_application_default(scope)
service = Google::Apis::AdminDirectoryV1::DirectoryService.new
service.authorization = authorization
response = service.list_groups(user_key: '[email protected], domain: "mydomain.com")

(irb session pasted below)

Note that the user and domain have been changed here for redaction purposes. Also note that additionally, if domain is not supplied, Google::Apis::ClientError: notFound: Domain not found. is thrown.

irb session is as follows:

irb(main):001:0> require 'google/apis/admin_directory_v1'
=> true
irb(main):002:0> require 'googleauth'
=> false
irb(main):003:0> ENV['GOOGLE_APPLICATION_CREDENTIALS'] = 'secrets.json'
=> "secrets.json"
irb(main):004:0> scope = [ 'https://www.googleapis.com/auth/admin.directory.group.readonly' ]
=> ["https://www.googleapis.com/auth/admin.directory.group.readonly"]
irb(main):005:0>  authorization = Google::Auth.get_application_default(scope)
=> #<Google::Auth::ServiceAccountCredentials:0x0000000238b1a0 @authorization_uri=nil, @token_credential_uri=#<Addressable::URI:0x11c55ec URI:https://www.googleapis.com/oauth2/v3/token>, @client_id=nil, @client_secret=nil, @code=nil, @expires_at=nil, @expires_in=nil, @issued_at=nil, @issuer="[email protected]", @password=nil, @principal=nil, @redirect_uri=nil, @scope=["https://www.googleapis.com/auth/admin.directory.group.readonly"], @state=nil, @username=nil, @expiry=60, @audience="https://www.googleapis.com/oauth2/v3/token", @signing_key=#<OpenSSL::PKey::RSA:0x0000000238b218>, @extension_parameters={}, @additional_parameters={}>
irb(main):006:0> service = Google::Apis::AdminDirectoryV1::DirectoryService.new
=> #<Google::Apis::AdminDirectoryV1::DirectoryService:0x000000023dbdd0 @root_url="https://www.googleapis.com/", @base_path="admin/directory/v1/", @upload_path="upload/admin/directory/v1/", @batch_path="batch", @client_options=#<struct Google::Apis::ClientOptions application_name="unknown", application_version="0.0.0", proxy_url=nil, use_net_http=false>, @request_options=#<struct Google::Apis::RequestOptions authorization=nil, retries=0, header=nil, timeout_sec=nil, open_timeout_sec=20>>
irb(main):007:0> service.authorization = authorization
=> #<Google::Auth::ServiceAccountCredentials:0x0000000238b1a0 @authorization_uri=nil, @token_credential_uri=#<Addressable::URI:0x11c55ec URI:https://www.googleapis.com/oauth2/v3/token>, @client_id=nil, @client_secret=nil, @code=nil, @expires_at=nil, @expires_in=nil, @issued_at=nil, @issuer="[email protected]", @password=nil, @principal=nil, @redirect_uri=nil, @scope=["https://www.googleapis.com/auth/admin.directory.group.readonly"], @state=nil, @username=nil, @expiry=60, @audience="https://www.googleapis.com/oauth2/v3/token", @signing_key=#<OpenSSL::PKey::RSA:0x0000000238b218>, @extension_parameters={}, @additional_parameters={}>
irb(main):008:0> response = service.list_groups(user_key: '[email protected], domain: "mydomain.com")
Google::Apis::ClientError: forbidden: Not Authorized to access this resource/api
    from /usr/local/share/ruby/gems/2.0/gems/google-api-client-0.9/lib/google/apis/core/http_command.rb:202:in `check_status'
    from /usr/local/share/ruby/gems/2.0/gems/google-api-client-0.9/lib/google/apis/core/api_command.rb:103:in `check_status'
    from /usr/local/share/ruby/gems/2.0/gems/google-api-client-0.9/lib/google/apis/core/http_command.rb:170:in `process_response'
    from /usr/local/share/ruby/gems/2.0/gems/google-api-client-0.9/lib/google/apis/core/http_command.rb:275:in `execute_once'
    from /usr/local/share/ruby/gems/2.0/gems/google-api-client-0.9/lib/google/apis/core/http_command.rb:107:in `block (2 levels) in execute'
    from /usr/local/share/ruby/gems/2.0/gems/retriable-2.1.0/lib/retriable.rb:54:in `block in retriable'
    from /usr/local/share/ruby/gems/2.0/gems/retriable-2.1.0/lib/retriable.rb:48:in `times'
    from /usr/local/share/ruby/gems/2.0/gems/retriable-2.1.0/lib/retriable.rb:48:in `retriable'
    from /usr/local/share/ruby/gems/2.0/gems/google-api-client-0.9/lib/google/apis/core/http_command.rb:104:in `block in execute'
    from /usr/local/share/ruby/gems/2.0/gems/retriable-2.1.0/lib/retriable.rb:54:in `block in retriable'
    from /usr/local/share/ruby/gems/2.0/gems/retriable-2.1.0/lib/retriable.rb:48:in `times'
    from /usr/local/share/ruby/gems/2.0/gems/retriable-2.1.0/lib/retriable.rb:48:in `retriable'
    from /usr/local/share/ruby/gems/2.0/gems/google-api-client-0.9/lib/google/apis/core/http_command.rb:96:in `execute'
    from /usr/local/share/ruby/gems/2.0/gems/google-api-client-0.9/lib/google/apis/core/base_service.rb:267:in `execute_or_queue_command'
    from /usr/local/share/ruby/gems/2.0/gems/google-api-client-0.9/generated/google/apis/admin_directory_v1/service.rb:943:in `list_groups'
    from (irb):8
    from /usr/bin/irb:12:in `<main>'irb(main):009:0> 
triage me

Most helpful comment

I think the issue is you're not actually running as a user on that domain. You're using the the service account identity. To actually impersonate a user (the domain-wide delegation part) you need to set the 'sub' attribute on the credentials to the email address of the user you want to impersonate.

Changing the auth code to be something like:

authorization = Google::Auth.get_application_default(scope).dup
authorization.sub = '<email of admin>'

should fix the problem.

All 5 comments

I think the issue is you're not actually running as a user on that domain. You're using the the service account identity. To actually impersonate a user (the domain-wide delegation part) you need to set the 'sub' attribute on the credentials to the email address of the user you want to impersonate.

Changing the auth code to be something like:

authorization = Google::Auth.get_application_default(scope).dup
authorization.sub = '<email of admin>'

should fix the problem.

Re-open if still having issues.

This solved my problem during my upgrade from .8 to .9 - thanks!

I have exactly the same problem. Everything works from Google API - API Explorer. But not by Ruby script. Do you have any idea why?

Best,
Rafal

authorization = Google::Auth.get_application_default(scope).dup
authorization.sub = '<email of admin>'

Where is this "sub" option documented? This option solves the problem to use a service account with wide delegation to search through all the Drives of the given domain but is the first time that I see it.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jponc picture jponc  路  5Comments

a14m picture a14m  路  7Comments

martincalvert picture martincalvert  路  4Comments

brandonhilkert picture brandonhilkert  路  6Comments

gregology picture gregology  路  5Comments