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;
    }
}

 
    