"code": 401, "message": "Invalid Credentials" ->Google drive connection error

I have an application that is connected to Google drive and transmission data to sheets.

I successfully made connections and everything works perfectly, but after a couple of hours or days (depending on the server where are user use app), my connection is broken and I got this message :

" { "error": { "errors": [ { "domain": "global", "reason": "authError", "message": "Invalid Credentials", "locationType": "header", "location": "Authorization" } ], "code": 401, "message": "Invalid Credentials" } }".

Below is code :

    $this->client = new Google_Client();
    $this->client->setApplicationName('BreezingForms Google Drive Spreadsheets');
    $this->client->addScope(array('https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/spreadsheets'));

    // testing:
    // 197794184197-bt2q9knrdu1i54vgladd97ob196k4c6s.apps.googleusercontent.com
    // dImciIWj3WNOrIcYRbu9MFeA

    if (isset($_POST['gdata_custom_client_id']) && trim($_POST['gdata_custom_client_id']) != '' && trim($_POST['gdata_custom_client_secret']) != '') {

        $this->client->setClientId(trim($_POST['gdata_custom_client_id']));
        $this->client->setClientSecret(trim($_POST['gdata_custom_client_secret']));

        $db->setQuery("Update #__breezingforms_addons_gdata Set custom_client_id = " . $db->quote(trim($_POST['gdata_custom_client_id'])) . ", custom_client_secret = " . $db->quote(trim($_POST['gdata_custom_client_secret'])) . " Where form_id = " . intval($_REQUEST['form']));
        $db->execute();

    } else {

        $form_id = -1;

        if(JRequest::getInt('ff_form',-1) > 0){

            $form_id = JRequest::getInt('ff_form',-1);

        }else if(isset($_REQUEST['form'])){

            $form_id = intval($_REQUEST['form']);
        }

        $db->setQuery("Select * From #__breezingforms_addons_gdata Where form_id = " . $db->quote($form_id));
        $client = $db->loadObject();

        if ($client) {

            $this->client->setClientId($client->custom_client_id);
            $this->client->setClientSecret($client->custom_client_secret);
        }
    }

    $this->client->setApprovalPrompt('auto');
    $this->client->setPrompt('consent');
    $this->client->setRedirectUri('urn:ietf:wg:oauth:2.0:oob');
    $this->client->setAccessType('offline');


}

function onPropertiesDisplay($form_id, $tabs){
    
    if(!$form_id) return '';
    
    $error = '';
    
    $db = JFactory::getDBO();
    
    $db->setQuery("Select `title`,`name`,`id` From #__facileforms_elements Where form = " . intval($form_id) . " And `title` Not In ('bfFakeTitle','bfFakeTitle2','bfFakeTitle3','bfFakeTitle4','bfFakeTitle5') And `type` Not In ('','UNKNOWN') Order By ordering");
    $breezingforms_fields = $db->loadObjectList();
    
    $db->setQuery("Select `enabled`, `username`, `password`, `worksheet_id`, `spreadsheet_id`, `fields`, `meta`, `debug` From #__breezingforms_addons_gdata Where form_id = " . intval($form_id));
    $gdata = $db->loadObject();
    
    if( $gdata === null ){
        $gdata = new stdClass();
        $gdata->username = '';
        $gdata->password = '';
        $gdata->enabled = 0;
        $gdata->worksheet_id = '';
        $gdata->spreadsheet_id = '';
        $gdata->fields = '';
        $gdata->meta = '';
        $gdata->debug = 0;
    }
    
    $gdata->fields = explode('/,/', $gdata->fields);
    $gdata->meta   = explode('/,/', $gdata->meta);
    
    $gdata_spreadsheets = array();
    $gdata_worksheets = array();
    $gdata_columns = array();
    $worksheets_name=array();
               $worksheets_name1=array();
               $worksheets_name2=array();

    
    //if( $gdata->enabled == 1 ){
        
        try{
        
            $spreadsheetFeed = null;
            
            $auth_url = '';
            
            $db->setQuery("Select password From #__breezingforms_addons_gdata Where form_id = " . intval($form_id));
            $accessToken = $db->loadResult();

            if(!$accessToken){
                
                $auth_url = $this->client->createAuthUrl();
                
            } else {
                
                try{
                    
                    $this->client->setAccessToken($accessToken);
                    $token = json_decode($accessToken);
            
                    if ($this->client->isAccessTokenExpired()) {
                        $this->client->refreshToken($token->refresh_token);
                         $tok = json_encode($this->client->getAccessToken());
                        $token = json_decode($tok);
                        $db->setQuery("Update #__breezingforms_addons_gdata set password = " . $db->quote($tok) . " Where form_id = " . intval($form_id));
                        $db->execute();
                    }
             
                }catch(Exception $e){
                    
                    $accessToken = null;
                    $auth_url = $this->client->createAuthUrl();
                    //$error = $e->getMessage();

                }

After I refresh the connection, everything works again, and problems appear again.

whether know, why it happens?

Regards,


Apps that are in test have their refresh tokens expired after seven days.

To fix it up your application into production.

Refresh token

A Google Cloud Platform project with an OAuth consent screen configured for an external user type and a publishing status of "Testing" is issued a refresh token expiring in 7 days.