douzhu3654 2016-01-26 08:17
浏览 270
已采纳

Google API:缺少refresh_token(访问类型=离线)

I'm trying to connect my webapp to google drive. So I'm using PHP with official Github PHP client code [ https://github.com/google/google-api-php-client/tree/v1-master ].

I followed the quickstart [ https://developers.google.com/drive/v2/web/quickstart/php ] for v2, because PHP client is for v2 only.

Then I added a line to request offline access. [See https://developers.google.com/identity/protocols/OAuth2WebServer#offline]

My app code, developed using Yii 1, but it's not important, is:

    $client = new Google_Client();
    $client->setApplicationName("Google Drive Client");
    $client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
    $client->setRedirectUri( Yii::app()->createAbsoluteUrl("site/googleApiLoginCallback") );    

    $client->setAuthConfigFile(CLIENT_SECRET_PATH);
    $client->setAccessType('offline');

    if (file_exists(CREDENTIALS_PATH)) {
        $accessToken = file_get_contents(CREDENTIALS_PATH);
    } else {
        // Request authorization from the user.
        $auth_url = $client->createAuthUrl();
        header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
        Yii::app()->end();
    }   
    $client->setAccessToken($accessToken);

    // Refresh the token if it's expired.
    if ($client->isAccessTokenExpired()) {
        $refresh_token = $client->getRefreshToken();
        // CVarDumper::dump($refresh_token,2,true);
        $client->refreshToken($refresh_token);
        file_put_contents(CREDENTIALS_PATH, $client->getAccessToken());
    }
    return $client;

This is the code for handling the OAuth callback. I simply set the access token received, then redirect to the page.

public function actionGoogleApiLoginCallback($code)
{
    $client = new Google_Client();
    $client->setApplicationName("Google Drive Client");
    $client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
    $client->setRedirectUri( Yii::app()->createAbsoluteUrl("site/googleApiLoginCallback") );    

    $client->setAuthConfigFile(CLIENT_SECRET_PATH);
    $client->setAccessType('offline');

    $accessToken = $client->authenticate($code);
    if(!file_exists(dirname(CREDENTIALS_PATH))) {
      mkdir(dirname(CREDENTIALS_PATH), 0700, true);
    }
    file_put_contents(CREDENTIALS_PATH, $accessToken);

    $preGoogleApiLoginRoute = Yii::app()->user->getState("preGoogleApiLoginRoute", null);
    if ($preGoogleApiLoginRoute) 
    {
        $this->redirect(array( $preGoogleApiLoginRoute ));
    } else  {
        $this->redirect(array("site/index"));
    }
}

When user the first time access the page, my webapp sucessfully redirect to Google Login; user do login, and Google redirect user to my website at site/googleApiLoginCallback. I set the received code as accessToken and redirect user to the page of webapp he come from.

It works.

BUT: After a while, when user came back to the page, tyhe token is expired. When it's executed the $client->getRefreshToken(), it returns a null, so $client->refreshToken() throw the following error because of missing refresh token

Error refreshing the OAuth2 token, message: '{ "error" : "invalid_request", "error_description" : "Missing required parameter: refresh_token" }'

What am I missing or doing wrong?

For reference: this is my json access token. As you can see I've not a field named 'refreshToken' as I expect

{"access_token":"...hiddden...","token_type":"Bearer","expires_in":3600,"created":1453759023}
  • 写回答

2条回答 默认 最新

  • dongzhuo2371 2016-01-26 09:15
    关注

    From this StackOverflow question I see that statement

    in order to obtain a new refresh_token after already receiving one, you will need to send your user back through the prompt, which you can do by setting approval_prompt to force.

    It pointed to this old blog post by Google.

    So I added

    $client->setApprovalPrompt('force');
    

    after

    $client->setAccessType('offline');
    

    And now I've the resfresh token.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮