Google API क्लाइंट के साथ टोकन रीफ़्रेश कैसे करें?


91

मैं Google Analytics API (V3) के साथ खेल रहा हूं और कुछ त्रुटियों में चला गया हूं। सबसे पहले, सब कुछ सही है और मेरे परीक्षण खाते के साथ काम किया है। लेकिन जब मैं किसी अन्य प्रोफाइल आईडी (सेम गूगल अकॉन्ट / जीए अकाउंट) से डेटा हड़पना चाहता हूं तो मुझे 403 त्रुटि मिलती है। अजीब बात यह है कि कुछ जीए खातों से डेटा वापस आ जाएगा जबकि अन्य इस त्रुटि को उत्पन्न करेगा।

मैंने टोकन को रद्द कर दिया है और एक और बार प्रमाणित किया है, और अब ऐसा लगता है कि मैं अपने सभी खातों से डेटा हड़प सकता हूं। समस्या सुलझ गयी? नहीं। जैसे ही एक्सेस कुंजी समाप्त होगी, मैं फिर से उसी मुद्दे पर चलूंगा।

अगर मैंने चीजों को सही समझा है, तो कोई नया प्रमाणीकरण प्राप्त करने के लिए resfreshToken का उपयोग कर सकता है।

समस्या यह है, जब मैं दौड़ता हूं:

$client->refreshToken(refresh_token_key) 

निम्न त्रुटि दी गई है:

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

मैंने रीफ्रेशटोकन विधि के पीछे कोड की जांच की है और अनुरोध को "apiOAuth2.php" फ़ाइल पर वापस ट्रैक किया है। सभी मापदंडों को सही ढंग से भेजा जाता है। अनुदान_टाइप को विधि के भीतर 'ताज़ा_टोकन' के लिए कठोर कोडित किया गया है, इसलिए मेरे लिए यह समझना मुश्किल है कि क्या गलत है। पैरामीटर सरणी इस तरह दिखता है:

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

प्रक्रिया निम्नलिखित है।

$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

क्या यह बग है, या मैंने कुछ गलत समझा है?


पता नहीं कि यह एक बग या कुछ और है, लेकिन मैं वर्तमान में एक कच्चे CURL http अनुरोध का उपयोग करके टोकन को ताज़ा कर रहा हूं और यह ठीक काम कर रहा है।
gremo

बेनाम: Seorch ... तुम यह अभी तक एक आंकड़ा? एक ही मुद्दा यहाँ।
ब्रायन वैंडरबुश 3

@gremo क्या आप यहां उपयोग किए गए कच्चे CURL http अनुरोध को साझा कर सकते हैं? वास्तव में मददगार होगा। धन्यवाद!
सिल्वर रिंगवे

जवाबों:


76

तो मैं अंत में पता लगा कि यह कैसे करना है। मूल विचार यह है कि आपके पास टोकन है जो आपको प्रमाणीकरण के लिए पूछने पर पहली बार मिलता है। इस पहले टोकन में एक ताज़ा टोकन होता है। पहला मूल टोकन एक घंटे के बाद समाप्त हो जाता है। एक घंटे के बाद आपको एक नया प्रयोग करने योग्य टोकन प्राप्त करने के लिए पहले टोकन से ताज़ा टोकन का उपयोग करना होगा। आप $client->refreshToken($refreshToken)एक नया टोकन प्राप्त करने के लिए उपयोग करते हैं । मैं इसे "अस्थायी टोकन" कहूंगा। आपको इस टेम्प टोकन को स्टोर करने की आवश्यकता है क्योंकि एक घंटे के बाद यह समाप्त हो जाता है और ध्यान दें कि इसके साथ जुड़ा हुआ ताज़ा टोकन नहीं है। एक नया अस्थायी टोकन प्राप्त करने के लिए आपको पहले इस्तेमाल की गई विधि का उपयोग करने की आवश्यकता है और पहले टोकन के रिफ्रेशोकेन का उपयोग करें। मैंने नीचे कोड संलग्न किया है, जो बदसूरत है, लेकिन इस पर नए ...

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

52
3600 सेकंड के लिए जाँच करने के बजाय, आपको $ क्लाइंट का उपयोग करना चाहिए- isAccessTokenExpired ()
गौरव गुप्ता

2
छोटा अपडेट। नवीनतम संस्करण में, जब आप रिफ्रेश टोकन का अनुरोध करते हैं, तो जो नया टोकन वापस आता है, वह नए रिफ्रेश टोकन के साथ आता है। इसलिए अनिवार्य रूप से, आप पिछले जक्सन टोकन को बदलने के लिए अपडेट किए गए जूसन टोकन का उपयोग कर सकते हैं, और किसी भी लंबे समय तक शुरुआती टोकन को बनाए रखने की आवश्यकता नहीं है। ।
स्किडडॉन

1
ध्यान दें कि $client->isAccessTokenExpired()यह अभी भी स्थानीय रूप से आयोजित समय की जांच करेगा यह देखने के लिए कि क्या यह टोकन समाप्त हो गया है। टोकन अभी भी समाप्त हो सकता है और स्थानीय एप्लिकेशन को केवल तभी पता चलेगा जब वह इसका उपयोग करने की कोशिश करता है। इस स्थिति में एपीआई क्लाइंट एक अपवाद लौटाएगा, और स्वचालित रूप से टोकन को ताज़ा नहीं करेगा।
जेसन

44

समस्या ताज़ा टोकन में है:

[refresh_token] => 1\/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY

जब एक स्ट्रिंग के साथ एक '/'हो जाता है json encoded, तो यह एक के साथ बच जाता है '\', इसलिए आपको इसे हटाने की आवश्यकता है।

आपके मामले में ताज़ा टोकन होना चाहिए:

1/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY

जो मैंने किया है, उसे मान लें कि आपने json string छपवाई है जिसे google ने वापस भेजा और कॉपी किया और टोकन को अपने कोड में पेस्ट किया क्योंकि अगर आप json_decodeइसे करते हैं तो यह '\'आपके लिए सही तरीके से हटा देगा !


1
अद्भुत उल्लेख, मेरा दिन बना दिया! घंटे बचाया!
मिरिकिया सैंडू

आपने मेरा दिन बचाया!
ट्रूंग डांग

काश मैं इस 100 बार उत्थान कर पाता। मैं टोकन काम करने के लिए पूरी तरह से सब कुछ करने की कोशिश करने के बाद कई घंटों के लिए "खराब अनुदान" संदेश को घूरने के बाद अपने कीबोर्ड के साथ एक दीवार में छेद करने वाला था। गूगल मैन फ्रिकिंग, स्लैश का उपयोग क्यों, बस क्यों?
आस्कर

18

यहाँ टोकन सेट करने के लिए स्निपेट है, इससे पहले कि यह सुनिश्चित करें कि एक्सेस प्रकार ऑफ़लाइन होना चाहिए

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

टोकन रीफ्रेश करने के लिए

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

यह आपके टोकन को ताज़ा करेगा, आपको इसे सत्र में अपडेट करना होगा जो आप कर सकते हैं

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

1
आपने इस दिन के साथ मेरा दिन बनाया :) बहुत बहुत धन्यवाद, एक बहुत अधिक सरल, जितना मैंने सोचा था कि यह होगा कि मैं बहुत समय बिता रहा
हूं

16

पहुंच प्रकार को सेट किया जाना चाहिए offlinestateएक चर है जिसे आप अपने उपयोग के लिए निर्धारित करते हैं, एपीआई के उपयोग के लिए नहीं।

सुनिश्चित करें कि आपके पास क्लाइंट लाइब्रेरी का नवीनतम संस्करण है और इसे जोड़ें:

$client->setAccessType('offline');

मापदंडों की व्याख्या के लिए URL बनाना देखें ।


धन्यवाद jk मैंने अपने खाते के लिए नवीनतम संस्करण डाउनलोड किया है और ऐप तक पहुंच रद्द कर दी है। फिर मैंने एक और बार एक्सेस की अनुमति दी और एक्सेसटॉकेन और रिफ्रेशटोकन को संग्रहीत किया। बात यह है, मुझे हमेशा एक ताज़ा किया गया है, भले ही setAccessType को छोड़ दिया गया हो। किसी भी तरह, जब मैं $ क्लाइंट- रिफ्रेशटोकन (रिफ्रेश-की-की) चलाता हूं, तब भी मुझे "अमान्य_ग्रांट" त्रुटि मिलती है। मैंने ऑरल-यूआरएल की जाँच की है और यह "फोर्स" को डिफॉल्ट करता है। यदि मैं इसे "ऑटो" में बदल देता हूं और प्रमाणित विधि चलाता हूं, तो मुझे पुनर्निर्देशित नहीं किया गया है क्योंकि मैंने पहले ही पहुंच प्रदान कर दी है। लेकिन जिम्मेदारी एक ताज़ा एक के बिना एक accessToken है। कोई विचार?
seorch.me

@ seorch.me पागल लगता है लेकिन क्या यह संभव है कि आपको ताज़ा टोकन का उपयोग करने के लिए एक नया $client( $client = new apiClient();) सेट करना होगा ?
जे.के.

1
@ seorch.me आप सेट करना होगा $client->setApprovalPrompt('force')और साथ ही $client->setAccessType('offline')एक नया ताज़ा प्राधिकरण के दौरान टोकन प्राप्त करने के। उपयोगकर्ता को उपयोग के दायरे को मंजूरी देने के लिए मजबूर किए बिना, Google मानता है कि आप पुराने ताज़ा टोकन का उपयोग करते रहेंगे।
जेसन

14

@ Uri-weg द्वारा पोस्ट किए गए उत्तर ने मेरे लिए काम किया लेकिन जैसा कि मुझे उनके स्पष्टीकरण बहुत स्पष्ट नहीं मिले, मुझे इसे थोड़ा फिर से करने दें।

कॉलबैक में पहले एक्सेस अनुमति अनुक्रम के दौरान, जब आप उस बिंदु पर पहुंचते हैं जहां आपको एक प्रमाणीकरण कोड प्राप्त होता है, तो आपको एक्सेस टोकन और ताज़ा टोकन को भी सहेजना होगा ।

कारण यह है कि Google एपीआई आपको एक ताज़ा टोकन के साथ एक एक्सेस टोकन भेजता है केवल एक्सेस अनुमति के लिए संकेत देते समय। अगली पहुंच टोकन बिना किसी ताज़ा टोकन के भेजी जाएगी (जब तक कि आप approval_prompt=forceविकल्प का उपयोग नहीं करते हैं )।

पहली बार प्राप्त किया गया ताज़ा टोकन तब तक मान्य रहता है जब तक उपयोगकर्ता पहुँच की अनुमति नहीं देता।

सरलीकृत php में, कॉलबैक अनुक्रम का एक उदाहरण होगा:

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

और बाद में, सरलीकृत php में, कनेक्शन अनुक्रम होगा:

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

परिपूर्ण, बहुत काम किया। केवल एक चीज मैं कहूंगा कि आपको समझा देना चाहिए कि आपको एक स्ट्रिंग के रूप में टोकन को नहीं बल्कि जोंस ऑब्जेक्ट को पास करने की आवश्यकता है।
ओलिवर बेयस-शेल्टन

@ ओलिवरबैयस-शेल्टन हाय। धन्यवाद। मुझे लगा // setAccessToken() expects jsonकि पर्याप्त है। या यह कोड के दूसरे भाग के लिए है?
दशी

यह मेरे लिए बहुत अच्छा काम करता है, लेकिन क्या आप जानते हैं कि यह कोड उन स्थितियों को संभालता है जहां एक टोकन 50 टोकन रीफ़्रेश की सीमा से अधिक होने के कारण समाप्त हो जाता है? 'टोकन समाप्ति' के बारे में विवरण यहाँ पाया जा सकता है: Developers.google.com/identity/protocols/OAuth2#expiration
Bjorn

ऐसा लगता है कि नवीनतम 2.0 संस्करण अब एक्सेस टोकन में ताज़ा टोकन लौटा रहा है। इसका मतलब है कि एक्सेस टोकन को बचाने से ताज़ा टोकन भी बचता है, क्योंकि ताज़ा टोकन शामिल है। ताज़ा टोकन समाप्ति के जवाब में, मैं यह अनुमान लगा रहा हूं कि इसके लिए परीक्षण करना होगा और स्पष्ट रूप से हैंडल करना होगा - याद रखें कि 50 सीमा "प्रति ग्राहक प्रति उपयोगकर्ता" है, अर्थात यह 50 प्रति ग्राहक है, इसलिए आपको इसे हिट करने की संभावना नहीं है, खासकर यदि आप टोकन को संयोजित करने के लिए शामिल स्कोप का उपयोग करते हैं।
ब्रायन सी

8

यहाँ कोड है जो मैं अपने प्रोजेक्ट में उपयोग कर रहा हूँ और यह ठीक काम कर रहा है:

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

6

एक ही मुद्दा था; मेरी स्क्रिप्ट जो कल काम करती थी, किसी अजीब कारण से आज नहीं हुई। कोई बदलाव नहीं।

जाहिरा तौर पर ऐसा इसलिए था क्योंकि मेरी प्रणाली की घड़ी 2.5 (!!) सेकंड से बंद थी, एनटीपी ने इसे ठीक किया।

इसे भी देखें: https://code.google.com/p/google-api-php-client/wiki/OAuth2#Solve_invalid_grant_errors


उस जवाब ने मुझे बहुत मदद की, यार। आपने शायद मेरा बहुत समय बचाया। बहुत! धन्यवाद! मैंने सिर्फ sudo apt-get install ntpNTP स्थापित करने के लिए अपने डेबियन मशीन पर अमल किया। इसने घड़ी को सिंक्रनाइज़ किया और समस्या हल हो गई।
सिजमन सादेलो

4

FYI करें: 3.0 Google Analytics API एक्सेस टोकन को स्वचालित रूप से ताज़ा कर देगा यदि आपके पास एक ताज़ा टोकन है, तो यह समाप्त हो जाता है ताकि आपके संदेश को कभी भी ज़रूरत न हो refreshToken

( Signसमारोह देखें auth/apiOAuth2.php)


"स्वचालित रूप से ताज़ा करें" का अर्थ है कि मुझे बस गेटअटैकटन () के लिए पूछना है और मुझे एक ताज़ा वापस मिलेगा? लेकिन मुझे डीबी के बाहर ताज़ा टोकन पहले सेट करना होगा, है ना? अन्यथा ताज़ा एक ताज़ा टोकन के बिना काम करेगा और मुझे नहीं लगता कि यह काम करेगा
ninsky

4

कभी-कभी ताज़ा टोकन मैं उपयोग करके उत्पन्न नहीं होता है $client->setAccessType ("offline");

इसे इस्तेमाल करे:

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

अधिक विशिष्ट होने के लिए, यह ऐसा लगता है कि ताज़ा करें टोकन आपके पहले प्राधिकरण में शामिल है । यदि आप सहेजते हैं और फिर इसका उपयोग करते हैं, तो मेरा मानना ​​है कि (दूसरों के अनुसार, सत्यापित नहीं) कि ताज़ा टोकन वापस आना जारी है। डोको अब यह भी कहता है कि यदि वे ताज़ा टोकन रखते हैं, तो वे एक्सेस टोकन को ऑटो-रिफ्रेश करेंगे, जिसका मतलब है कि यह ताज़ा टोकन को सुरक्षित रूप से प्रबंधित करने का मामला है। setApprovalPrompt ('बल') एक ताज़ा टोकन को बाद में जारी करने के लिए बाध्य करता है; इसके बिना आपको दूसरा नहीं मिलेगा।
ब्रायन C

2

मैंने Google API के वर्तमान संस्करण के साथ स्मार्टकोड द्वारा उदाहरण का उपयोग किया था, लेकिन यह काम नहीं किया। मुझे लगता है कि उनका एपीआई बहुत पुराना है।

इसलिए, मैंने अभी अपना खुद का संस्करण लिखा है, जो कि एपीआई उदाहरणों में से एक पर आधारित है ... यह एक्सेस टोकन, रिक्वेस्ट टोकन, टोकन टाइप, आईडी टोकन, एक्सपायरी टाइम और स्ट्रेंथ टाइम को स्ट्रिंग्स के रूप में आउटपुट करता है।

यदि आपके क्लाइंट क्रेडेंशियल और डेवलपर कुंजी सही हैं, तो यह कोड बॉक्स से बाहर काम करना चाहिए।

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

1
कृपया, क्या आप मुझे समझा सकते हैं कि यह पंक्ति क्यों $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];:। आप एक ही पृष्ठ पर पुनर्निर्देशित क्यों करते हैं? क्या यह आवश्यक है?
ट्रॉपिकलिस्टा

@ ट्रॉपिकलिस्टा: प्रति पेज को फिर से लोड करना आवश्यक नहीं है, लेकिन इस तरह से प्रमाणीकरण प्रवाह आमतौर पर लागू किया जाता है।
जॉन सलेगर्स

लेकिन यदि आप टोकन की पहुँच समाप्त हो गई है, तो आप नए टोकन प्राप्त करने के लिए ताज़ा टोकन का उपयोग नहीं कर रहे हैं।
अपदाना

1

मुझे google / google-api-php-client v2.0.0-RC7 के साथ एक ही समस्या है और 1 घंटे की खोज के बाद, मैंने इस समस्या को json_encode का उपयोग करके इस तरह हल किया :

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

1

यह यहाँ बहुत अच्छा काम करता है, शायद यह किसी की मदद कर सकता है:

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

1

मूल रूप से इस प्रश्न के पोस्ट किए जाने के बाद से Google ने कुछ बदलाव किए हैं।

यहाँ मेरा वर्तमान में काम कर रहा उदाहरण है।

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


}

1

मैं google-api-php-client v2.2.2 का उपयोग करता हूं। मुझे एक नया टोकन मिलता है fetchAccessTokenWithRefreshToken();अगर फ़ंक्शन कॉल बिना परमेस के होता है, तो यह एक अद्यतन एक्सेस टोकन लौटाता है और ताज़ा टोकन खो नहीं जाता है।

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

1

आपको प्रारंभिक प्राधिकरण अनुरोध के दौरान एक जेंस स्ट्रिंग के रूप में फ़ाइल या डेटाबेस तक पहुंच टोकन को बचाने की आवश्यकता है, और एक्सेस प्रकार को ऑफ़लाइन पर सेट करें $client->setAccessType("offline")

फिर, बाद में एपीआई अनुरोधों के दौरान, अपनी फ़ाइल या डीबी से एक्सेस टोकन को पकड़ो और इसे क्लाइंट को पास करें:

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

अब आपको जांचना होगा कि टोकन समाप्त हो गया है या नहीं:

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

fetchAccessTokenWithRefreshToken()फ़ंक्शन आपके लिए काम करेगा और एक नया एक्सेस टोकन प्रदान करेगा, इसे अपनी फ़ाइल या डेटाबेस में वापस सहेजें।


0

Google पर प्रमाणीकरण के अनुसार : OAuth2 'अमान्य_grant' लौटाता है

"आपको पहले सफल प्रमाणीकरण के बाद आपको प्राप्त टोकन का पुन: उपयोग करना चाहिए। यदि आपका पिछला टोकन अभी तक समाप्त नहीं हुआ है, तो आपको एक अवैध_गर्भ त्रुटि मिलेगी। इसे कहीं और कैश करें ताकि आप इसे पुन: उपयोग कर सकें।"

आशा करता हूँ की ये काम करेगा


-1

अपने ताज़ा टोकन प्राप्त करने के लिए निम्न कोड स्निपेट का उपयोग करें

    <?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'];
    ?>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.