enos-poseidon
v0.2.0
Published
Node.js port of the ENOS API client (enos-poseidon). Signs ENOS API requests with an apim-accesstoken header.
Maintainers
Readme
enos-poseidon (Node.js)
A Node.js port of the Python enos-poseidon package. It signs requests to the ENOS (EnvisionIoT) API gateway by generating the apim-accesstoken header, and transparently refreshes the token and retries once when the gateway reports an expired token.
Zero runtime dependencies — it uses only Node's built-in crypto, http, and https modules.
Install
Copy this package into your project, or add it as a local dependency:
npm install /path/to/enos-poseidonRequires Node.js >= 16.
Usage
const { urlopen } = require('enos-poseidon');
async function main() {
const accessKey = 'your-appkey';
const secretKey = 'your-appsecret';
const url = 'https://ag-cn4.envisioniot.com/connect-service/v2.1/time?orgId=YOUR_ORG';
// GET
const data = await urlopen(accessKey, secretKey, url);
console.log(data);
// POST with JSON body
const result = await urlopen(accessKey, secretKey, url, {
method: 'POST',
data: { deviceKeys: [{ assetId: 'a1' }] },
});
console.log(result);
}
main();API
urlopen(key, secret, url, options?) => Promise<object|string>
Sends a signed request. Returns parsed JSON when the response is JSON, otherwise the raw string body.
| Option | Type | Default | Description |
|---|---|---|---|
| data | object | string | null | Request body. Objects are JSON-stringified. |
| headers | object | {} | Extra request headers. |
| method | string | GET, or POST when data is present | HTTP method. |
| timeout | number | 9000 | Timeout in milliseconds. |
| contentType | string | application/json;charset=utf-8 | Content-Type override. |
| rejectUnauthorized | boolean | false | TLS certificate verification (HTTPS). |
buildAccessToken(key, secret) => string
Returns the apim-accesstoken header value for the given credentials. Useful if you want to sign requests with your own HTTP client.
How the signing works
This is a faithful re-implementation of the Python client:
- pin — Take the segment after the first
-in bothkeyandsecret, concatenate them, parse as a hexadecimal integer, render as decimal, left-pad to 9 digits, and take the first 6 digits. - tokens — Build
pin + expiryTimestampMsfor a short (2h) and long (30d) window, then HMAC-SHA256 each with the built-in secret key and hex-encode. These are the access and refresh tokens. - accesstoken — Concatenate
pin$key$secret$accessToken$refreshToken, RSA-encrypt with the built-in public key using PKCS1-OAEP (SHA-1), and base64-encode. This value is sent as theapim-accesstokenheader. - retry — If the response body has
apim_status4011(access token expired) or4012(refresh token expired), the client rebuilds the token and retries the request once.
Security notes
- Like the original Python client, TLS certificate verification is disabled by default (
rejectUnauthorized: false). For production use, passrejectUnauthorized: trueunless you have a specific reason not to. - The HMAC secret key and RSA public key are embedded constants shipped by ENOS, identical to the upstream Python package.
Testing
npm testtest/verify.jscross-checks thepinderivation and HMAC signing against the actual installed Python package (requires Python +enos-poseidon), and validates the RSA-OAEP output size.test/mock_flow.jsspins up a local HTTP server to verify header injection and the 4011 refresh-and-retry flow.
Compatibility
Verified byte-for-byte identical output against the Python package for the deterministic parts (pin, HMAC). The RSA-OAEP step is non-deterministic by design (random padding) but uses the same key, padding scheme, and hash, so the ENOS gateway accepts tokens produced by either client.
