function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Ashish2802Ashish2802 

Apex callout with external system using Oauth1 authentication

Hi,
I am trying to make an Apex callout to Netsuite which is using OAuth1 Authentication. It uses HMAC-SHA256 to generate signature using consumer secret and token secret. 
 
It is giving me Invalid Login Attempt error with 403 Forbidden error code.
 
Here is my Apex code.
 
public static void getResponse(){
        Netsuite_API__mdt netObj = [Select MasterLabel, Consumer_Key__c, Access_Token__c, Consumer_Secret__c, Endpoint_URL__c, Realm__c, Token_Secret__c From Netsuite_API__mdt Where MasterLabel = 'Restlet'];
        
        String content = '{"createdDate1": ["3/4/2021 12:03 pm"], "createdDate2": ["3/4/2021 12:08 pm"], "lastModifiedDate1": ["3/4/2021 12:03 pm"], "lastModifiedDate2": ["3/4/2021 12:08 pm"]}';
        
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        HttpResponse response = new HttpResponse();
        
        request.setEndpoint(netObj.Endpoint_URL__c);
        request.setBody(content);
        request.setHeader('Content-Type', 'application/json');
        request.setMethod('POST');
        request = Restlet_Integration.signRequest(request, netObj.Consumer_Key__c, netObj.Consumer_Secret__c, netObj.Realm__c, netObj.Access_Token__c, netObj.Token_Secret__c);
        try{
        	response = http.send(request);
            System.debug(response.getBody());
        	System.debug(response.getStatusCode() + response.getStatus());
        }
        catch(System.CalloutException e){
            System.debug(response.toString());
        	System.debug(response.getStatusCode() + response.getStatus());
            System.debug('Callout Error =' + e);
        }
        
    }
	
    public static HttpRequest signRequest(HttpRequest req, String consumerKey, String consumerSecret, String realm, String access_token, String tokenSecret){
        String nonce = String.valueOf(Crypto.getRandomLong());
        String timeStamp = String.valueOf(DateTime.now().getTime() / 1000);
        
        Map<String, String> parameters = new Map<String, String>();
        parameters.put('realm', realm);
        parameters.put('oauth_consumer_key', consumerKey);
        parameters.put('oauth_token', access_token);
        parameters.put('oauth_signature_method', 'HMAC-SHA256');
        parameters.put('oauth_timestamp', timeStamp);
        parameters.put('oauth_nonce', nonce);
        
        String signature = generateSignature(consumerSecret, tokenSecret);
        String header = generateHeader(signature, parameters);
        System.debug('Header =' + header);
        req.setHeader('Authorization', header);
        
        return req;
    }
    
    private static String generateSignature(String consumerSecret, String tokenSecret){
        String nonceKey = String.valueOf(Crypto.getRandomInteger());
        String secretKey = consumerSecret + '&' + tokenSecret;
        Blob sign = Crypto.generateMac('HmacSHA256', Blob.valueOf(nonceKey), Blob.valueOf(secretKey));
        System.debug('Signature =' +  EncodingUtil.convertToHex(sign));
        return EncodingUtil.convertToHex(sign);
    }
    
    private static String generateHeader(String signature, Map<String, String> parameters){
        String header = 'OAuth ';
        for(String key : parameters.keySet()){
            header = header + key + '="' + parameters.get(key) + '", ';
        }
        
        return header + 'oauth_signature="' + signature + '"';
    }

 
AnudeepAnudeep (Salesforce Developers) 
I have experienced similar issues in the past

I recommend reviewing the debug logs to check if the callout response is failing. You will see something like this

04:07:23.0 (20121558)|CALLOUT_REQUEST|[463]|System.HttpRequest[Endpoint=https://456822-sb1.restlets.api.netsuite.com/app/site/hosting/restlet.nl?script=223&deploy=1, Method=POST]
04:07:24.993 (1993694393)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:351
04:07:24.993 (2007599282)|CALLOUT_RESPONSE|[463]|System.HttpResponse[Status=Forbidden, StatusCode=403]

Also, I suggest verifying if the configuration is correct and check the call from postman and to see if that is successful. Also, please check the response using Request bin

If you are unable to identify the root cause after these steps, please create a support case to investigate this further

Let me know if this helps, if it does, please mark this answer as best so that others facing the same issue will find this information useful. Thank you
AkhilMandiaAkhilMandia
Hey ashish

are you able to resolve the issue?