php oauth - Wie kann ein Token mit dem Google API-Client aktualisiert werden?




refresh id (13)

Manchmal Refresh Token ich nicht mit $client->setAccessType ("offline"); generiert $client->setAccessType ("offline"); .

Versuche dies:

$client->setAccessType ("offline");
$client->setApprovalPrompt ("force"); 

Ich habe mit der Google Analytics-API (V3) herumgespielt und bin auf einige Fehler gestoßen. Erstens ist alles korrekt eingerichtet und hat mit meinem Testkonto funktioniert. Aber wenn ich Daten von einer anderen Profil-ID (dasselbe Google Accont / GA-Konto) abrufen möchte, erhalte ich einen Fehler 403. Das Merkwürdige ist, dass Daten von einigen GA-Konten Daten zurückgeben, während andere diesen Fehler generieren.

Ich habe das Token zurückgenommen und erneut authentifiziert, und jetzt scheint es, als könnte ich Daten von allen meinen Konten abrufen. Problem gelöst? Nicht. Da der Zugriffsschlüssel abläuft, werde ich wieder auf dasselbe Problem stoßen.

Wenn ich die Dinge richtig verstanden habe, könnte man mit dem resfreshToken einen neuen AuthenticationTooken bekommen.

Das Problem ist, wenn ich renne:

$client->refreshToken(refresh_token_key) 

Der folgende Fehler wird zurückgegeben:

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

Ich habe den Code hinter der refreshToken-Methode überprüft und die Anfrage zurück zur Datei "apiOAuth2.php" verfolgt. Alle Parameter werden korrekt gesendet. Der Grant_Type ist in der Methode fest auf "Refresh_Token" programmiert, so dass es mir schwer fällt zu verstehen, was falsch ist. Das Parameter-Array sieht so aus:

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

Das Verfahren ist wie folgt.

$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

Ist das ein Fehler oder habe ich etwas völlig falsch verstanden?


Ich habe das Beispiel von Smartcodes mit der aktuellen Version der Google API verwendet, aber das hat nicht funktioniert. Ich denke seine API ist zu veraltet.

Also habe ich meine eigene Version geschrieben, basierend auf einem der API-Beispiele ... Es gibt Zugangstoken, Anforderungs-Token, Token-Typ, ID-Token, Ablaufzeit und Erstellungszeit als Zeichenfolgen aus

Wenn Ihre Client-Anmeldeinformationen und Ihr Entwicklerschlüssel korrekt sind, sollte dieser Code sofort funktionieren.

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

Hier ist das Snippet, um das Token zu setzen. Vorher muss sichergestellt werden, dass der Zugriffstyp auf offline gesetzt ist

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

Um das Token zu aktualisieren

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

Dadurch wird Ihr Token aktualisiert. Sie müssen es in der Sitzung aktualisieren, damit Sie es tun können

 $_SESSION['access_token']= $client->getAccessToken()

Das hier funktioniert sehr gut, vielleicht könnte es jedem helfen:

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();
}
?>

Die Antwort, die von @ uri-weg gepostet wurde, hat für mich funktioniert, aber da ich seine Erklärungen nicht sehr klar fand, lass es mich ein wenig umschreiben.

Während der ersten Zugriffsberechtigungssequenz müssen Sie beim Rückruf an dem Punkt, an dem Sie einen Authentifizierungscode erhalten , das Zugriffstoken und das Aktualisierungstoken speichern .

Der Grund dafür ist, dass Google API Ihnen nur dann ein Zugriffstoken mit einem Aktualisierungstoken sendet, wenn Sie nach Zugriffsberechtigungen gefragt werden. Die nächsten Zugriffstoken werden ohne Aktualisierungstoken gesendet (es sei denn, Sie verwenden die Option approval_prompt=force ).

Das Aktualisierungstoken, das Sie zum ersten Mal erhalten haben, bleibt gültig, bis der Benutzer die Zugriffsberechtigung entzieht.

Im vereinfachten PHP wäre ein Beispiel für die Callback-Sequenz:

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

Und später, in vereinfachten PHP, wäre die Verbindungssequenz:

// 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());
}

Also habe ich endlich herausgefunden, wie das geht. Die Grundidee ist, dass Sie das Token haben, das Sie erhalten, wenn Sie zum ersten Mal nach einer Authentifizierung fragen. Dieses erste Token hat ein Aktualisierungstoken. Das erste ursprüngliche Token läuft nach einer Stunde ab. Nach einer Stunde müssen Sie das Aktualisierungstoken des ersten Tokens verwenden, um ein neues verwendbares Token zu erhalten. Sie verwenden $client->refreshToken($refreshToken) , um ein neues Token abzurufen. Ich werde das "Temp Token" nennen. Sie müssen dieses temporäre Token ebenfalls speichern, da es nach einer Stunde ebenfalls abläuft und nicht mit einem Aktualisierungs-Token verknüpft ist. Um ein neues temporäres Token zu erhalten, müssen Sie die Methode verwenden, die Sie zuvor verwendet haben, und die ersten Token-Token verwenden. Ich habe unten einen Code angehängt, der hässlich ist, aber ich bin neu in diesem ...

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


Laut Authentifizierung bei Google: OAuth2 gibt immer 'invalid_grant' zurück

"Sie sollten das Zugriffstoken, das Sie nach der ersten erfolgreichen Authentifizierung erhalten haben, erneut verwenden. Sie erhalten einen invalid_grant-Fehler, wenn Ihr vorheriges Token noch nicht abgelaufen ist. Speichern Sie es irgendwo, damit Sie es wiederverwenden können."

ich hoffe es hilft


Hier ist der Code, den ich in meinem Projekt verwende und es funktioniert gut:

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;
}

Verwenden Sie das folgende Code-Snippet, um Ihr Aktualisierungstoken zu erhalten

    <?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'];
    ?>

Ich habe das gleiche Problem mit Google / Google-API-Client 2.0.0-RC7 und nach der Suche nach 1 Stunden, löste ich dieses Problem mit json_encode wie folgt :

    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()));
    }

Der Zugriffstyp sollte auf offline . state ist eine Variable, die Sie für Ihre eigene Verwendung festlegen, nicht die Verwendung der API.

Stellen Sie sicher, dass Sie über die neueste Version der Clientbibliothek verfügen, und fügen Sie Folgendes hinzu:

$client->setAccessType('offline');

Siehe Erstellen der URL für eine Erläuterung der Parameter.


Für diejenigen, die nicht sicher sind, wie man PDO verwendet (von den mysql_Funktionen kommt), habe ich einen sehr einfachen PDO-Wrapper erstellt , der eine einzige Datei ist. Es gibt zu zeigen, wie einfach es ist, all die üblichen Dinge zu erledigen, in denen Anwendungen ausgeführt werden müssen. Funktioniert mit PostgreSQL, MySQL und SQLite.

Im Grunde genommen, lesen Sie es , PDO , um zu sehen , wie die PDO - Funktionen setzen im wirklichen Leben zu verwenden , um es einfach zu speichern und abzurufen Werte im Format Sie mögen.

Ich möchte eine einzelne Kolumne

$count = DB::column('SELECT COUNT(*) FROM `user`);

Ich möchte ein Array (key => value) ergebnisse (zB für eine selectbox)

$pairs = DB::pairs('SELECT `id`, `username` FROM `user`);

Ich möchte ein einziges Reihenergebnis

$user = DB::row('SELECT * FROM `user` WHERE `id` = ?', array($user_id));

Ich möchte eine Reihe von Ergebnissen

$banned_users = DB::fetch('SELECT * FROM `user` WHERE `banned` = ?', array(TRUE));




php google-api oauth-2.0 access-token google-analytics-api