I am trying to generate a JWT token that has to be given to another system. I have followed the below steps for doing so:
- Created a Connect App. I have got consumer key using this App.
- Created a self signed certificate. Downloaded the certificate(crt) file. Converted the crt file into key file using openSSL. I used command:
openssl req -newkey rsa:2048 -nodes -keyout SSO_Self_Signed.key -out SSO_Self_Signed.csr
SSO_Self_Signed is a label name of my certificate. The generated key file has private key in between -----BEGIN PRIVATE KEY-----
and -----END PRIVATE KEY-----
3. I have created an APEX class that will generate JWT token using the creds we obtained in STEP 1 and STEP 2.
The code snippet of my code is also mentioned below:
jwtToken
is generated on line 46.
When I am trying to validate the JWT in https://jwt.io/, I am getting invalid signature and I am not able to figure out the exact cause of the issue.
The inputs passed to the class includes - iss:mailaddress; sub:other system url; aud: consumer key from step1; privateKey: key from step2.
public class SSOJWTGenerator {
public static String generateJWT(String iss, String sub, String aud, String privateKey) {
String alg = 'RS256';
String typ = 'JWT';
// Create the JWT header
Map<String, Object> header = new Map<String, Object>{
'alg' => alg,
'typ' => typ
};
String encodedHeader = base64UrlEncode(JSON.serialize(header));
// Create the JWT claim set
Map<String, Object> claimSet = new Map<String, Object>{
'iss' => iss,
'sub' => sub,
'aud' => aud,
'exp' => String.valueOf(DateTime.now().getTime()/1000 + 300),
'iat' => String.valueOf(DateTime.now().getTime()/1000)
};
String encodedClaimSet = base64UrlEncode(JSON.serialize(claimSet));
// Create the signature
String input = encodedHeader + '.' + encodedClaimSet;
privateKey = privateKey.replace('-----BEGIN PRIVATE KEY-----', '');
privateKey = privateKey.replace('-----END PRIVATE KEY-----', '');
privateKey = privateKey.deleteWhitespace();
Blob privateKeyBlob = EncodingUtil.base64Decode(privateKey);
Blob signatureBlob = Crypto.sign('RSA-SHA256', Blob.valueOf(input), privateKeyBlob);
String signature = base64UrlEncode(signatureBlob);
// Combine the header, claim set, and signature to create the JWT token
String jwtToken = encodedHeader + '.' + encodedClaimSet + '.' + signature;
System.debug('jwtToken'+ jwtToken);
return jwtToken;
}
private static String base64UrlEncode(String input) {
// Replace + with -, / with _, and remove any trailing = signs
String base64 = EncodingUtil.base64Encode(Blob.valueOf(input));
base64 = base64.replace('+', '-').replace('/', '_').replaceAll('\\=+$', '');
return base64;
}
private static String base64UrlEncode(Blob input) {
// Replace + with -, / with _, and remove any trailing = signs
String base64 = EncodingUtil.base64Encode(input);
base64 = base64.replace('+', '-').replace('/', '_').replaceAll('\\=+$', '');
return base64;
}
}