PHP Service Account Authentication Issue with Google Documents API

I’m trying to connect to Google Documents API using a service account but running into authentication problems. Getting a 401 error that says authentication credentials are missing.

<?php
require_once 'vendor/autoload.php';

$googleClient = new Google\Client();
$googleClient->setApplicationName('DOC API TEST APP');
$googleClient->setAuthConfig('my-project-credentials.json');
$googleClient->setScopes("https://www.googleapis.com/auth/documents.readonly");
$googleClient->setSubject('[email protected]');
$googleClient->setAccessType('offline');

$httpClient = new GuzzleHttp\Client(['base_uri' => 'https://docs.googleapis.com/v1/documents/']);

$result = $httpClient->request('GET', '1A2B3C4D5E6F7G8H9I0J', [
    'verify' => false,
]);
print_r($result);
?>

The error message shows that OAuth 2 credentials are expected but I think I’m not passing the authentication token properly with my HTTP request. I have the service account set up in Google Workspace admin console with proper scopes configured.

How do I properly authenticate the API request using the service account credentials? What am I missing in my code?

your missing the auth header completely in your guzzle request. the google client generates tokens but you need to manually add them to your http calls. try $token = $googleClient->fetchAccessTokenWithAssertion(); $headers = ['Authorization' => 'Bearer ' . $token['access_token']]; then pass headers to your guzzle request. also double check your json file path is actualy correct

You’re creating an authenticated Google Client but then completely ignoring it when making your API request. The Guzzle client you’re using has no knowledge of the authentication token that Google Client generates. I ran into similar issues when I first started working with Google APIs. The simplest fix would be to replace your manual HTTP request with the Google Docs service wrapper. Initialize the service with $service = new Google_Service_Docs($googleClient); then use $service->documents->get('1A2B3C4D5E6F7G8H9I0J'); to retrieve your document. This approach handles all the authentication headers automatically. If you prefer sticking with direct HTTP calls, you need to extract the access token from the authenticated client and include it in your Guzzle request headers as a Bearer token.

The main issue stems from the fact that while you’ve initialized a Google Client, you’re making the API call using a separate GuzzleHttp client, which bypasses the authentication you’ve set up. I’ve experienced this exact problem in the past while working on a document processing script. You should utilize the built-in HTTP client of the Google Client instead of Guzzle. After configuring your authentication, invoke $googleClient->authorize() to obtain an authenticated HTTP client for your requests. Alternatively, consider using the Google Docs service class, which manages authentication for you. Lastly, ensure that the path to your service account JSON file is correct and confirm that the service account has access to the specific document, as service accounts require explicit sharing with their email addresses.