Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing OAuth scope giving invalid credentials error for existing users when appending rows in google sheet. #2569

Open
testtwf opened this issue Feb 27, 2024 · 0 comments

Comments

@testtwf
Copy link

testtwf commented Feb 27, 2024

we are integrating google sheet in our php(v8), laravel(v9) application and it was working fine untill we change the scope from https://www.googleapis.com/auth/gmail.metadata to https://www.googleapis.com/auth/userinfo.email. please help us to fix the issue, details are given below-

when now appending rows & headers it is not working and giving below error-

package we are using : https://github.com/googleapis/google-api-php-client

[2024-02-27 16:44:50] local.EMERGENCY: File:/var/www/html/projects/ProjectName/vendor/google/apiclient/src/Http/REST.phpLine:134Message:{
  "error": {
    "code": 401,
    "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
    "errors": [
      {
        "message": "Invalid Credentials",
        "domain": "global",
        "reason": "authError",
        "location": "Authorization",
        "locationType": "header"
      }
    ],
    "status": "UNAUTHENTICATED"
  }
}

updated scope and credentials in google developer console as well as in local config, it is working for new user. new user are able to authenticate, create spreadsheet and when any changes in data new rows and headers are getting appended in google sheet using api...but for existing google sheet and user when we try to call api to append rows, it is throwing above error. below is the codes how we are authenticating users and creating clients as well as appending rows.

/*
* authenticating user using oauth for creating spreadsheet
*/
public function authorizeService(Request $request)
{
    try {

        $client = new Client();
        $client->setClientId(config('constants.GOOGLE_CLIENT_ID'));
        $client->setClientSecret(config('constants.GOOGLE_CLIENT_SECRET'));
        $client->setRedirectUri(config('constants.GOOGLE_SERVICE_INTEGRATION_CALLBACK'));
        $client->setAccessType('offline');
        $client->setApprovalPrompt("force");
        $client->setScopes([
            'https://www.googleapis.com/auth/spreadsheets',
            'https://www.googleapis.com/auth/userinfo.email',
        ]);
        $client->setState(base64_encode(json_encode([
            'form_name' => $request->get('form_name'),
            'form_id' => $request->get('form_id'),
            'service' => $request->get('service')
        ])));

        $authUrl = $client->createAuthUrl();

        return $this->respondSuccess(__('form.success'), ['authUrl' => $authUrl]);

    } catch (Exception $e) {
        \Log::emergency("File:" . $e->getFile(). "Line:" . $e->getLine(). "Message:" . $e->getMessage());
        return $this->respondWentWrong($e);
    }
}
/*
* initializing client
*/
public function initializeClient($integration)
    {
        $accessToken = trim($integration->info['token']['access_token'] ?? '');
        $refresh_token = trim($integration->gmailAccount->refresh_token ?? '');

        $this->client = new Client();
        $this->client->setClientId(config('constants.GOOGLE_CLIENT_ID'));
        $this->client->setClientSecret(config('constants.GOOGLE_CLIENT_SECRET'));
        $this->client->setAccessType('offline');
        $this->client->setApprovalPrompt("force");
        $this->client->setAccessToken($accessToken);

        if ($this->client->isAccessTokenExpired()) {

            $this->client->setAccessToken($refresh_token);
            $this->client->fetchAccessTokenWithRefreshToken($refresh_token);
            $accessTokenUpdated = $this->client->getAccessToken();
            $this->client->setAccessToken($accessTokenUpdated);

            /*
            * update token
            */
            $info = $integration->info;
            $info['token'] = $accessTokenUpdated;
            $integration->info = $info;
            $integration->save();
        }
    }
/*
* appending rows
*/
public function appendRowsOnSpreadsheet($integration, $submission)
{
    try {

        $this->initializeClient($integration);
        $spreadsheetId = $integration->info['spreadsheetId'] ?? '';
        $accessToken = trim($integration->info['token']['access_token'] ?? '');

        /*
        * Define the range where you want to append data
        * (A2:C appends to columns A, B, C, starting from row 2)
        */
        $range = 'Sheet1';

        /*
        * Create the request body
        */
        $requestBody = [
            'values' => [
                $submission
            ]
        ];

        /*
        * Create the Guzzle HTTP client
        */
        $guzzleClient = new GuzzleClient();

        /*
        * Prepare the URL for appending data
        */
        $url = "https://sheets.googleapis.com/v4/spreadsheets/{$spreadsheetId}/values/{$range}:append";

        /*
        * Prepare the headers
        */
        $headers = [
            'Authorization' => 'Bearer ' . $accessToken,
            'Content-Type' => 'application/json',
        ];

        /*
        * Make the API request to append data
        */
        $response = $guzzleClient->post($url, [
            'headers' => $headers,
            'json' => $requestBody,
            'query' => [
                'valueInputOption' => 'RAW'
            ],
        ]);

        $responseData = json_decode($response->getBody(), true);

        $output = [
            'success' => true,
            'msg' => __('form.success'),
            'response' => $responseData
        ];
    } catch (Exception $e) {
        \Log::emergency("File:" . $e->getFile(). "Line:" . $e->getLine(). "Message:" . $e->getMessage());
        $output = [
            'success' => false,
            'msg' => $e->getMessage()
        ];
    }
    return $output;
}

please let us know what are the approaches we can take to fix the issue.
thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant