Search code examples
javascriptpostoauthnetsuite

Calling NetSuite RESTlet from Javascript: "Invalid Login Attempt"


I'm trying to test my javascript code online via Programiz but I'm having trouble figuring out where I'm going wrong. Please send help.

Here's the response that I'm getting when I send the request: {"error" : {"code" : "INVALID_LOGIN_ATTEMPT", "message" : "Invalid login attempt."}}

And when I check via Login Audit Trail in NetSuite, the Role is not showing compared to when I tried using POSTMAN.

var crypto = require("crypto");
var fetch = require('node-fetch');

var url = "https://{accountID}.restlets.api.netsuite.com/app/site/hosting/restlet.nl?script=729&deploy=1";
var realm = "{accountId}";
var signatureMethod = "HMAC-SHA256";
var oauthVersion = "1.0";
var consumerKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
var consumerSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
var tokenId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
var tokenSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

var nonce = randomString(10);
var timeStamp = Math.round((new Date()).getTime() / 1000); 
var baseString = realm + "&" + consumerKey + "&" + tokenId + "&" + nonce + "&" + timeStamp;
var signingKey = consumerSecret + "&" + tokenSecret;

var hmac = crypto.createHmac("sha256", signingKey);
hmac.update(baseString);
var signature = encodeURIComponent(hmac.digest("base64"));

var authorizationStr = "OAuth realm=\""+ realm + "\"" +
                      ",oauth_consumer_key=\"" + consumerKey + "\"" +
                      ",oauth_token=\"" + tokenId + "\"" +
                      ",oauth_signature_method=\"" + signatureMethod + "\"" +
                      ",oauth_timestamp=\"" + timeStamp + "\"" + 
                      ",oauth_nonce=\"" + nonce + "\"" + 
                      ",oauth_version=\"" + oauthVersion + "\"" + 
                      ",oauth_signature=\"" + signature + "\"";
console.log("timeStamp: " + timeStamp);
console.log("nonce: " + nonce);
console.log("signature: " + signature);

var raw = JSON.stringify({
  "searchId": "customsearch_pendingso"
});

var requestOptions = {
  method: 'POST',
  headers: {
      "Authorization": authorizationStr,
      "Content-Type": "application/json",
      "Cookie": "NS_ROUTING_VERSION=LAGGING",
      "Cache-Control": "no-cache",
      "Accept": "*/*",
      "Accept-Encoding": "gzip, deflate, br"
  },
  body: raw,
  redirect: 'follow'
};

fetch(url, requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));

function randomString(length) {
  var text = "";
  var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  for (var i = 0; i < length; i++) {
    text += possible.charAt(Math.floor(Math.random() * possible.length));
  }
  return text;
}

Solution

  • Here's the solution to my problem.

    So instead of trying to do it on an online compiler, I installed NodeJS and used oauth-1.0a.

    var request = require('request');
    var OAuth = require('oauth-1.0a');
    
    var realm = "{ACCOUNTID}";
    
    var token = {
        public: "{TOKEN_ID}",
        secret: "{TOKEN_SECRET}"
    };
    
    var oauth = OAuth({
        consumer: {
            public: "{CONSUMER_KEY}",
            secret: "{CONSUMER_SECRET}"
        },
        signature_method: "HMAC-SHA256"
    });
    
    var request_data = {
        url: "{RESTLET_EXTERNAL_URL}",
        method: 'POST'
    };
    
    var request_headers = oauth.toHeader(oauth.authorize(request_data, token));
    request_headers.Authorization  += ', realm="' + realm + '"';
    request_headers['content-type'] = 'application/json';
    
    var request_payload = {
        "searchId": "customsearch_pendingso"
    }
    
    request({
        url: request_data.url,
        method: request_data.method,
        headers: request_headers,
        json: request_payload
    }, function(error, response, body) {
        if (error) console.log(error);
        console.log(body);
    });