Search code examples
phpoauth-2.0google-apigmail

Request had insufficient authentication scopes - gmail api offline not working refresh token


In my app users log in to the Google Api to sync specified messages from gmail to my app. When user log in to the app it's working for ~one week and after this time the refresh token is expired and user have to login again, but when they login again api is not working and return error.

Message: { "error": { "code": 403, "message": "Request had insufficient authentication scopes.", "errors": [ { "message": "Insufficient Permission", "domain": "global", "reason": "insufficientPermissions" } ], "status": "PERMISSION_DENIED" } }

Code:

include_once 'vendor/autoload.php';

                    foreach($officesList as $office)
                    {
                        #$this->debug(2, 'cronGmail', 'step2 execution');
                        $googleClient = new Google_Client();
                        $googleClient->setClientId('DELETED');
                        $googleClient->setClientSecret('DELETED');
                        
                        if(explode('.', $_SERVER['HTTP_HOST'])[0] == 'dev') {
                            $googleClient->setRedirectUri('DELETED');
                        } else {
                            $googleClient->setRedirectUri('DELETED');
                        }
                        $googleClient->setAccessType('offline');
                        $googleClient->addScope('email');
                        $googleClient->addScope('profile');
                        $googleClient->addScope(Google_Service_Gmail::GMAIL_READONLY);

                        $googleClient->setAccessToken($office->office_google_token);
                        if(!empty($office->office_google_refresh_token))
                        {
                            $googleClient->refreshToken($office->office_google_refresh_token);
                            echo 'not empety refresh';
                        }
                        else
                        {
                            $googleClient->setAccessToken($office->office_google_token);
                        }

                        if($googleClient->isAccessTokenExpired() == TRUE)
                        {
                            // TOKEN IS EXPIRED
                            $this->debug(1, 'cronGmail/1', 'token for oauth: '.$office->office_google_login_oauth_id.' is expired');
                            $this->google_conn_model->setTokenExpiredForOffice($office->office_id);

                            $this->cronReport('cronGmail/1', $startTime, date('Y-m-d H:i:s', time()), 'token expired, oauth: '.$office->office_google_login_oauth_id, 0);
                        }
                        else
                        {
                            // TOKEN NOT EXPIRED
                            $gmailService = new Google_Service_Gmail($googleClient);

                            $connectParams                  = [];
                            $connectParams['maxResults']    = 100;

                            $getMessagesResult = $gmailService->users_messages->listUsersMessages('me', $connectParams);

Solution

  • working for one week and after this time the refresh token is expired

    This should be resulting in an invalid_token error.

    Applications that are in the testing mode have their refresh tokens revoked after seven days.

    You will need to set your application to production in order to get an access token that will last longer.

    enter image description here

    Due to the fact that you are using the gmail api it will also expire if the user has changed their password.

    not working after logging in again

    Actually your issue isnt with login its with authorization. Im not sure where you are getting this

    $office->office_google_refresh_token
    

    But make sure when the user authorizes your application again that you store the new refresh token and are not using the old one. The old refresh token is expired and can not be used again.

    Alternately you could have the user go to their google account and check under third party access to ensure that your app's access was totally revoked. This will force the consent screen to show again and the user can then grant your application access again.