17
votes

I have a web based application which use Google OAuth2.0 as the login framework. It works nicely previously until yesterday. The applcation couldn't get the refresh token after the access token expired. Besides that, the "Request for permission" page had change to "Have offline access" instead of "Know who you are on Google" and "View you email"

Originally, the "Request for permission" page will request the access to "Know who you are on Google" and "View you email". After user logout and attempts second login, the "Request for permission" page will be the same too.

However, until yesterday, the "Request for permission" page changed to "Have offline access". After the access token is expired, I got the error messsage below:

PHP Fatal error: Uncaught exception 'Google_AuthException' with message 'The OAuth 2.0 access token has expired, and a refresh token is not available. Refresh tokens are not returned for responses that were auto-approved.' in /home2/xxxx/public_html/test/google-api-php-client/src/auth/Google_OAuth2.php:221

I tried $client->setAccessType('online'); . However, I still got this fatal error with me. Below is my code to get the access token :

    if ($client->getAccessToken()) {
      $token = $client->getAccessToken();
      $authObj = json_decode($token);
      $refreshToken = $authObj->refresh_token;
      $user = $oauth2->userinfo->get();
      $me = $plus->people->get('me');
      $email = filter_var($user['email'], FILTER_SANITIZE_EMAIL); // get the USER EMAIL ADDRESS using OAuth2

      $optParams = array('maxResults' => 100);
      $activities = $plus->activities->listActivities('me', 'public', $optParams);


      $_SESSION['access_token'] = $client->getAccessToken();
    } else {
      $authUrl = $client->createAuthUrl();
    }

I tried to search for similar problem like me but I couldn't find one. This happened since yesterday. Before this, I never made any change on the codes.

3
As far as i know, they changed a little bit their security management. If you now give access to an app, Google knows for the future, what permissions you asked for and saves them and you're only asked again, if you want to have new permissions or offline access. I think, that was a temporary bug whilst they have been updating their system, because i don't experience any problems right now.user2897701
Update: You're right, I also can't use refresh tokens anymore...user2897701
Can you tell me how to get rid of this?Akilsree1

3 Answers

18
votes

With his comments, Fabian Parzefall helped me getting this fixed.

Here's my script :

if($client->isAccessTokenExpired()) {

    $authUrl = $client->createAuthUrl();
    header('Location: ' . filter_var($authUrl, FILTER_SANITIZE_URL));

}

It's actually pretty simple. Instead of asking him to click the "connect me" button (as put by the demo script provided by the GA API team), I redirect him directly. Not sure if it's the proper/safer way, but that's the one working for me right now!

3
votes
  if($client->isAccessTokenExpired()) {

     $client->authenticate();
     $NewAccessToken = json_decode($client->getAccessToken());
     $client->refreshToken($NewAccessToken->refresh_token);

    }
2
votes

The answer above is 'correct' but I faffed around working out where to put it(!)... so post this for any one else trying out examples that end up with tokens expiring(!).

Once your code has done whatever token stuff it needs, and your client has an access token... then check it is still valid and if not send off for reauthorisation!

// Stuff to do with getting tokens and storing in session etc...

if ($client->getAccessToken()) { // Hey! we got one!
    if($client->isAccessTokenExpired()) { // Oh! its not good - go for another
        $authUrl = $client->createAuthUrl();
        header('Location: ' . filter_var($authUrl, FILTER_SANITIZE_URL));
        exit();
    }
  try{
...
     }