Google api refresh_token null and how to refresh access token

shuba.ivan picture shuba.ivan · Jul 19, 2016 · Viewed 9.4k times · Source

I use HWIO Bundle for google api and when I have response from google refreshToken = null why? How to refresh token

oAuthToken = {HWI\Bundle\OAuthBundle\Security\Core\Authentication\Token\OAuthToken} [11]
accessToken = "ya29.Ci8lA1JTu9CB81dOFy-nzszViRgCI2CvvKVrCd0Lq-8I0QR_dIrl-_7RccdGt1Islg"
rawToken = {array} [4]
 access_token = "ya29.Ci8lA1JTu9CB81dOFy-nzszViRgCI2CvvKVrCd0Lq-8I0QR_dIrl-_7RccdGt1Islg"
 token_type = "Bearer"
 expires_in = 3578
id_token = "xxxxx"
refreshToken = null
expiresIn = 3578
createdAt = 1468957368
tokenSecret = null
resourceOwnerName = null

because in google/apiclient, "version": "1.1.7" in function need refresh_token

 public function getRefreshToken()
 {
  if (array_key_exists('refresh_token', $this->token)) {
    return $this->token['refresh_token'];
  } else {
    return null;
  }
 }

this my access token

{"access_token":"ya29.Ci8lA1JTu9CB81dOFy-nzszViRgCI2CvvKVrCd0Lq-8I0QR_dIrl-_7RccdGt1Islg","token_type":"Bearer","expires_in":3578,"id_token":"xxxx","created":1468957368}

not have refresh token because from google get refreshToken = null or need set null with key refresh token or this dosn't metter ?

    $isExpired = $client->isAccessTokenExpired(); // true (bool Returns True if the access_token is expired.)
    $refresh = $client->getRefreshToken(); //null because not gahe refresh token 

    $client->getGoogleClient()->setAccessType ("offline"); //some  recomendation
    $client->getGoogleClient()->setApprovalPrompt ("force"); //some recomendation

    $isAgainExpired = $client->isAccessTokenExpired(); // still true (expired)

still have exception - 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.

how to refresh token and how to with token get refresh token, for refresh token ?

I try

  • In my code too $client = new Google_Client() but in wrapper, in constructor.
  • I get access token from HWIO bundle:

    hwi_oauth:
    connect:
      account_connector: app.provider.user_provider
    firewall_name: secured_area
    resource_owners:
        google:
            type:                google
            client_id:           xxx.apps.googleusercontent.com
            client_secret:       xxx
            scope:               "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/drive"
    

and after I get access token I set it in DB. Then in Action I create wrapper for google api (new Google Client ()) and set this client my accesss token from DB. How to refresh my access token? I try in action use function google api lib setAccessType and setApprovalPrompt, but not efect

public function __construct(array $config, LoggerInterface $symfonyLogger = null)
{
    // True if objects should be returned by the service classes.
    // False if associative arrays should be returned (default behavior).
    $config['use_objects'] = true;
    $client = new \Google_Client($config);
    if ($symfonyLogger) {
        //BC for Google API 1.0
        if (class_exists('\Google_Logger_Psr')) {
            $googleLogger = new \Google_Logger_Psr($client, $symfonyLogger);
            $client->setLogger($googleLogger);
        } else {
            $client->setLogger($symfonyLogger);
        }
    }
    $client -> setApplicationName($config['application_name']);
    $client -> setClientId($config['oauth2_client_id']);
    $client -> setClientSecret($config['oauth2_client_secret']);
    $client -> setRedirectUri($config['oauth2_redirect_uri']);
    $client -> setDeveloperKey($config['developer_key']);
    $client -> setAccessType ($config['access_type']);
    $client -> setApprovalPrompt ($config['approval_prompt']);

    $this -> client = $client;
}

config this is:

    happy_r_google_api:
    application_name: carbon-quanta-137312
    oauth2_client_id: xxxx.apps.googleusercontent.com
    oauth2_client_secret: xxx
    oauth2_redirect_uri: null
    developer_key: null
    site_name: aog.local.com
    access_type: offline
    approval_prompt: force

and if in action I set to Google Client some parameters this is same if I add constructorI, so what I'am doing wrong ?

Answer

Arithran picture Arithran · Dec 12, 2016

The refresh_token is only returned on the first request. When you refresh the access token a second time it returns everything except the refresh_token and the file_put_contents removes the refresh_token when this happens the second time.

Modifying the code as following will merge in the original access token with the new one (see: array_merge). This way you will be able to preserve your refresh_token for future requests. I have submitted the following fix to Google, hope they update it at some point.

See docs for more info

    // Refresh the token if it's expired.
    if ($client->isAccessTokenExpired()) {
        $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
        $newAccessToken = $client->getAccessToken();
        $accessToken = array_merge($accessToken, $newAccessToken);
        file_put_contents($credentialsPath, json_encode($accessToken));
    }