APEX API Node.js Security Utility
A Javascript utility that generates HTTP security headers for authenticating with secured Apex endpoints, for Node.js.
Table of Contents
Getting Started
Installation
$ npm install node-apex-api-security
API Usage
ApiSigningUtil.getSignatureToken(options)
Returns a signature token used for authentication with a secured Apex API.
APEX L1 Secured API
Authorization token with HMACSHA256 signature
const ApiSigningUtil = require('node-apex-api-security').ApiSigningUtil;
const requestOptions = {
appId: 'my-app-id',
secret: 'my-app-secret',
authPrefix: 'apex_l1_eg',
httpMethod: 'get',
urlPath: 'https://my.apex.api/endpoint'
};
const L1SignatureToken = ApiSigningUtil.getSignatureToken(requestOptions);
APEX L2 Secured API
Authorization token with SHA256withRSA signature
const ApiSigningUtil = require('node-apex-api-security').ApiSigningUtil;
const requestOptions = {
appId: 'my-app-id',
keyString: '----BEGIN PRIVATE KEY-----...',
authPrefix: 'apex_l2_eg',
httpMethod: 'get',
urlPath: 'https://my.apex.api/endpoint'
};
const L2SignatureToken = ApiSigningUtil.getSignatureToken(requestOptions);
The generated token should then be added to the Authorization
header when making HTTP API calls:
GET /endpoint HTTP/1.1
Host: my.apex.api
Authorization: Apex_l1_ig realm="https://my.apex.api/endpoint",apex_l1_ig_app_id="my-app-id",apex_l1_ig_nonce="UldycUAF56GWJGlWz0YSwOOp5gruJqvBy0CJeZ4XpGk=",apex_l1_ig_signature="u5nTX4ZbkL8c9pp5C79VHu07QPPLG9yx2VxpLX7kqGM=",apex_l1_ig_signature_method="HMACSHA256",apex_l1_ig_timestamp="1523935422173",apex_l1_ig_version="1.0"
...
Core Options
Apex App ID. The App needs to be approved and activated by the API provider. This value can be obtained from the gateway portal.
let appId = 'my-app-id';
API gateway-specific authorization scheme for a specific gateway zone. Takes 1 of 4 possible values.
let authPrefix = 'Apex_l1_ig';
let authPrefix = 'Apex_l1_eg';
let authPrefix = 'Apex_l2_ig';
let authPrefix = 'Apex_l2_eg';
The API HTTP method
let httpMethod = 'get';
The full API endpoint, for example https://my-apex-api.api.gov.sg/api/my/specific/data.
Note: Must be the endpoint URL as served from the Apex gateway, from the domain api.gov.sg. This may differ from the actual HTTP endpoint that you are calling, for example if it were behind a proxy with a different URL.
IMPORTANT NOTE from v0.7.8 onwards : If you are intending pass in the query params in optional parameters queryString or formData, please remove the queryString from the urlPath. Checkout the optional section
let urlPath = "https://my.apex.api/v1/resources?host=https%3A%2F%2Fnd-hello.api.example.comß&panelName=hello";
secret
- Required for L1 signature
If the API you are accessing is secured with an L1 policy, you need to provide the generated App secret that corresponds to the appId
provided.
Note: leave secret
undefined if you are using ApiSigningUtil L2 RSA256 Signing
let secret = 's0m3S3ecreT';
keyString
or keyFile
- Required for L2 signature- (optional)
passphrase
If the API you are access is secured with an L2 policy, you need to provide the private key corresponding to the public key uploaded for appId
.
Provide either the path to your private key used to generate your L2 signature in keyFile
or the actual contents in keyString
.
let keyFile = '/path/to/my/private.key';
let keyString = '----BEGIN PRIVATE KEY ----\n ${private_key_contents} \n -----END PRIVATE KEY-----';
let passphrase = 'passphrase for the keyString';
Optional options
An identifier for the caller, this can be set to any value.
Object representation of form data (x-www-form-urlencoded) passed during HTTP POST / HTTP PUT requests
let formData = {key : 'value'};
let postData = qs.stringify(formData, null, null, {encodeURIComponent: encodeURIComponent});
let req = request(param.httpMethod, targetURL.href);
req.buffer(true);
req = req.type("application/x-www-form-urlencoded").set("Content-Length", Buffer.byteLength(postData)).send(postData);
NOTE
For formData parameter used for Signature generation, the key value parameters do not need to be URL encoded,
When your client program is making the actual HTTP POST call, the key value parameters has to be URL encoded
Object representation of URL query parameters, for the API.
IMPORTANT NOTE For version v0.7.7 and below : You can also leave the query string on the urlPath parameter; it will automatically be extracted, and you won't have to use this parameter.
IMPORTANT NOTE From v0.7.8 onwards : If you pass in the params in queryString or formData, please remove the queryString from the urlPath parameter
For example, the API endpoint is https://example.com/v1/api?key=value , then you have you pass in the params in this manner below :
let qsData = {
abc: 'def',
ghi: 123
}
const requestOptions = {
appId: 'my-app-id',
secret: 'my-app-secret',
authPrefix: 'apex_l1_eg',
httpMethod: 'get',
urlPath: 'https://api.example.com'
queryString : qsData
};
An arbitrary string, needs to be different after each successful API call. Defaults to 32 bytes random value encoded in base64.
A unix timestamp. Defaults to the current unix timestamp.
Logging
To see detailed logs while using ApiSigningUtil, set the log level to trace
ApiSigningUtil.setLogLevel('trace');
Security Signature Token Example
Authorization: Apex_l2_ig realm="http://api.mygateway.com",
apex_l2_ig_timestamp="1502199514462",
apex_l2_ig_nonce="UldycUAF56GWJGlWz0YSwOOp5gruJqvBy0CJeZ4XpGk=",
apex_l2_ig_app_id="my-apex-app-id",
apex_l2_ig_signature_method="SHA256withRSA",
apex_l2_ig_signature="Gigxd7Yif2NqiFGI3oi0D3+sVv3QxURLPwCSE9ARyeenYhipG+6gncCR+tWEfaQBGyH9gnG6RtwZh3A==",
apex_l2_ig_version="1.0"
Contributing
For more information about contributing, and raising PRs or issues, see CONTRIBUTING.md.
Release
See CHANGELOG.md.
License
Licensed under the MIT LICENSE
References