We are setting up a Salesforce Community and our community members should be able to automatically login using the credentials from an extenal platform when clicking on a link from this platform. I'm trying to generate a JWT token (Please find below the class I've made to generate the JWT) and I've created a connected app to get a consumer key.
public inherited sharing class JWTAuthFlow {
public static string createJWT(String iss, String sub, String aud, String endpoint){
// Static Resource to get the Key that will be used for Crypto-Sign
StaticResource jwtPrivate = [SELECT Id, Body FROM StaticResource WHERE Name = 'JWT_Private_key' LIMIT 1];
String privateKey = jwtPrivate.Body.toString();
//Create Body of the Json that contains enpoint URL, Consumer Key, Type, ect
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()));
JSONGenerator jsonBody = JSON.createGenerator(false);
jsonBody.writeStartObject();
jsonBody.writeStringField('iss', iss);
jsonBody.writeStringField('sub', sub);
jsonBody.writeStringField('aud', aud);
jsonBody.writeNumberField('exp', Datetime.now().addMinutes(3).getTime());
jsonBody.writeEndObject();
String encodedBody = EncodingUtil.base64Encode(Blob.valueOf(jsonBody.getAsString()));
String jwtRequest = encodedHeader + '.' + encodedBody;
// Sign JWT Request
Blob key = EncodingUtil.base64Decode(privateKey);
Blob rs256sig = Crypto.sign('RSA-SHA256', Blob.valueOf(jwtRequest), key);
String signature = EncodingUtil.base64Encode(rs256sig);
signature = signature.replace('+', '-');
signature = signature.replace('/', '_');
String signedJwtRequest = jwtRequest + '.' + signature;
// Create the payload
String payload = 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer';
payload += '&assertion=' + signedJwtRequest;
// Create a HttpRequest and send it to server
Http httpObj = new Http();
HttpRequest req = new HttpRequest();
HttpResponse res;
req.setEndpoint(endpoint);
req.setMethod('POST');
req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
req.setBody(payload);
res = httpObj.send(req);
if(res.getStatusCode() == 200){
Map<String, Object> mapTokenResponse = (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
return (String)mapTokenResponse.get('access_token');
}
return res.getBody();
}
}
I have the following error when I try to generate a JWT: 'Unrecognized base64 character:-' (I can see from system.debug that it generates the header and the body, but not the signature).
I don't know what I'm doing wrong ?
It's the first time I'm working with JWT so I don't know if I've missed something. The developer from the external app is waiting for the token, and the returnURL (the path). Is there something else I need to give him ?