I am trying to create a JSON Web Token in order to use it for making refresh token call with Google Analytics API access. I have taken service account approach.
As per this approach I need to :
I am not sure whether my approach of creating JWT is correct or not. The sample available as JWT_Handler.java
on the Google Code site talks about creating JWT with claim part and request payload only with header and signature part missing. This is confusing with googles guidelines for creating JWT for refresh token where the JWT involves three parts :
All the three parts are Base64Url encoded. I tried following code :
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.nio.charset.Charset;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.Calendar;
import java.util.Enumeration;
import com.google.api.client.util.Base64;
import com.google.gson.JsonObject;
public class TestJWT {
private final static Charset UTF8_CHARSET = Charset.forName("UTF-8");
private static KeyStore myStore = null;
private static FileInputStream in_cert = null;
public static void main(String[] args) {
PrivateKey privateKey = null;
try {
in_cert = new FileInputStream(
"D://Google Analytics//ClientLogin//Analytics//%$%%$%$%-privatekey.p12");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
myStore = KeyStore.getInstance("PKCS12");
myStore.load(in_cert, "notasecret".toCharArray());
String alias = "";
Enumeration objEnumeration = myStore.aliases();
while (objEnumeration.hasMoreElements() == true) {
alias = (String) objEnumeration.nextElement();
privateKey = (PrivateKey) myStore.getKey(alias,
"notasecret".toCharArray());
}
} catch (Exception e1) {
e1.printStackTrace();
}
JsonObject header = new JsonObject();
header.addProperty("alg", "RS256");
header.addProperty("typ", "JWT");
Calendar cal = Calendar.getInstance();
cal.set(1970, 01, 01);
String iat = Long.toString((System.currentTimeMillis() - cal.getTimeInMillis())/1000);
String exp = Long.toString((System.currentTimeMillis() - cal.getTimeInMillis())/1000 + 60000L);
JsonObject claim = new JsonObject();
claim.addProperty("iss", "$$%$^%&^!%@#[email protected]");
claim.addProperty("scope", "https://www.googleapis.com/auth/devstorage.readonly");
claim.addProperty("aud", "https://accounts.google.com/o/oauth2/token");
claim.addProperty("access_type", "offline");
claim.addProperty("exp", exp);
claim.addProperty("iat", iat);
System.out.println("Header : " + header);
String headerStr = header.toString();
System.out.println("claim : " + claim);
String claimStr = claim.toString();
try {
byte[] headerArr = headerStr.getBytes(UTF8_CHARSET);
System.out.println(Base64.encodeBase64String(headerArr));
byte[] claimArr = claimStr.getBytes(UTF8_CHARSET);
System.out.println(Base64.encodeBase64String(claimArr));
String inputStr = Base64.encodeBase64String(headerArr) + "." + Base64.encodeBase64String(claimArr);
System.out.println("Input String : " + inputStr);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(inputStr.getBytes(UTF8_CHARSET));
System.out.println("Sign : " + signature.sign());
System.out.println("Base64url encoded sign : " + Base64.encodeBase64String(signature.sign()));
System.out.println("Final JWT : " + Base64.encodeBase64String(headerArr) + "." + Base64.encodeBase64String(claimArr) + "." + Base64.encodeBase64String(signature.sign()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
Prathamesh, is this the same question as your other post? (Making Refresh Token Request In Java With JWT through a stand alone application - Not a Web App)
To clarify, signing a JWT using the P12 file will let you get an access token (not a refresh token). That's OK, because an access token is what you need to make a subsequent API call.
I strongly suggesting using Google's Java client library to construct the JWT and do the signing, of which you already pasted a good sample for in the other post:
GoogleCredential credentialGA = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("$#$@#$#$#[email protected]")
.setServiceAccountScopes(Collections.singleton(AnalyticsScopes.ANALYTICS_READONLY))
.setServiceAccountPrivateKeyFromP12File(new File("$#$#$%$%$%$-privatekey.p12"))
.build();
this.analytics = new Analytics.Builder(httpTransport, JSON_FACTORY, credentialGA).setApplicationName("Demo App").build();
Is there a specific reason you don't want to use the client library? It will take care of creating the JWT, signing it, sending it, buildng the service requests, adding authorization headers, refreshing the access token when it expires etc etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With