0

I am new to the Google APIs and also to somewhat to PHP. I know there has been quite some similar questions, but going through them all in the last few days I didn't manage to handle my problem.

I am building an app which reads from and writes to google sheets, and using a simple API key with a public sheet I am able to read without problems. I didn't manage to figure out the Service Account authorization though.

I have made the sheet private and authorized the service account e-mail address editor access to the sheet.

I double and triple checked the client_id, email address, sheet id.

Here is my code:

function update_stat($spreadsheet_range)
{
    session_start();
    $client_id = 'XXXXXXXXXX';
    $email_address = 'xxx@xxxx.iam.gserviceaccount.com';

    $service_account_file = __DIR__ . '/sheetsCS.json';
    $spreadsheet_id = 'xxxxxxxxxxxxxxxxxxxxxx';
    putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $service_account_file);
    date_default_timezone_set("Europe/Rome");

    $client = new Google_Client();
    $client->useApplicationDefaultCredentials();
    $client->setScopes(Google_Service_Sheets::SPREADSHEETS);
    $service = new Google_Service_Sheets($client);

    $result = $service->spreadsheets_values->get($spreadsheet_id, $spreadsheet_range);
    return $result;
}

No matter what I try, I get the following error:

[25-Nov-2020 09:22:07 Europe/Rome] PHP Fatal error:  Uncaught Google\Service\Exception: {"error":"invalid_grant","error_description":"Invalid JWT Signature."} in /home/usedbott/public_html/wp-content/themes/ubl-custom-theme/stat-interface/vendor/google/apiclient/src/Http/REST.php:128
Stack trace:
#0 /home/usedbott/public_html/wp-content/themes/ubl-custom-theme/stat-interface/vendor/google/apiclient/src/Http/REST.php(103): Google\Http\REST::decodeHttpResponse(Object(GuzzleHttp\Psr7\Response), Object(GuzzleHttp\Psr7\Request), 'Google_Service_...')
#1 [internal function]: Google\Http\REST::doExecute(Object(GuzzleHttp\Client), Object(GuzzleHttp\Psr7\Request), 'Google_Service_...')
#2 /home/usedbott/public_html/wp-content/themes/ubl-custom-theme/stat-interface/vendor/google/apiclient/src/Task/Runner.php(181): call_user_func_array(Array, Array)
#3 /home/usedbott/public_html/wp-content/themes/ubl-custom-theme/stat-interface/vendor/google/apiclient/src/Http/REST.php(66): Google\Task\Runner->run()
#4 /home/usedbott/public_html/wp-content/themes/ubl-custom-theme/stat-int in /home/usedbott/public_html/wp-content/themes/ubl-custom-theme/stat-interface/vendor/google/apiclient/src/Http/REST.php on line 128

What am I missing to make this work?

Krisztian Toth
  • 57
  • 3
  • 13
  • It does say clearly that `"error":"invalid_grant","error_description":"Invalid JWT Signature."`. Are you following some guide to the authentication? Have you manage to make it work at some point? – Raserhin Nov 25 '20 at 11:12
  • No, I haven't managed to make it work at any point. I followed many guides and none of them helped me get it to a point where I actually managed to access sheets. I suspect it is something basic I am missing, but I haven't managed to figure it out. – Krisztian Toth Nov 25 '20 at 15:11
  • But how are you managing credentials with the service account? Could [this link](https://developers.google.com/identity/protocols/oauth2/service-account) help you? – Raserhin Nov 25 '20 at 15:12
  • I have the credentials file saved on the server and load it from there. I know the linked page. – Krisztian Toth Nov 25 '20 at 16:01

1 Answers1

1

You might also want to check this Quickstart guide for Google Sheets API in PHP https://developers.google.com/sheets/api/quickstart/php

Contents:

  1. Guidelines on how to enable Google Sheets API
  2. How to install Google Client Library
  3. Setup a sample code
  4. Run the sample code

Sample Code:

<?php
require __DIR__ . '/vendor/autoload.php';

if (php_sapi_name() != 'cli') {
    throw new Exception('This application must be run on the command line.');
}

/**
 * Returns an authorized API client.
 * @return Google_Client the authorized client object
 */
function getClient()
{
    $client = new Google_Client();
    $client->setApplicationName('Google Sheets API PHP Quickstart');
    $client->setScopes(Google_Service_Sheets::SPREADSHEETS_READONLY);
    $client->setAuthConfig('credentials.json');
    $client->setAccessType('offline');
    $client->setPrompt('select_account consent');

    // Load previously authorized token from a file, if it exists.
    // The file token.json stores the user's access and refresh tokens, and is
    // created automatically when the authorization flow completes for the first
    // time.
    $tokenPath = 'token.json';
    if (file_exists($tokenPath)) {
        $accessToken = json_decode(file_get_contents($tokenPath), true);
        $client->setAccessToken($accessToken);
    }

    // If there is no previous token or it's expired.
    if ($client->isAccessTokenExpired()) {
        // Refresh the token if possible, else fetch a new one.
        if ($client->getRefreshToken()) {
            $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
        } else {
            // Request authorization from the user.
            $authUrl = $client->createAuthUrl();
            printf("Open the following link in your browser:\n%s\n", $authUrl);
            print 'Enter verification code: ';
            $authCode = trim(fgets(STDIN));

            // Exchange authorization code for an access token.
            $accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
            $client->setAccessToken($accessToken);

            // Check to see if there was an error.
            if (array_key_exists('error', $accessToken)) {
                throw new Exception(join(', ', $accessToken));
            }
        }
        // Save the token to a file.
        if (!file_exists(dirname($tokenPath))) {
            mkdir(dirname($tokenPath), 0700, true);
        }
        file_put_contents($tokenPath, json_encode($client->getAccessToken()));
    }
    return $client;
}


// Get the API client and construct the service object.
$client = getClient();
$service = new Google_Service_Sheets($client);

// Prints the names and majors of students in a sample spreadsheet:
// https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
$spreadsheetId = '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms';
$range = 'Class Data!A2:E';
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
$values = $response->getValues();

if (empty($values)) {
    print "No data found.\n";
} else {
    print "Name, Major:\n";
    foreach ($values as $row) {
        // Print columns A and E, which correspond to indices 0 and 4.
        printf("%s, %s\n", $row[0], $row[4]);
    }
}
Ron M
  • 5,791
  • 1
  • 4
  • 16