¿Cómo actualizar el token con el cliente API de Google?

91

He estado jugando con la API de Google Analytics (V3) y me he encontrado con algunos errores. En primer lugar, todo está configurado correctamente y funcionó con mi cuenta de prueba. Pero cuando quiero obtener datos de otra ID de perfil (Misma cuenta de Google / Cuenta GA), obtengo un error 403. Lo extraño es que los datos de algunas cuentas de GA devolverán datos mientras que otras generan este error.

Revoqué el token y me autentiqué una vez más, y ahora parece que puedo obtener datos de todas mis cuentas. ¿Problema resuelto? No. Como la clave de acceso caducará, volveré a tener el mismo problema.

Si he entendido bien las cosas, se podría usar resfreshToken para obtener un nuevo authenticationTooken.

El problema es, cuando ejecuto:

$client->refreshToken(refresh_token_key) 

se devuelve el siguiente error:

Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }'

Revisé el código detrás del método refreshToken y rastreé la solicitud hasta el archivo "apiOAuth2.php". Todos los parámetros se envían correctamente. Grant_type está codificado en 'refresh_token' dentro del método, por lo que es difícil para mí entender qué está mal. La matriz de parámetros se ve así:

Array ( [client_id] => *******-uqgau8uo1l96bd09eurdub26c9ftr2io.apps.googleusercontent.com [client_secret] => ******** [refresh_token] => 1\/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY [grant_type] => refresh_token )

El procedimiento es el siguiente.

$client = new apiClient();
$client->setClientId($config['oauth2_client_id']);
$client->setClientSecret($config['oauth2_client_secret']);
$client->setRedirectUri($config['oauth2_redirect_uri']);
$client->setScopes('https://www.googleapis.com/auth/analytics.readonly');
$client->setState('offline');

$client->setAccessToken($config['token']); // The access JSON object.

$client->refreshToken($config['refreshToken']); // Will return error here

¿Es esto un error o he entendido mal algo por completo?

seorch.me
fuente
No sé si es un error o algo así, pero actualmente estoy actualizando el token de acceso usando una solicitud http CURL sin procesar y está funcionando bien.
Gremo
Seorch ... ¿ya has resuelto esto? El mismo problema aquí.
Brian Vanderbusch
@gremo, ¿podrías compartir la solicitud http de CURL sin procesar que usaste aquí? Sería muy útil. ¡Gracias!
Silver Ringvee

Respuestas:

76

Así que finalmente descubrí cómo hacer esto. La idea básica es que tenga el token que obtiene la primera vez que solicita la autenticación. Este primer token tiene un token de actualización. El primer token original caduca después de una hora. Después de una hora, debe usar el token de actualización del primer token para obtener un nuevo token utilizable. Usas $client->refreshToken($refreshToken)para recuperar un nuevo token. A esto lo llamaré "ficha temporal". También debe almacenar este token temporal porque después de una hora también caduca y tenga en cuenta que no tiene un token de actualización asociado. Para obtener un nuevo token temporal, debe usar el método que usó antes y usar el primer token de actualización. He adjuntado el código a continuación, que es feo, pero soy nuevo en esto ...

//pull token from database
$tokenquery="SELECT * FROM token WHERE type='original'";
$tokenresult = mysqli_query($cxn,$tokenquery);
if($tokenresult!=0)
{
    $tokenrow=mysqli_fetch_array($tokenresult);
    extract($tokenrow);
}
$time_created = json_decode($token)->created;
$t=time();
$timediff=$t-$time_created;
echo $timediff."<br>";
$refreshToken= json_decode($token)->refresh_token;


//start google client note:
$client = new Google_Client();
$client->setApplicationName('');
$client->setScopes(array());
$client->setClientId('');
$client->setClientSecret('');
$client->setRedirectUri('');
$client->setAccessType('offline');
$client->setDeveloperKey('');

//resets token if expired
if(($timediff>3600)&&($token!=''))
{
    echo $refreshToken."</br>";
    $refreshquery="SELECT * FROM token WHERE type='refresh'";
    $refreshresult = mysqli_query($cxn,$refreshquery);
    //if a refresh token is in there...
    if($refreshresult!=0)
    {
        $refreshrow=mysqli_fetch_array($refreshresult);
        extract($refreshrow);
        $refresh_created = json_decode($token)->created;
        $refreshtimediff=$t-$refresh_created;
        echo "Refresh Time Diff: ".$refreshtimediff."</br>";
        //if refresh token is expired
        if($refreshtimediff>3600)
        {
            $client->refreshToken($refreshToken);
        $newtoken=$client->getAccessToken();
        echo $newtoken."</br>";
        $tokenupdate="UPDATE token SET token='$newtoken' WHERE type='refresh'";
        mysqli_query($cxn,$tokenupdate);
        $token=$newtoken;
        echo "refreshed again";
        }
        //if the refresh token hasn't expired, set token as the refresh token
        else
        {
        $client->setAccessToken($token);
           echo "use refreshed token but not time yet";
        }
    }
    //if a refresh token isn't in there...
    else
    {
        $client->refreshToken($refreshToken);
        $newtoken=$client->getAccessToken();
        echo $newtoken."</br>";
        $tokenupdate="INSERT INTO token (type,token) VALUES ('refresh','$newtoken')";
        mysqli_query($cxn,$tokenupdate);
        $token=$newtoken;
        echo "refreshed for first time";
    }      
}

//if token is still good.
if(($timediff<3600)&&($token!=''))
{
    $client->setAccessToken($token);
}

$service = new Google_DfareportingService($client);
Uri Weg
fuente
52
En lugar de verificar 3600 segundos, debe usar $ client-> isAccessTokenExpired ()
Gaurav Gupta
2
Pequeña actualización. En la última versión, cuando solicita un token de actualización, el nuevo token de acceso que se devuelve ahora viene con un nuevo token de actualización. Entonces, esencialmente, puede usar el token json actualizado para reemplazar el token json anterior, y ya no necesita retener el token de acceso inicial. .
skidad el
1
Tenga en cuenta que $client->isAccessTokenExpired()solo comprobará los tiempos que se mantienen localmente para ver si cree que el token ha expirado. Es posible que el token aún haya caducado y la aplicación local solo lo sabrá realmente cuando intente usarlo. En este caso, el cliente API devolverá una excepción y no actualizará automáticamente el token.
Jason
44

El problema está en el token de actualización:

[refresh_token] => 1\/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY

Cuando una cadena con un '/'get json encoded, se escapa con un'\' , por lo tanto, debe eliminarlo.

El token de actualización en su caso debería ser:

1/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY

Lo que supongo que ha hecho es que imprimió la cadena json que Google envió y copió y pegó el token en su código porque si lo json_decodehace, ¡lo eliminará correctamente '\'!

Asim
fuente
1
mención increíble, hizo mi día! horas ahorradas!
Mircea Sandu
Salvaste mi día !
Truong Dang
Ojalá pudiera votar esto 100 veces. Estaba a punto de hacer un agujero en una pared con mi teclado después de mirar el mensaje de "mala concesión" durante varias horas después de intentar absolutamente todo para que la ficha funcionara. Maldito hombre de Google, ¿por qué usar barras, solo por qué?
Askerman
18

aquí está el fragmento para configurar el token, antes de eso, asegúrese de que el tipo de acceso debe establecerse como sin conexión

if (isset($_GET['code'])) {
  $client->authenticate();
  $_SESSION['access_token'] = $client->getAccessToken();
}

Para actualizar el token

$google_token= json_decode($_SESSION['access_token']);
$client->refreshToken($google_token->refresh_token);

esto actualizará su token, debe actualizarlo en la sesión para que pueda hacerlo

 $_SESSION['access_token']= $client->getAccessToken()
Faishal
fuente
1
me alegraste el día con esto :) muchas gracias, mucho más simple de lo que pensé que sería, ya que he pasado mucho tiempo sin llegar a ninguna parte: D
TB Ygg
16

El tipo de acceso debe establecerse en offline. statees una variable que configura para su propio uso, no para el uso de la API.

Asegúrese de tener la última versión de la biblioteca cliente y agregue:

$client->setAccessType('offline');

Consulte Formación de la URL para obtener una explicación de los parámetros.

jk.
fuente
Gracias jk. Descargué la última versión y revoqué el acceso a la aplicación para mi cuenta. Luego concedí acceso una vez más y almacené el accessToken y refreshToken. La cuestión es que siempre me han dado un refreshToken, incluso si se ha omitido setAccessType. De todos modos, cuando ejecuto $ client-> refreshToken (refresh-token-key), todavía obtengo el error "invalid_grant". He comprobado la URL de autenticación y su valor predeterminado es "forzar". Si lo cambio a "auto" y ejecuto el método de autenticación, no me redirigen porque ya he concedido acceso. Pero el respons es un accessToken sin uno de actualización. ¿Algunas ideas?
seorch.me
@ seorch.me Suena loco, pero ¿es posible que tenga que configurar un nuevo $client( $client = new apiClient();) para usar el token de actualización?
jk.
1
@ seorch.me debe configurar $client->setApprovalPrompt('force')y $client->setAccessType('offline')obtener un nuevo token de actualización durante la autorización. Sin obligar al usuario a aprobar el alcance del acceso, Google asume que seguirá usando el token de actualización anterior.
Jason
14

La respuesta publicada por @ uri-weg funcionó para mí, pero como no encontré sus explicaciones muy claras, permítanme reformularlas un poco.

Durante la secuencia del primer permiso de acceso, en la devolución de llamada, cuando llega al punto en el que recibe un código de autenticación, debe guardar el token de acceso y el token de actualización. también.

El motivo es que la API de Google le envía un token de acceso con un token de actualización solo cuando se le solicita permiso de acceso. Los siguientes tokens de acceso se enviarán sin ningún token de actualización (a menos que use elapproval_prompt=force opción).

El token de actualización que recibió la primera vez permanece válido hasta que el usuario revoca el permiso de acceso.

En php simplista, un ejemplo de la secuencia de devolución de llamada sería:

// init client
// ...

$authCode = $_GET['code'];
$accessToken = $client->authenticate($authCode);
// $accessToken needs to be serialized as json
$this->saveAccessToken(json_encode($accessToken));
$this->saveRefreshToken($accessToken['refresh_token']);

Y más adelante, en php simplista, la secuencia de conexión sería:

// init client
// ...

$accessToken = $this->loadAccessToken();
// setAccessToken() expects json
$client->setAccessToken($accessToken);

if ($client->isAccessTokenExpired()) {
    // reuse the same refresh token
    $client->refreshToken($this->loadRefreshToken());
    // save the new access token (which comes without any refresh token)
    $this->saveAccessToken($client->getAccessToken());
}
Daishi
fuente
perfecto, funcionó mucho. Lo único que diría es que debe explicar que necesita pasar el objeto json, no solo el token como una cadena.
Oliver Bayes-Shelton
@ OliverBayes-Shelton Hola. Gracias. Pensé que // setAccessToken() expects jsonera suficiente. ¿O es para otra parte del código?
Daishi
Esto funciona muy bien para mí, pero ¿sabe si este código maneja situaciones en las que un token expira debido a que se excede el límite de 50 actualizaciones de token? Los detalles sobre la "Caducidad del token" se pueden encontrar aquí: developers.google.com/identity/protocols/OAuth2#expiration
Bjorn
Parece que la última versión 2.0 ahora devuelve el token de actualización en la matriz de tokens de acceso. Esto significa que guardar el token de acceso también guarda el token de actualización, ya que se incluye el token de actualización. En respuesta a la expiración del token de actualización, supongo que tendría que probarse y manejarse explícitamente; recuerde que el límite de 50 es "por usuario por cliente", es decir, es de 50 por cliente, por lo que es poco probable que lo alcance, especialmente si utiliza los ámbitos incluidos para combinar tokens.
Brian C
8

Aquí está el código que estoy usando en mi proyecto y está funcionando bien:

public function getClient(){
    $client = new Google_Client();
    $client->setApplicationName(APPNAME);       // app name
    $client->setClientId(CLIENTID);             // client id
    $client->setClientSecret(CLIENTSECRET);     // client secret 
    $client->setRedirectUri(REDIRECT_URI);      // redirect uri
    $client->setApprovalPrompt('auto');

    $client->setAccessType('offline');         // generates refresh token

    $token = $_COOKIE['ACCESSTOKEN'];          // fetch from cookie

    // if token is present in cookie
    if($token){
        // use the same token
        $client->setAccessToken($token);
    }

    // this line gets the new token if the cookie token was not present
    // otherwise, the same cookie token
    $token = $client->getAccessToken();

    if($client->isAccessTokenExpired()){  // if token expired
        $refreshToken = json_decode($token)->refresh_token;

        // refresh the token
        $client->refreshToken($refreshToken);
    }

    return $client;
}
SR verde
fuente
6

Tuvo el mismo problema; mi guión que funcionó ayer, por alguna extraña razón no lo hizo hoy. Sin cambios.

Aparentemente, esto se debió a que el reloj de mi sistema estaba apagado en 2.5 (!!) segundos, la sincronización con NTP lo solucionó.

Consulte también: https://code.google.com/p/google-api-php-client/wiki/OAuth2#Solving_invalid_grant_errors

strikernl
fuente
Esa respuesta me ayudó mucho, hombre. Probablemente me ahorraste mucho tiempo. ¡Mucho! ¡Gracias! Acabo de ejecutar sudo apt-get install ntpen mi máquina Debian para instalar NTP. Sincronizó el reloj y se solucionó el problema.
Szymon Sadło
4

Para su información: la API de Google Analytics 3.0 actualizará automáticamente el token de acceso si tiene un token de actualización cuando caduque, por lo que su secuencia de comandos nunca necesita refreshToken .

(Ver la Signfunción en auth/apiOAuth2.php)

Mark Smith
fuente
"Actualizar automáticamente" significa que solo tengo que solicitar getAccessToken () y recibiré uno actualizado. Pero primero tengo que configurar el token de actualización de la base de datos, ¿verdad? De lo contrario, la actualización funcionaría sin un token de actualización y no creo que esto funcione
ninsky
4

A veces, el Token de actualización no se genera al usar $client->setAccessType ("offline"); .

Prueba esto:

$client->setAccessType ("offline");
$client->setApprovalPrompt ("force"); 
Meenu Sharma
fuente
Para ser más específico, parece que el token de actualización está incluido en su primera autorización. Si lo guarda y luego lo usa, creo (según otros, no verificado) que el token de actualización se sigue devolviendo. El documento ahora también dice que actualizarán automáticamente el token de acceso si tienen un token de actualización, lo que significa que es simplemente una cuestión de administrar el token de actualización de forma segura. setApprovalPrompt ('force') fuerza la emisión de un token de actualización posteriormente; sin él no obtendrás otro.
Brian C
2

Usé el ejemplo de códigos inteligentes con la versión actual de la API de Google, pero ese no funcionó. Creo que su API está demasiado desactualizada.

Entonces, acabo de escribir mi propia versión, basada en uno de los ejemplos de API ... Genera token de acceso, token de solicitud, tipo de token, token de identificación, tiempo de vencimiento y tiempo de creación como cadenas

Si sus credenciales de cliente y clave de desarrollador son correctas, este código debería funcionar de inmediato.

<?php
// Call set_include_path() as needed to point to your client library.
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_Oauth2Service.php';
session_start();

$client = new Google_Client();
$client->setApplicationName("Get Token");
// Visit https://code.google.com/apis/console?api=plus to generate your
// oauth2_client_id, oauth2_client_secret, and to register your oauth2_redirect_uri.
$oauth2 = new Google_Oauth2Service($client);

if (isset($_GET['code'])) {
    $client->authenticate($_GET['code']);
    $_SESSION['token'] = $client->getAccessToken();
    $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
    header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
    return;
}

if (isset($_SESSION['token'])) {
    $client->setAccessToken($_SESSION['token']);
}

if (isset($_REQUEST['logout'])) {
    unset($_SESSION['token']);
    $client->revokeToken();
}
?>
<!doctype html>
<html>
    <head><meta charset="utf-8"></head>
    <body>
        <header><h1>Get Token</h1></header>
        <?php
        if ($client->getAccessToken()) {
            $_SESSION['token'] = $client->getAccessToken();
            $token = json_decode($_SESSION['token']);
            echo "Access Token = " . $token->access_token . '<br/>';
            echo "Refresh Token = " . $token->refresh_token . '<br/>';
            echo "Token type = " . $token->token_type . '<br/>';
            echo "Expires in = " . $token->expires_in . '<br/>';
            echo "ID Token = " . $token->id_token . '<br/>';
            echo "Created = " . $token->created . '<br/>';
            echo "<a class='logout' href='?logout'>Logout</a>";
        } else {
            $authUrl = $client->createAuthUrl();
            print "<a class='login' href='$authUrl'>Connect Me!</a>";
        }
        ?>
    </body>
</html>
John Slegers
fuente
1
Por favor, ¿me podría explicar por qué esta línea: $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];. ¿Por qué redirige a la misma página? ¿Es esto necesario?
Tropicalista
@Tropicalista: No es necesario recargar la página per se, pero esta es la forma en que se implementan típicamente los flujos de autenticación.
John Slegers
pero no está utilizando el token de actualización para obtener un nuevo token de acceso si el token de acceso ha caducado.
Apadana
1

Tengo el mismo problema con google / google-api-php-client v2.0.0-RC7 y después de buscar durante 1 hora, resolví este problema usando json_encode así:

    if ($client->isAccessTokenExpired()) {
        $newToken = json_decode(json_encode($client->getAccessToken()));
        $client->refreshToken($newToken->refresh_token);
        file_put_contents(storage_path('app/client_id.txt'), json_encode($client->getAccessToken()));
    }
Grandong
fuente
1

Esto aquí funciona muy bien, tal vez podría ayudar a cualquiera:

index.php

session_start();

require_once __DIR__.'/client.php';

if(!isset($obj->error) && isset($_SESSION['access_token']) && $_SESSION['access_token'] && isset($obj->expires_in)) {
?>
<!DOCTYPE html>
<html>
<head>
<title>Google API Token Test</title>
<meta charset='utf-8' />
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script>
search('Music Mix 2010');
function search(q) {
    $.ajax({
        type: 'GET',
        url: 'action.php?q='+q,
        success: function(data) {
            if(data == 'refresh') location.reload();
            else $('#response').html(JSON.stringify(JSON.parse(data)));
        }
    });
}
</script>
</head>
<body>
<div id="response"></div>
</body>
</html>
<?php
}
else header('Location: '.filter_var('https://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/oauth2callback.php', FILTER_SANITIZE_URL));
?>

oauth2callback.php

require_once __DIR__.'/vendor/autoload.php';

session_start();

$client = new Google_Client();
$client->setAuthConfigFile('auth.json');
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
$client->setRedirectUri('https://'.filter_var($_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'], FILTER_SANITIZE_URL));
$client->addScope(Google_Service_YouTube::YOUTUBE_FORCE_SSL);

if(isset($_GET['code']) && $_GET['code']) {
    $client->authenticate(filter_var($_GET['code'], FILTER_SANITIZE_STRING));
    $_SESSION['access_token'] = $client->getAccessToken();
    $_SESSION['refresh_token'] = $_SESSION['access_token']['refresh_token'];
    setcookie('refresh_token', $_SESSION['refresh_token'], time()+60*60*24*180, '/', filter_var($_SERVER['HTTP_HOST'], FILTER_SANITIZE_URL), true, true);
    header('Location: '.filter_var('https://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']), FILTER_SANITIZE_URL));
    exit();
}
else header('Location: '.filter_var($client->createAuthUrl(), FILTER_SANITIZE_URL));
exit();

?>

client.php

// https://developers.google.com/api-client-library/php/start/installation
require_once __DIR__.'/vendor/autoload.php';

$client = new Google_Client();
$client->setAuthConfig('auth.json');
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
$client->addScope(Google_Service_YouTube::YOUTUBE_FORCE_SSL);

// Delete Cookie Token
#setcookie('refresh_token', @$_SESSION['refresh_token'], time()-1, '/', filter_var($_SERVER['HTTP_HOST'], FILTER_SANITIZE_URL), true, true);

// Delete Session Token
#unset($_SESSION['refresh_token']);

if(isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) {
    $client->refreshToken($_SESSION['refresh_token']);
    $_SESSION['access_token'] = $client->getAccessToken();
}
elseif(isset($_COOKIE['refresh_token']) && $_COOKIE['refresh_token']) {
    $client->refreshToken($_COOKIE['refresh_token']);
    $_SESSION['access_token'] = $client->getAccessToken();
}

$url = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token='.urlencode(@$_SESSION['access_token']['access_token']);
$curl_handle = curl_init();
curl_setopt($curl_handle, CURLOPT_URL, $url);
curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_USERAGENT, 'Google API Token Test');
$json = curl_exec($curl_handle);
curl_close($curl_handle);

$obj = json_decode($json);

?>

action.php

session_start();

require_once __DIR__.'/client.php';

if(isset($obj->error)) {
    echo 'refresh';
    exit();
}
elseif(isset($_SESSION['access_token']) && $_SESSION['access_token'] && isset($obj->expires_in) && isset($_GET['q']) && !empty($_GET['q'])) {
    $client->setAccessToken($_SESSION['access_token']);
    $service = new Google_Service_YouTube($client);
    $response = $service->search->listSearch('snippet', array('q' => filter_input(INPUT_GET, 'q', FILTER_SANITIZE_SPECIAL_CHARS), 'maxResults' => '1', 'type' => 'video'));
    echo json_encode($response['modelData']);
    exit();
}
?>
usuario1768700
fuente
1

Google ha realizado algunos cambios desde que se publicó originalmente esta pregunta.

Aquí está mi ejemplo de trabajo actual.

    public function update_token($token){

    try {

        $client = new Google_Client();
        $client->setAccessType("offline"); 
        $client->setAuthConfig(APPPATH . 'vendor' . DIRECTORY_SEPARATOR . 'google' . DIRECTORY_SEPARATOR . 'client_secrets.json');  
        $client->setIncludeGrantedScopes(true); 
        $client->addScope(Google_Service_Calendar::CALENDAR); 
        $client->setAccessToken($token);

        if ($client->isAccessTokenExpired()) {
            $refresh_token = $client->getRefreshToken();
            if(!empty($refresh_token)){
                $client->fetchAccessTokenWithRefreshToken($refresh_token);      
                $token = $client->getAccessToken();
                $token['refresh_token'] = json_decode($refresh_token);
                $token = json_encode($token);
            }
        }

        return $token;

    } catch (Exception $e) { 
        $error = json_decode($e->getMessage());
        if(isset($error->error->message)){
            log_message('error', $error->error->message);
        }
    }


}
Dave Spelts
fuente
1

Utilizo google-api-php-client v2.2.2 Obtengo un nuevo token con la fetchAccessTokenWithRefreshToken();llamada a la función sin parámetros, devuelve un token de acceso actualizado y el token actualizado no se pierde.

if ($client->getAccessToken() && $client->isAccessTokenExpired()) {
    $new_token=$client->fetchAccessTokenWithRefreshToken();
    $token_data = $client->verifyIdToken();
}    
Igor Burlov
fuente
1

Debe guardar el token de acceso en el archivo o la base de datos como una cadena json durante la solicitud de autorización inicial y establecer el tipo de acceso en fuera de línea $client->setAccessType("offline")

Luego, durante las solicitudes de API posteriores, tome el token de acceso de su archivo o base de datos y páselo al cliente:

$accessToken = json_decode($row['token'], true);
$client->setAccessToken($accessToken);

Ahora debe verificar si el token ha expirado:

if ($client->isAccessTokenExpired()) {
    // access token has expired, use the refresh token to obtain a new one
    $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
    // save the new token to file or db
    // ...json_encode($client->getAccessToken())

La fetchAccessTokenWithRefreshToken()función hará el trabajo por usted y le proporcionará un nuevo token de acceso, lo guardará de nuevo en su archivo o base de datos.

Sam Thompson
fuente
-1

use el siguiente fragmento de código para obtener su token de actualización

    <?php

    require_once 'src/apiClient.php';
    require_once 'src/contrib/apiTasksService.php';

    $client = new apiClient();
    $client->setAccessType('offline');
    $tasksService = new apiTasksService($client);

    $auth = $client->authenticate();
    $token = $client->getAccessToken();
    // the refresh token
    $refresh_token = $token['refresh_token'];
    ?>
Aymen Mouelhi
fuente