How to Use NetSuite’s nlapiRequestURLWithCredentials API

This article is relevant if you are a NetSuite SuiteScript developer and you want to leverage the nlapiRequestURLWithCredentials function to securely manage your calls to remote systems.

Background

While working towards NetSuite’s ‘Built for NetSuite’ certification for the Bitcoin Transactoin Coordinator, we needed to securely connect to remote Bitcoin Payment Processors with account credentials. ¬†For example, BitPay uses an API token to communicate with its system; and BTC4ERP uses a common set of usernames and passwords. ¬†This data needs to be kept private and used only in the context of calls inside the application.

NetSuite offers a pair of calls that allow you to securely manage credential information:

  1. nlobjForm.addCredentialField API: use this call to gather credentials or other private token data from users and store it within NetSuite in a secure manner.
  2. nlapiRequestURLWithCredentials API: use this call to make an HTTPS request to remote systems using the credential information captured with addCredentialField.
These functions are meant to be used together.  Using one without the using the other does not offer any value.

Using addCredentialField Function

To capture private credential information from the user, you will need to create a custom session only field(s) that will be used to gather data as presented in your SuiteLet or built-in user form.  Information that you collect from the user will effectively be encrypted and not available for use outside of a call with the nlapiRequestURLWithCredentials function.  You will store the encrypted results of the addCredentialField call in a custom Free-Form text field in NetSuite.  Since it is encrypted, the data stored in NetSuite is meaninless if it ever becomes compomised.  Here is a code snippet to show how it can be used to draw two fields in a standard record BeforeLoad UserEvent:
function userEventBeforeLoad(type, form, request){
	domains = ['www.bitpay.com']; //an array of domains that is possible to use these credentials
	var script = 'customscript_bitpay_credential_sched'; //the script that will eventually use the nlapiRequestURLWithCredentials call
	var cred_group    = form.addFieldGroup("_credgroup", "Credential Fields Generated in Code");
        var cred_1        = form.addCredentialField('custpage_cred_1', 'String 1', domains, script, null, false, "_credgroup");
        var cred_2        = form.addCredentialField('custpage_cred_2', 'String 2', domains, script, null, false, "_credgroup");
}
In the code example, there are important matters to consider:
  1. domains: This is an array list of domains that can be called when trying to access your application outside of NetSuite.  The exact domains are required.
  2. script: this is the name of the single script that will be used with the nlapiRequestURLWithCredentials call to the remote system. ¬†Note, as of 2014.1, the documentation says that this parameter is optional but it is not correct; if you do not supply it, you won’t be able to decrypt the data.
Now, client side, I place the data into actual free-from custom fields that will hold the encrypted data:
function clientSave(){
	nlapiSetFieldValue('custrecord_credential_string_1', nlapiGetFieldValue('custpage_cred_1'));
	nlapiSetFieldValue('custrecord_credential_string_2', nlapiGetFieldValue('custpage_cred_2'));
	return true;
}
While I am probably incorrect of the actual under the cover implementation, I speculate that the “script” parameter actually acts as a key to encrypt the data captured in the call. ¬†I further believe that the “domains” parameter limits the range of distribution points that the credential can be used. ¬†It is important to recognize that NetSuite’s provided function allows for only one script to use this data. ¬†If you have other scripts that need to reference these credentials, it will not work.

Using nlapiRequestURLWithCredentials Function

Now we get to the part that you want to make your call to the remote service. ¬†The trick to understand what is happening is that the function implictly knows what script id you are running under. ¬†It uses this information to act like a key to decrypt the data. ¬†If you try to run this function under a different script id then the one you orginally provided, you won’t be able to decrypt the data.
Here is sample code where we wanted to use the credentials in the outbound HTTPS header.  However, we could just as easily referenced the URL or the BodyPost area.
function callSecureURL(type) {
	//www.bitpay.com domain was previously referenced
	var url = 'https://www.bitpay.com/payments'; 

	//get the data from our custom record; its encrypted
	var r = nlapiLoadRecord('customrecord_credentials', 1);
	var cred_1 = r.getFieldValue('custrecord_credential_string_1');
	var cred_2 = r.getFieldValue('custrecord_credential_string_2');

	//store the encrypted credentials into an array
	var credentials = [cred_1, cred_2];

	//craft the the header
	var headers = {};
        headers['Content-Type'] = 'application/json';
        headers['Accept'] = 'application/json';
        headers['cred_1'] = '{' + cred_1 + '}';  //most important is to craft the value to be a JavaScript object {<data>}
        headers['cred_2'] = '{' + cred_2 + '}';

	//here is a sample where we use an https get to pass credentials
	//url = url + '&cred_1={' + cred_1 + '}&cred_2={' + cred_2 + '}';
	var response = nlapiRequestURLWithCredentials(credentials, url, null, headers, null); //send data
};

The challenge with this function call is you can’t see the work it is doing because it goes out over the wire and decrypts at the same time. ¬†There is no traditional debugging available.

We have written an HTTPS inspection utility to help you understand how this works by catching the information being passed over the SSL URL. ¬†See the “Diagnose and Inspect NetSuite HTTPS Posts” article to learn more. ¬†In that article, we reference a SuiteBundle that you can install — that bundle also includes scripts and custom records that we referenced in this article to help you learn how to use the entire secure practice.

Enhance Your NetSuite System

If you are looking for experts in the NetSuite platform, contact us.

 

Be Sociable, Share!

Marty Zigman

Holding all three official certifications, Marty is Southern California's NetSuite expert and leads a team of senior professionals at Prolecto Resources, Inc. He is a former Deloitte & Touche CPA and has held CTO roles. For over 25 years, Marty has produced leadership in ERP, CRM and eCommerce business systems. Contact Marty to set up a conversation.

More Posts - Website - Twitter - Facebook - LinkedIn - Google Plus - YouTube

| Tags: , , , | Category: NetSuite, Technical | 4 Comments

2 Comments

  1. Carlo
    Posted September 21, 2014 at 6:32 pm | Permalink

    “script” parameter identifies the script that can use the credentials using nlapiRequestURLWithCredentials. In your example it is not apparent because addCredentials is in the same script that call nlapiRequestURLWithCredentials. It is designed this way to allow credentials input on one script and credentials usage on another script, which could be a user event script, scheduled script, another suitelet etc. I wish Netsuite made this an array instead of a single script id.

  2. Posted September 22, 2014 at 6:48 am | Permalink

    Thank you Carlo. Indeed, the ‘script’ parameter is about the target script that will be using the nlapiRequestURLWithCredentials function call. If it could take an array, it would be more flexible, Idealy, we wouldn’t need that script key at all and instead, it would be controlled by the distribution definition. See my new article about nlapiEncrypt and nlapiDecrypt.

2 Trackbacks

  1. […] How to Use NetSuite’s nlapiRequestURLWithCredentials API […]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>