title: Google OAuth 2.0 refresh token for web application with public access
body: <p>I'm getting the following error:</p>
  
  <blockquote>
    <p>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</p>
  </blockquote>
  
  <p>I have a web application which only my server will be accessing, the initial auth works fine, but after an hour, the aforementioned error message pops up. My script looks like this:</p>
  
  <pre><code>require_once 'Google/Client.php';     
  require_once 'Google/Service/Analytics.php';       
  session_start();
  
  $client = new Google_Client();
  $client-&gt;setApplicationName("Client_Library_Examples");
  $client-&gt;setDeveloperKey("{MY_API_KEY}");
  $client-&gt;setClientId('{MY_CLIENT_ID}.apps.googleusercontent.com');
  $client-&gt;setClientSecret('{MY_KEY}');
  $client-&gt;setRedirectUri('{MY_REDIRECT_URI}');
  $client-&gt;setScopes(array('https://www.googleapis.com/auth/gmail.readonly'));
  
  if (isset($_GET['code'])) {
      $client-&gt;authenticate($_GET['code']);  
      $_SESSION['token'] = $client-&gt;getAccessToken();
      $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
      header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
  }
  
  if (!$client-&gt;getAccessToken() &amp;&amp; !isset($_SESSION['token'])) {
      $authUrl = $client-&gt;createAuthUrl();
      print "&lt;a class='login' href='$authUrl'&gt;Connect Me!&lt;/a&gt;";
  }
  </code></pre>
  
  <p>How can I set up a refresh token for this?</p>
  
  <p><strong>Edit 1:</strong> I've tried doing this with a Service account as well. I followed the documentation available on GitHub:</p>
  
  <p><a href="https://github.com/google/google-api-php-client/blob/master/examples/service-account.php" rel="nofollow noreferrer">https://github.com/google/google-api-php-client/blob/master/examples/service-account.php</a></p>
  
  <p>My script looks like this:</p>
  
  <pre><code>session_start();
  include_once "templates/base.php";
  require_once 'Google/Client.php';
  require_once 'Google/Service/Gmail.php';
  $client_id = '{MY_CLIENT_ID}.apps.googleusercontent.com'; 
  $service_account_name = '{MY_EMAIL_ADDRESS}@developer.gserviceaccount.com ';
  $key_file_location = 'Google/{MY_KEY_FILE}.p12';
  echo pageHeader("Service Account Access");
      if ($client_id == ''
  || !strlen($service_account_name)
  || !strlen($key_file_location)) {
    echo missingServiceAccountDetailsWarning();
  }
  $client = new Google_Client();
  $client-&gt;setApplicationName("Client_Library_Examples");
  $service = new Google_Service_Gmail($client);
  if (isset($_SESSION['service_token'])) {
    $client-&gt;setAccessToken($_SESSION['service_token']);
  }
  $key = file_get_contents($key_file_location);
  $cred = new Google_Auth_AssertionCredentials(
      $service_account_name,
      array('https://www.googleapis.com/auth/gmail.readonly'),
      $key
  );
  $client-&gt;setAssertionCredentials($cred);
  if($client-&gt;getAuth()-&gt;isAccessTokenExpired()) {
    $client-&gt;getAuth()-&gt;refreshTokenWithAssertion($cred);
  }
  </code></pre>
  
  <p>This returns the following message:</p>
  
  <blockquote>
    <p>Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }''</p>
  </blockquote>
  
  <p>After tracking this code to it's source, which can be found in <code>Google/Auth/OAuth2.php</code></p>
  
  <p>The method in question, <code>refreshTokenRequest</code>:</p>
  
  <pre><code>private function refreshTokenRequest($params)
  {
      $http = new Google_Http_Request(
      self::OAUTH2_TOKEN_URI,
      'POST',
      array(),
      $params
      );
      $http-&gt;disableGzip();
      $request = $this-&gt;client-&gt;getIo()-&gt;makeRequest($http);
  
      $code = $request-&gt;getResponseHttpCode();
      $body = $request-&gt;getResponseBody();
      if (200 == $code) {
        $token = json_decode($body, true);
        if ($token == null) {
          throw new Google_Auth_Exception("Could not json decode the access token");
        }
  
        if (! isset($token['access_token']) || ! isset($token['expires_in']))     {
          throw new Google_Auth_Exception("Invalid token format");
        }
  
        if (isset($token['id_token'])) {
          $this-&gt;token['id_token'] = $token['id_token'];
        }
        $this-&gt;token['access_token'] = $token['access_token'];
        $this-&gt;token['expires_in'] = $token['expires_in'];
        $this-&gt;token['created'] = time();
      } else {
        throw new Google_Auth_Exception("Error refreshing the OAuth2 token, message: '$body'", $code);
      }
    }
  </code></pre>
  
  <p>Which means that the <code>$code</code> variable is NULL.
  I found this post on SO:</p>
  
  <p><a href="https://stackoverflow.com/questions/23590164/error-refreshing-the-oauth2-token-error-invalid-grant">Error refreshing the OAuth2 token { “error” : “invalid_grant” }</a></p>
  
  <p>And can see that there is still no prefered solution. <strong>This is driving me nuts.</strong> There is very little to no documentation available on this and if anybody has a solution, I'm sure I'm not the only one looking for it.</p>