Comment actualiser le jeton avec le client API Google?

91

J'ai joué avec l'API Google Analytics (V3) et j'ai rencontré des erreurs. Tout d'abord, tout est configuré correctement et fonctionne avec mon compte de test. Mais lorsque je veux récupérer des données d'un autre identifiant de profil (même compte Google Accont / GA), j'obtiens une erreur 403. La chose étrange est que les données de certains comptes GA renverront des données tandis que d'autres génèrent cette erreur.

J'ai révoqué le jeton et me suis authentifié une fois de plus, et il semble maintenant que je puisse récupérer les données de tous mes comptes. Problème résolu? Ne pas. Comme la clé d'accès expirera, je rencontrerai à nouveau le même problème.

Si j'ai bien compris les choses, on pourrait utiliser le resfreshToken pour obtenir un nouveau authenticationTooken.

Le problème est que lorsque je cours:

$client->refreshToken(refresh_token_key) 

l'erreur suivante est renvoyée:

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

J'ai vérifié le code derrière la méthode refreshToken et suivi la demande dans le fichier «apiOAuth2.php». Tous les paramètres sont envoyés correctement. Le grant_type est codé en dur sur 'refresh_token' dans la méthode, il m'est donc difficile de comprendre ce qui ne va pas. Le tableau de paramètres ressemble à ceci:

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

La procédure est la suivante.

$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

Est-ce un bug, ou ai-je complètement mal compris quelque chose?

seorch.me
la source
Je ne sais pas si c'est un bogue ou quelque chose du genre, mais je rafraîchis actuellement le jeton d'accès en utilisant une requête http CURL brute et cela fonctionne bien.
gremo
Seorch ... vous avez déjà compris celui-ci? Même problème ici.
Brian Vanderbusch
@gremo pourriez-vous partager la requête http CURL brute que vous avez utilisée ici? Serait vraiment utile. Merci!
Silver Ringvee

Réponses:

76

Alors j'ai finalement compris comment faire ça. L'idée de base est que vous disposez du jeton que vous obtenez la première fois que vous demandez l'authentification. Ce premier jeton a un jeton d'actualisation. Le premier jeton d'origine expire après une heure. Après une heure, vous devez utiliser le jeton d'actualisation du premier jeton pour obtenir un nouveau jeton utilisable. Vous utilisez $client->refreshToken($refreshToken)pour récupérer un nouveau jeton. J'appellerai ce «jeton temporaire». Vous devez également stocker ce jeton temporaire car après une heure, il expire également et notez qu'il n'est pas associé à un jeton d'actualisation. Afin d'obtenir un nouveau jeton temporaire, vous devez utiliser la méthode que vous avez utilisée auparavant et utiliser le jeton d'actualisation du premier jeton. J'ai joint le code ci-dessous, ce qui est moche, mais je suis nouveau dans ce domaine ...

//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
la source
52
Au lieu de vérifier pendant 3600 secondes, vous devriez utiliser $ client-> isAccessTokenExpired ()
Gaurav Gupta
2
Petite mise à jour. Dans la dernière version, lorsque vous demandez un jeton d'actualisation, le nouveau jeton d'accès qui est renvoyé est désormais livré avec un nouveau jeton d'actualisation. Donc, essentiellement, vous pouvez utiliser le jeton json mis à jour pour remplacer le jeton json précédent et vous n'avez plus besoin de conserver le jeton d'accès initial. .
skidadon
1
Notez que $client->isAccessTokenExpired()cela ne vérifiera toujours que les heures tenues localement pour voir s'il pense que le jeton a expiré. Le jeton a peut-être encore expiré et l'application locale ne saura vraiment que lorsqu'elle essaiera de l'utiliser. Dans ce cas, le client API renverra une exception et n'actualisera pas automatiquement le jeton.
Jason
44

Le problème est dans le jeton d'actualisation:

[refresh_token] => 1\/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY

Quand une chaîne avec un '/'obtient json encoded, elle est échappée avec un '\', vous devez donc la supprimer.

Le jeton d'actualisation dans votre cas doit être:

1/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY

Ce que je suppose que vous avez fait, c'est que vous avez imprimé la chaîne json que Google a renvoyée et copié et collé le jeton dans votre code, car si vous json_decodele faites, il supprimera correctement le '\'pour vous!

Asim
la source
1
mention incroyable, a fait ma journée! heures économisées!
Mircea Sandu
Tu as sauvé ma journée!
Truong Dang
J'aimerais pouvoir voter 100 fois. J'étais sur le point de faire un trou dans un mur avec mon clavier après avoir regardé le message "mauvais accord" pendant plusieurs heures après avoir essayé absolument tout pour faire fonctionner le jeton. Fricking google man, pourquoi utiliser des barres obliques, juste pourquoi?
Askerman
18

voici l'extrait de code pour définir le jeton, avant cela, assurez-vous que le type d'accès doit être défini sur hors ligne

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

Pour actualiser le jeton

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

cela actualisera votre token, vous devez le mettre à jour en session pour que vous puissiez le faire

 $_SESSION['access_token']= $client->getAccessToken()
Faishal
la source
1
vous avez fait ma journée avec ça :) merci beaucoup, beaucoup plus simple que je ne le pensais car j'ai passé beaucoup de temps à aller nulle part: D
TB Ygg
16

Le type d'accès doit être défini sur offline. stateest une variable que vous définissez pour votre propre usage, pas pour l'utilisation de l'API.

Assurez-vous que vous disposez de la dernière version de la bibliothèque cliente et ajoutez:

$client->setAccessType('offline');

Voir Formation de l'URL pour une explication des paramètres.

jk.
la source
Merci jk. J'ai téléchargé la dernière version et j'ai révoqué l'accès à l'application pour mon compte. Ensuite, j'ai accordé l'accès une fois de plus et j'ai stocké le accessToken et refreshToken. Le fait est que j'ai toujours reçu un refreshToken, même si setAccessType a été omis. Quoi qu'il en soit, quand j'exécute $ client-> refreshToken (refresh-token-key), j'obtiens toujours l'erreur "invalid_grant". J'ai vérifié l'auth-url et elle est par défaut "force". Si je le change en "auto" et exécute la méthode d'authentification, je ne suis pas redirigé car j'ai déjà accordé l'accès. Mais le respons est un accessToken sans rafraîchissement. Des idées?
seorch.me
@ seorch.me Cela semble fou, mais est-il possible que vous deviez configurer un nouveau $client( $client = new apiClient();) pour utiliser le jeton d'actualisation?
jk.
1
@ seorch.me vous devez définir $client->setApprovalPrompt('force')ainsi que $client->setAccessType('offline')pour obtenir un nouveau jeton d'actualisation lors de l'autorisation. Sans forcer l'utilisateur à approuver l'étendue de l'accès, Google suppose que vous allez continuer à utiliser l'ancien jeton d'actualisation.
Jason
14

La réponse postée par @ uri-weg a fonctionné pour moi mais comme je n'ai pas trouvé ses explications très claires, permettez-moi de la reformuler un peu.

Lors de la première séquence d'autorisation d'accès, dans le rappel, lorsque vous arrivez au point où vous recevez un code d'authentification, vous devez également enregistrer le jeton d'accès et le jeton d'actualisation .

La raison en est que google api vous envoie un jeton d'accès avec un jeton d'actualisation uniquement lorsque vous vous demandez une autorisation d'accès. Les jetons d'accès suivants seront envoyés sans jeton d'actualisation (sauf si vous utilisez l' approval_prompt=forceoption).

Le jeton d'actualisation que vous avez reçu la première fois reste valide jusqu'à ce que l'utilisateur révoque l'autorisation d'accès.

En php simpliste, un exemple de séquence de rappel serait:

// 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']);

Et plus tard, en php simpliste, la séquence de connexion serait:

// 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
la source
parfait, a beaucoup travaillé. la seule chose que je dirais, c'est que vous devriez expliquer que vous devez passer l'objet json et pas seulement le jeton sous forme de chaîne.
Oliver Bayes-Shelton
@ OliverBayes-Shelton Salut. Merci. J'ai pensé que // setAccessToken() expects jsonc'était suffisant. Ou est-ce pour une autre partie du code?
Daishi
Cela fonctionne très bien pour moi, mais savez-vous si ce code gère les situations où un jeton expire en raison du dépassement de la limite de 50 actualisations de jetons? Des détails sur «l'expiration des jetons» sont disponibles ici: développeurs.google.com
identity
Il semble que la dernière version 2.0 renvoie maintenant le jeton d'actualisation dans le tableau de jetons d'accès. Cela signifie que l'enregistrement du jeton d'accès enregistre également le jeton d'actualisation, car le jeton d'actualisation est inclus. En réponse à l'expiration du jeton d'actualisation, je suppose que cela devrait être testé et traité explicitement - rappelez-vous que la limite de 50 est "par utilisateur et par client", c'est-à-dire qu'elle est de 50 par client, il est donc peu probable que vous l'atteigniez, surtout si vous utilisez des étendues incluses pour combiner des jetons.
Brian C du
8

Voici le code que j'utilise dans mon projet et il fonctionne 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;
}
Monsieur green
la source
6

Eu le même problème; mon script qui a fonctionné hier, pour une raison étrange n'a pas fonctionné aujourd'hui. Aucun changement.

Apparemment, c'était parce que mon horloge système était désactivée de 2,5 (!!) secondes, la synchronisation avec NTP l'a corrigé.

Voir aussi: https://code.google.com/p/google-api-php-client/wiki/OAuth2#Solving_invalid_grant_errors

strikernl
la source
Cette réponse m'a beaucoup aidé, mec. Vous m'avez probablement fait gagner beaucoup de temps. Beaucoup! Merci! Je viens de l'exécuter sudo apt-get install ntpsur ma machine Debian pour installer NTP. Il a synchronisé l'horloge et le problème a été résolu.
Szymon Sadło
4

FYI: L'API Google Analytics 3.0 actualisera automatiquement le jeton d'accès si vous disposez d'un jeton d'actualisation lorsqu'il expire afin que votre script n'en ait jamais besoin refreshToken.

(Voir la Signfonction dans auth/apiOAuth2.php)

Mark Smith
la source
"Actualiser automatiquement" signifie que je n'ai qu'à demander getAccessToken () et que je vais en récupérer un actualisé? Mais je dois d'abord définir le jeton d'actualisation hors de la base de données, non? Sinon, l'actualisation fonctionnerait sans jeton d'actualisation et je ne pense pas que cela fonctionnerait
ninsky
4

Parfois, le jeton d'actualisation n'est pas généré en utilisant $client->setAccessType ("offline"); .

Essaye ça:

$client->setAccessType ("offline");
$client->setApprovalPrompt ("force"); 
Meenu Sharma
la source
Pour être plus précis, il semble que le jeton d'actualisation soit inclus dans votre première autorisation. Si vous enregistrez puis utilisez-le, je pense (selon d'autres, non vérifié) que le jeton d'actualisation continue d'être retourné. Le doco indique également maintenant qu'ils actualiseront automatiquement le jeton d'accès s'ils ont un jeton d'actualisation, ce qui signifie qu'il s'agit simplement de gérer le jeton d'actualisation en toute sécurité. setApprovalPrompt ('force') force un jeton d'actualisation à être émis ultérieurement; sans cela, vous n'en aurez pas d'autre.
Brian C
2

J'ai utilisé l'exemple par smartcodes avec la version actuelle de l'API Google, mais celle-ci n'a pas fonctionné. Je pense que son API est trop obsolète.

Donc, je viens d'écrire ma propre version, basée sur l'un des exemples d'API ... Elle génère le jeton d'accès, le jeton de demande, le type de jeton, le jeton d'identification, l'heure d'expiration et l'heure de création sous forme de chaînes

Si vos informations d'identification client et votre clé de développeur sont correctes, ce code devrait fonctionner immédiatement.

<?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
la source
1
S'il vous plaît, pourriez - vous me expliquer pourquoi cette ligne: $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];. Pourquoi vous redirigez vers la même page? est-ce nécessaire?
Tropicalista
@Tropicalista: Il n'est pas nécessaire de recharger la page en soi, mais c'est ainsi que les flux d'authentification sont généralement mis en œuvre.
John Slegers
mais vous n'utilisez pas le jeton d'actualisation pour obtenir un nouveau jeton d'accès si le jeton d'accès a expiré.
apadana le
1

J'ai le même problème avec google / google-api-php-client v2.0.0-RC7 et après une recherche de 1 heures, j'ai résolu ce problème en utilisant json_encode comme ceci:

    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
la source
1

Cela fonctionne très bien ici, peut-être que cela pourrait aider n'importe qui:

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();
}
?>
user1768700
la source
1

Google a apporté quelques modifications depuis la publication de cette question.

Voici mon exemple de travail actuellement.

    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
la source
1

J'utilise google-api-php-client v2.2.2 Je reçois un nouveau jeton avec un fetchAccessTokenWithRefreshToken();appel de fonction if sans paramètres, il renvoie un jeton d'accès mis à jour et le jeton actualisé n'est pas perdu.

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

Vous devez enregistrer le jeton d'accès dans un fichier ou une base de données en tant que chaîne json lors de la demande d'autorisation initiale et définir le type d'accès sur hors ligne $client->setAccessType("offline")

Ensuite, lors des requêtes API suivantes, récupérez le jeton d'accès de votre fichier ou de votre base de données et transmettez-le au client:

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

Vous devez maintenant vérifier si le jeton a expiré:

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()fonction fera le travail pour vous et fournira un nouveau jeton d'accès, le sauvegardera dans votre fichier ou votre base de données.

Sam Thompson
la source
0

Selon l' authentification sur Google: OAuth2 continue de renvoyer «invalid_grant»

"Vous devez réutiliser le jeton d'accès que vous avez obtenu après la première authentification réussie. Vous obtiendrez une erreur invalid_grant si votre jeton précédent n'a pas encore expiré. Mettez-le en cache quelque part afin de pouvoir le réutiliser."

J'espère que ça aide

Jon
la source
-1

utilisez l'extrait de code suivant pour obtenir votre jeton d'actualisation

    <?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
la source