Trouble making authenticated calls to Google API via OAuth
Asked Answered
U

2

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 = '[email protected]';
$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/[email protected]/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?

Unsaddle answered 31/3, 2014 at 21:39 Comment(4)
have you tried this? developers.google.com/admin-sdk/directory/v1/guides/delegationSwaraj
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.Unsaddle
isn't that what the section "Delegate domain-wide authority to your service account" on that page describes?Swaraj
Not exactly. I can delegate domain-wide access to a given scope there. But not to an API. The documentation under 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.".Unsaddle
O
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.

Oxide answered 3/4, 2014 at 12:6 Comment(1)
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 = '[email protected]'; $client->setAssertionCredentials($cred);Unsaddle
T
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
);
Tee answered 3/6, 2014 at 14:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.