Below is the requirement and they provided JAva code to create JWT.
JWT token should be signed with Client Secret. Client Key, UniqueAppId (Id assigned to the app) and a GUID should be included in the payload off the token. Client secret should be UTF-8 encoded. JWT Structure:
Header.Payload.Signature
Signature:
data = base64urlEncode( header ) + “.” + base64urlEncode( payload )
hashedData = hash( data, Encoding.UTF8.GetBytes(plainTextSecurityKey))
signature = base64urlEncode( hashedData )
Java:
public static void main(String[] args) throws UnsupportedEncodingException {
final Instant nowInstant = Instant.now().minus(Duration.ofHours(24));
System.out.println("Epoch second: " + nowInstant.getEpochSecond());
final Date currentTime = Date.from(nowInstant);
final Date expirationDate =
Date.from(currentTime.toInstant().plusSeconds(1000L));
final Map<String, Object> xyzClaims = new HashMap<>();
xyzClaims.put("ClientKey", "Client_Key");
xyzClaims.put("UniqueAppId", "App_ID");
xyzClaims.put("GUID", "GUID");
final String clientSecret = "Client_Secret";
final String jwt = Jwts.builder()
.setHeaderParam("typ", "JWT")
.setClaims(xyzClaims)
.setNotBefore(currentTime)
.setIssuedAt(currentTime)
.setExpiration(expirationDate)
.setIssuer("Your_Domain")
.setAudience("api.XYZ.com")
.signWith(SignatureAlgorithm.HS256, clientSecret.getBytes("UTF-8"))
.compact();
System.out.println("JWT: " + jwt);
}
first I need to Create JWT token ,then using JWTtoken and client credentials call a 3rd party oAuth api to get JSON response (with access, refresh tokens and expiry times).
This is the requirement and I need to write this in apex to create JWT. I have written below way. But when I try to send this with username, password which client provided I'm getting the error as
|DEBUG|Exception :PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Because I'm getting a cert error, I generated a self signed cert and mentioned in the code (commented in the code as still it is not working and giving the same error) Not sure if JWT created incorrectly or I'm missing something in the code. Client is not providing us the certificate. Please suggest ASAP.
To create JWT token:
public static String getJWTToken() {
String header = '{"typ": "JWT", "alg": "HS256"}';
String JWTHeader = base64URLencode(blob.valueOf(header));
System.debug('JWTHeader: ' + JWTHeader);
Blob b = Crypto.GenerateAESKey(128);
String h = EncodingUtil.ConvertTohex(b);
String guid = h.SubString(0,8)+ '-' + h.SubString(8,12) + '-' + h.SubString(12,16) + '-' + h.SubString(16,20) + '-' + h.substring(20);
System.debug(guid);
xyz_custom_md__mdt mdt = new xyz_custom_md__mdt();
String qualifiedApiName== 'xyz_mdata_Prod';
mdt = [SELECT Id, ClientKey__c, ClientSecret__c, UniqueAppId__c, nbf__c,exp__c,iat__c,iss__c,aud__c, UserId__c,Password__c,
QualifiedApiName from xyz_custom_md__mdt WHERE QualifiedApiName = :qualifiedApiName LIMIT 1 ];
System.debug('metadata from getToken: ' + mdt);
JSONGenerator gentr = JSON.createGenerator(true);
gentr.writeStartObject();
gentr.writeStringField('ClientKey', mdt.ClientKey__c);
gentr.writeStringField('UniqueAppId', mdt.UniqueAppId__c);
gentr.writeStringField('GUID', guid);
gentr.writeStringField('nbf', mdt.nbf__c);
gentr.writeStringField('exp', mdt.exp__c);
gentr.writeStringField('iat', mdt.iat__c);
gentr.writeStringField('iss', mdt.iss__c);
gentr.writeStringField('aud', mdt.aud__c);
gentr.writeEndObject();
String Payload = gentr.getAsString();
String JWTPayload = base64URLencode(blob.valueOf(Payload));
System.debug('JWTPayload: ' + JWTPayload);
String signatureInput = JWTHeader + '.' + JWTPayload;
System.debug('signatureInput: ' +signatureInput);
String secret = mdt.ClientSecret__c;
System.debug('signatureInput blob: ' +Blob.valueOf(signatureInput));
System.debug('signatureInput secret blob: ' +Blob.valueOf(secret));
Blob JWTSignature = Crypto.generateMac('HmacSHA256', Blob.valueOf(signatureInput),EncodingUtil.base64Decode(secret) );
System.debug('JWTsignature: ' +JWTSignature);
System.debug('encoded JWTsignature: ' +base64URLencode(JWTSignature));
String JWToken = signatureInput + '.' + base64URLencode(JWTSignature);
System.debug('JWToken: ' + JWToken);
return JWToken;
}
public static String base64URLencode(Blob input){
String output = encodingUtil.base64Encode(input);
output = output.replace('+', '-');
output = output.replace('/', '_');
while ( output.endsWith('=')){
output = output.subString(0,output.length()-1);
}
return output;
}
To get access token:
public static String getAccessToken(){
String access_token = '';
String refresh_token = '';
String JWToken = getJWTToken();
if(JWToken == null ) {
jwtResponse = 'Error while generating JWT token.';
System.debug('----Error :'+ jwtResponse);
return '';
}
try{
xyz_custom_md__mdt mdt = new xyz_custom_md__mdt();
String qualifiedApiName= 'xyz_mdata_Prod';
mdt = [SELECT UserId__c,Password__c, QualifiedApiName FROM xyz_custom_md__mdt
WHERE QualifiedApiName = :qualifiedApiName LIMIT 1 ];
System.debug('metadata: ' + mdt);
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('callout:prod_xyz/getoauth');//though not required, I'm using named cred with no authentication.
request.setMethod('POST');
request.setHeader('Content-Type', 'application/json');
request.setHeader('Authorization', JWToken);
//request.setClientCertificateName('QA_cert');
//request.setBody('{"UserId" : "string" , "Password" : "string"}');
JSONGenerator gen = JSON.createGenerator(true);
gen.writeStartObject();
gen.writeStringField('UserId', mdt.UserId__c);
gen.writeStringField('Password', mdt.Password__c);
gen.writeEndObject();
String jsonS = gen.getAsString();
request.setBody(jsonS);
System.debug('-- decoderequest with body -' +request.getbody());
HttpResponse response = http.send(request);
System.debug('StatusCode' + response.getStatusCode() + ' ' + response.getStatus());
System.debug('-- response -' +response.getBody());
if ( response.getStatusCode() == 200 ) {
System.JSONParser parser = System.JSON.createParser(response.getBody());
while (parser.nextToken() != null) {
if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) && (parser.getText() == 'AccessToken')) {
parser.nextToken();
access_token = parser.getText();
System.debug('access_token: '+ access_token);
//break;
}
if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) && (parser.getText() == 'RefreshToken')) {
parser.nextToken();
refresh_token = parser.getText();
System.debug('refresh_token: '+ refresh_token);
//break;
}
}
}
}
catch(Exception ex)
{
//jwtResponse = ex.getMessage();
System.debug('Exception :' + ex.getMessage());
}
return access_token;
}
setClientCertificateName(..)