1
votes

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/[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> 
1
I think you are not impersonating any user, specifically for this scenario, the admin. Check this documentation, the user you want to impersonate is set in the parameter 'sub': developers.google.com/api-client-library/ruby/auth/… - Gerardo
I actually thought of that and added this: auth_client = authorization.dup auth_client.sub = '[email protected]' service = Google::Apis::AdminDirectoryV1::DirectoryService.new response = service.list_groups(user_key: '[email protected]', domain: 'mydomain.com') and that throws this error: "Requested client not authorized." Any ideas? - Rusty Ross
i'm wondering if this line is correct: service.list_groups(user_key: '[email protected], domain: "mydomain.com") ... after the [email protected] the quotation is not closed - Gerardo

1 Answers

0
votes

You're missing a call to authorization.fetch_access_token! before calling the service as described in the API client docs.