Google OAuth2 returns "invalid_grant" - signing JWT issue
<p>I've a OAuth2 java client that is trying to create a JWT and then sign with a private key (from Google API console) - follow these pages  <a href="https://developers.google.com/accounts/docs/OAuth2ServiceAccount" rel="nofollow">https://developers.google.com/accounts/docs/OAuth2ServiceAccount</a>. However, google OAuth2 keeps returning "invalid grant".</p>

<p>Here is the client code to sign the JWT:</p>

<pre><code>    package com.oauth2.google.app.url;

    import java.io.FileInputStream;

    import java.security.KeyStore;
    import java.security.PrivateKey;
    import java.security.Signature;

    import java.text.MessageFormat;

    import org.apache.commons.codec.binary.Base64;


    public class WebToken
    {  
      private String iss;
      private String prn;
      private String scope;
      private String aud;
      private long exp;
      private long iat;
      private String keystoreLoc;
      private String keyAlias;

      public WebToken(String iss, String prn, String scope, String aud, long exp, long iat, String keystore,
                          String keyAlias)
      {
        super();
        this.iss = iss;
        this.prn = prn;
        this.scope = scope;
        this.aud = aud;
        this.exp = exp;
        this.iat = iat;
        this.keystoreLoc = keystore;
        this.keyAlias = keyAlias;
      }

      /**
       * Performs base64-encoding of input bytes.
       *
       * @param rawData * Array of bytes to be encoded.
       * @return * The base64 encoded string representation of rawData.
       */
      public static String encodeBase64(byte[] rawData)
      {
        byte[] data = Base64.encodeBase64(rawData);

        return new String(data);
      }

      public String getToken()
        throws Exception
      {
        String header = "{\"alg\":\"RS256\",\"typ\":\"JWT\"}";
        //String header = "{\"alg\":\"RS256\"}";
        String claimTemplate = "'{'\"iss\": \"{0}\", \"prn\": \"{1}\", \"scope\": \"{2}\", \"aud\": \"{3}\", \"exp\": {4}, \"iat\": {5}'}'";

        StringBuffer token = new StringBuffer();

        //Encode the JWT Header and add it to our string to sign
        token.append(encodeBase64(header.getBytes("UTF-8")));

        //Separate with a period
        token.append(".");

        //Create the JWT Claims Object
        String[] claimArray = new String[6];
        claimArray[0] = this.iss;
        claimArray[1] = this.prn;
        claimArray[2] = this.scope;
        claimArray[3] = this.aud;
        claimArray[4] = "" + this.exp;
        claimArray[5] = "" + this.iat;

        MessageFormat claims = new MessageFormat(claimTemplate);
        String payload = claims.format(claimArray);
        print(payload);

        //Add the encoded claims object
        token.append(encodeBase64(payload.getBytes("UTF-8")));

        //Load the private key from a keystore
        KeyStore keystore = KeyStore.getInstance("JKS");
        keystore.load(new FileInputStream(this.keystoreLoc), "welcome1".toCharArray());
        PrivateKey privateKey = (PrivateKey) keystore.getKey(keyAlias, "notasecret".toCharArray());

        //Sign the JWT Header + "." + JWT Claims Object
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(token.toString().getBytes("UTF-8"));
        byte[] sig = signature.sign();
        String signedPayload = encodeBase64(sig);

        //Separate with a period
        token.append(".");

        //Add the encoded signature
        token.append(signedPayload);

        return token.toString();
      }

      public static void print(String msg)
      {
        System.out.println(msg);
      }

      public static void main(String[] args)
        throws Exception
      {
        String iss = "17560ddd122-nggij305nchhs76pge045jg9u1f4567k@developer.gserviceaccount.com";
        String prn = "test123@ggmail.com";
        String scope = "https://www.googleapis.com/auth/urlshortener";
        String aud = "https://accounts.google.com/o/oauth2/token";
        long iat =  System.currentTimeMillis()/1000 - 60;
        long exp =  iat + 3600;
        String keystoreLoc = "D:\\keystore.jks";
        String keyAlias = "privatekey";

        WebToken jwt = new WebToken(iss, prn, scope, aud, exp, iat, keystoreLoc, keyAlias);
        String token = jwt.getToken();
        print(token);
      }
    }
</code></pre>

<p>Then use curl to get token:
    curl -k -vSs -X POST -d "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&amp;assertion=" <a href="https://accounts.google.com/o/oauth2/token" rel="nofollow">https://accounts.google.com/o/oauth2/token</a></p>

<p>Any idea on what's wrong?</p>
