googleapis / google-api-php-client

A PHP client library for accessing Google APIs
Apache License 2.0
9.2k stars 3.52k forks source link

Google does not return refresh token and the token does not refresh automatically #2591

Closed Guervyl closed 3 weeks ago

Guervyl commented 1 month ago

Environment details

Steps to reproduce

  1. Generate the auth link:
            $client->setAccessType('offline');
            $client->addScope(\Google\Service\Calendar::CALENDAR_EVENTS);
            $client->addScope(\Google\Service\Calendar::CALENDAR);
            $client->setRedirectUri($redirectUri);
            $client->setIncludeGrantedScopes(true);

            $client->createAuthUrl();
  1. Fetch the token:
            $client->setAccessType('offline');
            $tokens = $client->fetchAccessTokenWithAuthCode($code);

This is the generated link https://accounts.google.com/o/oauth2/v2/auth/oauthchooseaccount?response_type=code&access_type=offline&client_id=

But, In the json there is no refresh_token. It only returns access_token. And the access token expires 1 hour later and I have to go and repeat the auth process again. Wich is not the case of my app. Because the token is being used in API.

Thanks!

Lucas-Mondini commented 1 month ago

I have the same problem

Guervyl commented 1 month ago

No one?

mdespeuilles commented 1 month ago

I had the same problem. You have to put :

$client->setAccessType('offline');

Before generating the authorisation url

$client = new Client(); $client->setClientId($this->parameterBag->get('app.google_client_id')); $client->setClientSecret($this->parameterBag->get('app.google_client_secret')); $client->addScope("https://mail.google.com"); $client->setRedirectUri("https://localhost/api/gmail/connect"); $client->setAccessType('offline'); $service = new Gmail($client);

    if ($request->query->get('code')) {
        $token = $client->fetchAccessTokenWithAuthCode($request->query->get('code'));
        $client->setAccessToken($token);
        ........
    }

    $authUrl = $client->createAuthUrl();

    return $this->redirect($authUrl);
aasa commented 1 month ago

I have the same problem and I also did put the setAccessType before createAuthUrl() but still do not work.

I have 2 functions, one to generate the Auth Url

public function createAuthUrl()
{
        $client = new Client();
        $client->setAuthConfig(ADMIN . '/config/google_api_credentials.json');
        $client->addScope('https://www.googleapis.com/auth/adwords');
        $client->setAccessType("offline");
        $client->setApprovalPrompt('force');
        $client->setRedirectUri($this->admin_site_url . $this->app['url_generator']->generate('google.oauth2.authorization-callback'));
        return $client->createAuthUrl();
}

And another as callback:

public function getTokensFromAuthCode($auth_code)
    {
        $client = new Client();
        $client->setAuthConfig(ADMIN . '/config/google_api_credentials.json');

        $client->addScope('https://www.googleapis.com/auth/adwords');
        $client->setAccessType("offline");
        $client->setApprovalPrompt('force');
        $client->setRedirectUri($this->admin_site_url . $this->app['url_generator']->generate('google.oauth2.authorization-callback'));
        $tokens = $client->fetchAccessTokenWithAuthCode($auth_code);
        $client->setAccessToken($tokens);

        return $tokens;
    }
aasa commented 1 month ago

Ok, i was able to get the refresh token, by some reason, google only sends you the refresh token for the first time you consent/allow the permission.

So you already give the consent/allow you need to revoke the access token, you can do that by going to your google account and removing the permission or with the access token you can revoke that:

$client->revokeToken($client->getAccessToken());

The time you request the token the google will send you the refresh token.

There is also some claims that this behaviour only happens with some language libs

Check More: https://stackoverflow.com/questions/10827920/not-receiving-google-oauth-refresh-token

Hectorhammett commented 3 weeks ago

Thanks for clarifying the solution.

Doing some research it seems that revoking the access token is the correct way: https://stackoverflow.com/questions/67016594/how-to-get-refresh-token-for-login-with-google-api