title: Trouble with JWT and PHP
body: <p>I need to get an access token for my service account, that was created in my google console to get private access for google spreadsheet service!</p>
  
  <p>My php file for testing:</p>
  
  <pre><code>&lt;?php
  
  function base64_url_encode($input) {
      return strtr(str_replace('=', '', base64_encode($input)), '+/', '-_');
  }
  
  header('Content-type: text/plain');
  
  $header = '{"alg":"RS256","typ":"JWT"}';
  
  $payload =
  '{
    "iss":"[my service account]@[my project name].iam.gserviceaccount.com",
    "scope":"https://www.googleapis.com/auth/spreadsheets",
    "aud":"https://www.googleapis.com/oauth2/v4/token",
    "exp":'.(time() + 3600).',
    "iat":'.(time()).'
  }';
  
  
  include('Crypt/RSA.php');
  
  $rsa = new Crypt_RSA();
  
  $private_key = "-----BEGIN PRIVATE KEY-----[my private key from google console json file of my service account]-----END PRIVATE KEY-----\n";
  
  //$rsa-&gt;setPassword('password');
  $rsa-&gt;loadKey($private_key); // private key
  
  $plaintext = base64_url_encode($header).'.'.base64_url_encode($payload);
  
  $rsa-&gt;setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
  $signature = $rsa-&gt;sign($plaintext);
  
  //$rsa-&gt;loadKey($rsa-&gt;getPublicKey()); // public key
  //echo $rsa-&gt;verify($plaintext, $signature) ? 'verified' : 'unverified';
  
  $jwt =  base64_url_encode($header).'.'.base64_url_encode($payload).'.'.base64_url_encode($signature);
  
  
  
  $query = http_build_query(Array('grant_type' =&gt; 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' =&gt; $jwt));
  
  //echo $query;
  
  $options = array(
      'http' =&gt; array(
          'header'  =&gt; "Content-type: application/x-www-form-urlencoded\r\n",
          'method'  =&gt; 'POST',
          'content' =&gt; $query
      )
  );
  
  $context  = stream_context_create($options);
  
  $access_token = file_get_contents('https://www.googleapis.com/oauth2/v4/token', false, $context);
  
  ?&gt;
  </code></pre>
  
  <p>The php output:</p>
  
  <pre><code>file_get_contents(https://www.googleapis.com/oauth2/v4/token) [&lt;a href='function.file-get-contents'&gt;function.file-get-contents&lt;/a&gt;]: failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request
  </code></pre>
  
  <p>If I run the same query in wfetch ("$query" variable from php script):</p>
  
  <pre><code>HTTP/1.1 400 Bad Request\r\n
  {\n
   "error": "invalid_grant",\n
   "error_description": "Invalid JWT Signature."\n
  }\n
  </code></pre>
  
  <p>P.S. My php version is PHP 5.2 (without of namespace support), also phpseclib1.0.3 used.</p>
  
  <p>P.P.S. Tryed to change RS256 to HS256 and google still response 400 - Invalid JWT Signature, but if change to nonexistent XX256 (for example) -> google response 500 - error: internal_failure. So I think may be google also supports HS256. If it's true - I can use mutch more simple HS256 method. And I found this: <a href="https://github.com/progrium/php-jwt/blob/master/JWT.php" rel="nofollow">https://github.com/progrium/php-jwt/blob/master/JWT.php</a></p>