Back to Blogs
NetSuite Diaries

Credential Shield: Securing Third-Party App Access in NetSuite

Jona Obrador
September 20, 2024
6
minutes to read

Credential Shield: Securing Third-Party App Access in NetSuite

When I started out as a NetSuite developer, integrating with third-party applications like Amazon, Shopify, and WMS was a common aspect of my projects. One of my major concerns was securing the credentials used in these integrations, as they have the potential to manipulate data across these platforms.

Today, we’re discussing best practices to ensure that these credentials don’t fall into the wrong hands. With knowledge of the API and credentials, malicious actors could wreak havoc on a business.

Hard-Coding Practice

const GIPHY_TRANSLATE_URL = "https://api.giphy.com/v1/gifs/translate";
const apiKey = "xxxxxxxxxxx";

const giphyResponse = https.get({
   url: `${GIPHY_TRANSLATE_URL}?&api_key=${apiKey}&s=${searchString}`,
   header: {
       "Accept":" application/json"
    }
})

Risk: Hard-coding API keys directly into source code is a risky practice. If the code is exposed, the API keys can be easily copied and misused.

Mitigation: When deploying as part of a SuiteBundle or SuiteApp, ensure that files containing sensitive information are locked and hidden to prevent unauthorized access.


Storing Encrypted API Keys

To enhance security, consider encrypting your API keys before storing them. Here’s a basic example of encrypting an API key in a user event beforeLoad().

1. Encrypt: Encrypt the API key using an encryption key that only your application knows.

/**
 * @NApiVersion 2.1
 * @NScriptType UserEventScript
 * @NModuleScope SameAccount
 */

import {EntryPoints} from "N/types";

import * as crypto from "./crypto-js/index";
import {ENCRYPTION_KEY} from "./encryptionKey";

export const beforeSubmit: EntryPoints.UserEvent.beforeSubmit = (scriptContext) => {
    const {newRecord} = scriptContext;

    if(!newRecord) {
        return;
    }

    const API_KEY_FIELD = "custrecord_asp_api_key";
    const apiKey = newRecord.getValue({
        fieldId: API_KEY_FIELD
    });

    const encryptedApiKey = crypto.AES.encrypt(apiKey, ENCRYPTION_KEY).toString();
    newRecord.setValue({
        fieldId: API_KEY_FIELD,
        value: encryptedApiKey
    });
};

2. Store: Save the encrypted API key in a custom record.

api-encrypted-key

3. Retrieve: Decrypt the API key using your encryption key when needed, then use it for your request.

const getGiphyImageUrl = (searchString: string) => {
    const GIPHY_TRANSLATE_URL = "https://api.giphy.com/v1/gifs/translate";

    const [queryResult] = query.runSuiteQL({
        query: `
            SELECT
                custrecord_asp_api_key as apikey
            FROM
                customrecord_asp_api_key
        `
    }).asMappedResults();
    
    const apiKey = crypto.AES.decrypt(queryResult.apikey, ENCRYPTION_KEY).toString(crypto.enc.Utf8);

    const giphyResponse = https.get({
        url: `${GIPHY_TRANSLATE_URL}?&api_key=${apiKey}&s=${searchString}`,
        headers: {
            "Accept": "application/json"
        }
    });
}

Demo video here: Get Giphy via Encrypted Key

Risk: The encryption key could be exposed in the source code, making it vulnerable to reverse engineering. If the decrypted API key is logged, it may be at risk of compromise.

Mitigation: When deploying a SuiteBundle or SuiteApp, make sure to secure and hide any files that contain encryption keys to safeguard against unauthorized access.


NetSuite API Secrets

NetSuite has introduced a feature to address security concerns regarding sensitive data: API Secrets.

1. Store API key via API Secret

  • Navigate to Setup > Company > API Secrets > New
  • Paste your API key into the Password field.
  • Check Allow for All Scripts and Allow for All Domains.
ns-api-secret-setup-1

2. Retrieve the API Key: Use https.createSecureString() to access the API key securely.

const getGiphyImageUrl = (searchString: string) => {
    const GIPHY_TRANSLATE_URL = "https://api.giphy.com/v1/gifs/translate";
    const url = https.createSecureString({
        input: `${GIPHY_TRANSLATE_URL}?&api_key={custsecret_asp_giphy_api_key}&s=${searchString}`
    });
    const giphyResponse = https.get({
        url,
        headers: {
            "Accept": "application/json"
        }
    });
}

Demo video here: Get Giphy via Secret


Limit access to API Secret (Optional)

To ensure that API Secrets are only accessible to authorized scripts, follow these steps:

1. Navigate to the API Secret: Go to Setup > Company > API Secrets and select the API Secret you have created.

2. Set Restrictions:

  • Click on the Restrictions tab.
  • Enter the Script ID of the specific script that should have access to this API Secret. This ensures that only the designated script can retrieve the API Secret, enhancing security by limiting access.
ns-api-secret-setup-2

Demo Video for Unauthorized: Get Giphy via Secret - Unauthorized Script

Risk: This approach appears to carry minimal risk. The API key is not easily accessible, and attempts to log the URL value return an empty object, adding an extra layer of security.


Final Thoughts

NetSuite API Secrets deliver a powerful means of securing sensitive information and enhance the NetSuite security toolkit. I highly recommend using this native feature, as it offers an easy and effective way to manage API credentials with less complexity than conventional encryption methods.

To see the complete SuiteScript code and implementation details discussed in this article, visit Jona's GitHub repository.


Meet the Author

jona-obrador-author

Jona has over a decade of experience in SuiteCloud Development on the NetSuite platform. She specializes in implementing advanced solutions and has led teams in creating high-quality software. Jona holds multiple certifications and has been recognized with awards like the Summit Award and Quality Champion Award.