I'm trying to get an access token for the google api and have the following error: {"error":"invalid_grant","error_description":"Invalid JWT Signature."}
Things that I had to do to get it signed:
I'm coding it for the SFCC (demandware) platform. The code looks like that:
var Signature = require("dw/crypto/Signature");
var Encoding = require('dw/crypto/Encoding');
var Bytes = require('dw/util/Bytes');
function execute( args : PipelineDictionary ) : Number
{
var service = GoogleAPIHttpFormService.getService();
var jwt = createJWT();
service.addHeader("Content-Type", "application/x-www-form-urlencoded");
service.setRequestMethod("POST");
service.addParam('grant_type', 'urn:ietf:params:oauth:grant-type:jwt-bearer');
service.addParam('assertion', jwt);
var result = service.call();
return PIPELET_NEXT;
}
function createJWT() {
var json = {
"private_key": "...private key code...",
"client_email": "*****@*******.iam.gserviceaccount.com"
};
var date = new Date();
var iat = (date.getTime() / 1000);
var exp = iat + 3600; //the current time + 1 hour in seconds
var jwtHeader = {"alg":"RS256","typ":"JWT"};
var jwtClaimSet = {
"iss": json.client_email,
"scope": "https://www.googleapis.com/auth/analytics.readonly",
"aud": "https://oauth2.googleapis.com/token",
"exp": exp,
"iat": iat
};
var signature = new Signature();
//Encode the Header as Base64
let headerBase64 = Encoding.toBase64(new Bytes(JSON.stringify(jwtHeader)));
//Encode the Payload as Base64
let jwtClaimSetBase64 = Encoding.toBase64(new Bytes(JSON.stringify(jwtClaimSet)));
//Create the content of the JWT Signature
var signatureStr = headerBase64 + "." + jwtClaimSetBase64;
var token = signature.sign(signatureStr, json.private_key, 'SHA256withRSA');
var signatureUrlEncoded = token.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/m, '');
let jwt = headerBase64 + "." + jwtClaimSetBase64 + "." + signatureUrlEncoded;
return jwt;
}
I will be thankful for any ideas how to fix it.
I tried whitout the replace of the symbols in the token and if I use this part:
token.replace(/\//g, '_').replace(/\=+$/m, '')
I get this error:
{
"error": "invalid_grant",
"error_description": "java.security.SignatureException: Invalid signature for token: ...
}
I found the issue, 2 changes had to be made:
I added this line var keyStr = json.private_key.replace("-----BEGIN PRIVATE KEY-----", "").replace(/\n/gi, '').replace("-----END PRIVATE KEY-----", "");
Then I replaced the signature concatenation line with this one:
var signatureStr = Encoding.toBase64(new Bytes(headerBase64 + "." + jwtClaimSetBase64));
And now it works