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

报告相同问题?

悬赏问题

  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)