1

I have a requirement where I need to send JWT token as a part of my request body. I have created a JWT class and an Apex rest class to acheive the required scenario. Below are the classes

Apex Rest Class:

  public class AccUpdateController {
        @future(callout=true)
        public static void AccupdateController(Set<Id> accountIdset) { 
JWT jwt = new JWT();
        String token = jwt.issue();       
            string resultBodyGet = '';

            list<Account> accts = [SELECT Unique_ID__c, Account_Status__c, Email__c from Account where Account_Partner_Status__c = 'ACTIVE' and Id IN:accountIdset];

            system.debug('>>>>>>>>>>' + accts);        
            for(Account c : accts){         

                MAp<String, String> tags = new Map<String, String>();
                tags.put('accId', c.Unique_ID__c);
                tags.put('email', c.Email__c);
                tags.put('status', c.Account_Status__c); 
                tags.put('jwt token', token);
                system.debug('#### Input JSON: ' + JSON.serialize(tags));            
                try{
                    string endpoint = 'https://my-endpoint.com';
                    HttpRequest req = new HttpRequest();
                    req.setEndpoint(endpoint);
                    req.setMethod('POST');
                    req.setHeader('Content-type', 'application/json');
                    req.setbody(JSON.serialize(tags));
                    Http http = new Http();
                    system.debug('Sending User to update status');
                    HTTPResponse response = http.send(req); 
                    system.debug('Status updated');
                    resultBodyGet = response.getBody();
                    system.debug('Output response:' + resultBodyGet);
                    accResponse myAccResponse = new accResponse();
                    myAccResponse = (accResponse) JSON.deserialize(resultBodyGet, accResponse.class);
                    system.debug('#### myAccResponse: ' + myAccResponse);

                }
                catch (exception e) {                              
                }   
            }
        }    
        public class accResponse {
            public string message {get;set;}
        }
    }

Below is the JWT class

public class JWT {

    public jwt(){

    }

     String alg = 'RS256';
     String ISS = 'F360';
    String SUB = 'F360';
    String AUD = 'T360';
   Long expires_at = math.roundToLong(DateTime.now().addMinutes(10).getTime() / 1000);    
    Long issued_at = math.roundToLong(DateTime.now().addSeconds(-2).getTime() / 1000);
    public Map<String,String> claims {get;set;}
    //public Integer validFor {get;set;}
    public String cert {get;set;}
    public String pkcs8 {get;set;}
    string privatekey = 'XXXMyPrivatekeyXXX'


    public static final String HS256 = 'HS256';
    public static final String RS256 = 'RS256';
    public static final String NONE = 'none';


    public JWT(String alg) {
        this.alg = alg;
        //this.validFor = 300;
    }


    public String issue() {

        String jwt = '';

        JSONGenerator header = JSON.createGenerator(false);
        header.writeStartObject();
        header.writeStringField('alg', this.alg);
        header.writeEndObject();
        String encodedHeader = base64URLencode(Blob.valueOf(header.getAsString()));

        JSONGenerator body = JSON.createGenerator(false);
        body.writeStartObject();
        body.writeStringField('iss', this.iss);
        body.writeStringField('sub', this.sub);
        body.writeStringField('aud', this.aud);
        //Long rightNow = (dateTime.now().getTime()/1000)+1;
        body.writeNumberField('expires_at', this.expires_at);
        body.writeNumberField('issued_at', this.issued_at);
        if (claims != null) {
            for (String claim : claims.keySet()) {
                body.writeStringField(claim, claims.get(claim));
            }
        }
        body.writeEndObject();

        jwt = encodedHeader + '.' + base64URLencode(Blob.valueOf(body.getAsString()));

        if ( this.alg == HS256 ) {
            Blob key = EncodingUtil.base64Decode(privateKey);
            Blob signature = Crypto.generateMac('hmacSHA256',Blob.valueof(jwt),key);
            jwt += '.' + base64URLencode(signature);  
        } else if ( this.alg == RS256 ) {
            Blob signature = null;

            if (cert != null ) {
                signature = Crypto.signWithCertificate('rsa-sha256', Blob.valueOf(jwt), cert);
            } else {
                Blob privateKey = EncodingUtil.base64Decode(pkcs8);
                signature = Crypto.sign('rsa-sha256', Blob.valueOf(jwt), privateKey);
            }
            jwt += '.' + base64URLencode(signature);  
        } else if ( this.alg == NONE ) {
            jwt += '.';
        }

        return jwt;

    }


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


}

When I execute this class, I am recieving an error stating

First error: Argument cannot be null.

Can anyone please suggest how to overcome this.

0

The problem is in the pkcs8 variable in JWT class, it is null, because the JWT class is called from future context and it isn't set to any value.

Therefore, the method Blob privateKey = EncodingUtil.base64Decode(pkcs8); gets null as an argument which is unacceptable.

The same relates to cert variable.

  • Thanks @MariiaIllarinova....What do I need to call in the argument of private key in my code. Please suggest – Skumar Jul 17 at 10:58
  • Set it after JWT jwt = new JWT(); and before String token = jwt.issue(); directly in the future method. – Mariia Illarionova Jul 17 at 10:59
  • Thanks a ton Mariia... :) – Skumar Jul 17 at 11:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.