1

When I try to make a call to the Google Directory API using Server to Server authentication, I get the error message "Not Authorized to access this resource/api".

What I did:

  1. Created an App in the Google Developers Console.
  2. Downloaded the private key and looked up the service account name.
  3. Activated the Admin SDK under APIs.
  4. Downloaded the google-api-php-client.
  5. Wrote the following code:

$serviceAccountName = 'XXXXXXXXXXX@developer.gserviceaccount.com';
$scopes = 'https://www.googleapis.com/auth/admin.directory.group';
$privateKeyFile = dirname(__FILE__).'/../certs/googleapi-privatekey.p12';

$client = new Google_Client();
$client->setApplicationName('API Project');
$client->setScopes($scopes);
$cred = new Google_Auth_AssertionCredentials($serviceAccountName, $scopes, file_get_contents($privateKeyFile));
$client->setAssertionCredentials($cred);
$client->getAuth()->refreshTokenWithAssertion();

$req = new Google_Http_Request("https://www.googleapis.com/admin/directory/v1/groups/group-id@example.com/members?maxResults=1000");

$val = $client->getAuth()->authenticatedRequest($req);

var_dump($client->getAuth()->getAccessToken());
var_dump($val->getResponseBody());
  1. Executing that small script yields a valid access token, valid for an hour and the following error message:

{ "error": { "errors": [ { "domain": "global", "reason": "forbidden", "message": "Not Authorized to access this resource/api" } ], "code": 403, "message": "Not Authorized to access this resource/api" } }

I get the same error when I try to do the same request on the Google OAuth playground with the access key from my PHP script. Do I have to activate access to the group data for that service account somewhere in the Developers Console?

Raptor
  • 53,206
  • 45
  • 230
  • 366
user3482779
  • 15
  • 1
  • 6
  • have you tried this? https://developers.google.com/admin-sdk/directory/v1/guides/delegation – Vinicius Braz Pinto Apr 01 '14 at 00:36
  • No. But I did now ;-) . I still get the error message. But there was a hint in the article you posted: "Only users with access to the Admin APIs can access the Admin SDK Directory API, therefore your service account needs to impersonate one of those users to access the Admin SDK Directory API." How can I enable access to the Admin SDK for a service account?! Until now, I just activated the Admin SDK under APIs for the whole Project. – user3482779 Apr 01 '14 at 07:03
  • isn't that what the section "Delegate domain-wide authority to your service account" on that page describes? – Vinicius Braz Pinto Apr 01 '14 at 12:35
  • Not exactly. I can delegate domain-wide access to a given scope there. But not to an API. The documentation under https://developers.google.com/admin-sdk/directory/v1/guides/delegation specifically says in the note at the bottom of the section "Delegate domain-wide authority to your service account", that access to the API is needed in addition: "Only users with access to the Admin APIs can access the Admin SDK Directory API, therefore your service account needs to impersonate one of those users to access the Admin SDK Directory API.". – user3482779 Apr 01 '14 at 16:27

2 Answers2

0

Beyond granting the service account client id access to the given scopes in your Google Apps Control Panel, you need to tell the service account to impersonate a super administrator user within your Google Apps domain:

$auth->sub = $adminEmail;

For some reason, the Admin SDK docs don't contain a PHP sample but there's sample code for instantiating a service account in the Google Drive docs.

Jay Lee
  • 13,415
  • 3
  • 28
  • 59
  • Thanks a lot! That totally worked! Well yes, sadly the documentation and error message are not very helpful. I used the code from above and added just one line: $cred = new Google_Auth_AssertionCredentials($serviceAccountName, $scopes, file_get_contents($privateKeyFile)); $cred->sub = 'XXXX@my-domain.com'; $client->setAssertionCredentials($cred); – user3482779 Apr 04 '14 at 14:10
0

I found by trial and error that removing "admin." from the scopes makes it work (in addition to everything said above about following these steps: https://developers.google.com/drive/web/delegation#delegate_domain-wide_authority_to_your_service_account ).

$cs = json_decode(file_get_contents(<MY SECRET PATH> . 'client_secrets.json'), true); 
$cs = $cs['web'];
$cred = new Google_Auth_AssertionCredentials(
    $cs['client_email'], //why do they call this "service account name" ? Misleading >:(
    array(
        'https://www.googleapis.com/auth/directory.user',
        'https://www.googleapis.com/auth/directory.group',
        'https://www.googleapis.com/auth/directory.group.member'
    ),
    $key,
    'notasecret',
    'http://oauth.net/grant_type/jwt/1.0/bearer',
    '<MY EMAIL IN THE DOMAIN>' //_my_ email as an user with admin rights
);