0

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;
    }
9
  • Client didn't provide any cert, For the callout, do I need to generate a CA trusted certificate?Am I creating JWT token correct?
    – SFRR
    Commented Mar 24, 2020 at 17:46
  • JWT Token code looks correct. SunCertPathBuilderException is due to SSL issues. If the server expects a SSL cert (mutual auth in SSL), then you'll need to grab a cert (or cert chain) from your client, import it correctly via Certs and Keys and then use it via setClientCertificateName(..)
    – identigral
    Commented Mar 24, 2020 at 17:50
  • Thank you for the reply but Client is not providing us cert. What do you mean by "grab a cert (or cert chain) from your client"? Sorry I'm new to this approach. Could you explain me?
    – SFRR
    Commented Mar 25, 2020 at 15:31
  • grab a cert means you'll need to talk to your Client and ask about SSL.
    – identigral
    Commented Mar 25, 2020 at 15:38
  • But without cert, when I test on Fiddler, it works fine.
    – SFRR
    Commented Mar 25, 2020 at 18:15

0

Browse other questions tagged .