I am currently working on sending a request to Snowflake using Key Pair Authentication. They have provided me with a private key and a public key, and for testing purposes, I have hardcoded them as follows:
String privateKey = '-----BEGIN PRIVATE KEY-----\n' +
'MI56GHYFDgkqhkiG9w0BAQEFAASCBKkwgDFDFQC/38qQEqZcSO2F\n' +
'GwgOTsxJQ4bELFvfq7qoDaMKtZBHDh42dGZro2NrJ+d/deUg+9hH0qwnidke9PEx\n' +
.....
'-----END PRIVATE KEY-----';
privateKey = privateKey .replace('-----BEGIN PRIVATE KEY-----','');
privateKey = privateKey .replace('-----END PRIVATE KEY-----','');
privateKey = privateKey .replace('\n','');
String publicKey = '-----BEGIN PUBLIC KEY-----\n' +
'MIEFHYuyuzGkiG9w0BAQEFAAOCAQ8AMIIBCgKDDFGHH34KkBKmXEjthRsIDk7M\n' +
'SUOGxCxb36uAAAtyuw4eNnRma6Njayfnf3XlIPvYRdfGT65vTxMY1wwVO6\n' +
......
'-----END PUBLIC KEY-----';
publicKey = publicKey .replace('-----BEGIN PUBLIC KEY-----','');
publicKey = publicKey .replace('-----END PUBLIC KEY-----','');
publicKey = publicKey .replace('\n','');
String encodedPublicKey = EncodingUtil.base64Encode(Blob.valueOf(publicKey));
After that, I created the header:
JSONGenerator jsonHeader = JSON.createGenerator(false);
jsonHeader.writeStartObject();
jsonHeader.writeStringField('alg', 'RS256');
jsonHeader.writeStringField('typ', 'JWT');
jsonHeader.writeEndObject();
String encodedHeader = EncodingUtil.base64Encode(Blob.valueOf(jsonHeader.getAsString()));
And the payload:
JSONGenerator jsonBody = JSON.createGenerator(false);
jsonBody.writeStartObject();
jsonBody.writeStringField('iss', accountId+'.'+userId+'.SHA256:'+encodedPublicKey);
jsonBody.writeStringField('sub', accountId+'.'+userId);
jsonBody.writeNumberField('iat', Datetime.now().getTime());
jsonBody.writeNumberField('exp', Datetime.now().addMinutes(3).getTime());
jsonBody.writeEndObject();
String encodedBody = EncodingUtil.base64Encode(Blob.valueOf(jsonBody.getAsString()));
Finally, I attempted to generate the JWT request:
String jwtRequest = encodedHeader + '.' + encodedBody;
Blob key = EncodingUtil.base64Decode(privateKey);
Blob signature = Crypto.generateMac('HmacSHA256', Blob.valueOf(jwtRequest), key);
String signatureEncoded = EncodingUtil.base64Encode(signature);
signatureEncoded = signatureEncoded.replace('+', '-');
signatureEncoded=signatureEncoded.replace('/', '_');
signatureEncoded=signatureEncoded.substringBefore('=');
String signedJwtRequest = jwtRequest + '.' + signatureEncoded;
However, I encountered the following issue when tried to copy the token into postman
{
"code": "390144",
"message": "JWT token is invalid. {0}"
}
I have requested the external source to generate a valid JWT using the same variables (they did it with snowSQL), and the token they provided works. I dont sure if its need to be the same length of chars everytime but the generated token has 616 characters, while the one I generated is 1027 characters.
I have followed the steps outlined in the Snowflake documentation here, but something seems to be amiss.
As I am relatively new to integrating with JWT, any assistance with an explanation would be highly appreciated.
Many thanks!!!