title: invalid_grant error when requesting OAuth2 access token for Google Cloud Storage REST API using Service Account
body: <p>I am creating an API request (GET bucket) for the storage API and one of the required parameter is the "Authorization" header.</p>
  
  <p>Please note that I am using a <strong>Service Account</strong> to access the API.</p>
  
  <p>I followed the document <a href="https://developers.google.com/accounts/docs/OAuth2ServiceAccount" rel="nofollow">https://developers.google.com/accounts/docs/OAuth2ServiceAccount</a> to get the access token for the "Authorization" header so I could send an authorized request to their REST API. The problem is I am always getting the "invalid_grant" error.</p>
  
  <p>Use this code to check it out:</p>
  
  
  
  <pre><code>&lt;?php
  error_reporting(E_ERROR);
  
  const CLIENT_ID = 'XXXXXXXXXXXX.apps.googleusercontent.com';
  const SERVICE_ACCOUNT = 'XXXXXXXXXXXX@developer.gserviceaccount.com';
  const KEY_FILE = 'XXX.p12';
  
  function get_oauth_access_token()
  {
      $header[alg] = 'RS256';
      $header[typ] = 'JWT';
  
      $header = urlencode(base64_encode(utf8_encode(json_encode($header))));
  
      $assertion_time = time();
  
      $claim[iss] = CLIENT_ID; //also tried SERVICE_ACCOUNT here, no improvement
      $claim[scope] = 'https://www.googleapis.com/auth/devstorage.read_only';
      $claim[aud] = 'https://accounts.google.com/o/oauth2/token';
      $claim[exp] = $assertion_time + 3600;
      $claim[iat] = $assertion_time;
  
      $claim = urlencode(base64_encode(utf8_encode(json_encode($claim))));
  
      $data = $header . '.' . $claim;
  
      $p12 = file_get_contents(KEY_FILE);
      $cert = array();
      openssl_pkcs12_read($p12, $cert, 'notasecret');
      $priv_key_id = openssl_get_privatekey($cert[pkey]);
  
      openssl_sign($data, $signature, $priv_key_id, 'sha256');
  
      $signature = urlencode(base64_encode($signature));
  
      $assertion = $data . '.' . $signature;
  
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, 'https://accounts.google.com/o/oauth2/token');
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
      curl_setopt($ch, CURLOPT_POST, true);
      curl_setopt($ch, CURLOPT_POSTFIELDS, array('grant_type'=&gt;'assertion', 
                                                 'assertion_type'=&gt;'http://oauth.net/grant_type/jwt/1.0/bearer', 
                                                 'assertion'=&gt;$assertion));
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  
  
      $result = curl_exec($ch);
      $error = curl_error($ch);
  
      curl_close($ch);
      var_dump($result);
      var_dump($error);
  }
  
  get_oauth_access_token();
  </code></pre>
  
  <p>Is there anything wrong in this code that causes the "invalid_grant" error?</p>