node-red-contrib-tdn-sts-gen2 1.0.1
STS_Gen2 & BI API
node-red-contrib-tdn-sts-gen2
Two Node-RED nodes for working with a cloud POS transaction API:
sts-oidc-token— authenticates against an OpenID Connect provider using the OAuth2 Authorization Code Flow with PKCEsts-gen2-poller— watches enabled locations and revenue centres for newly closed (paid) checks and emits each one exactly once
Install
From your Node-RED user directory (typically ~/.node-red):
npm install node-red-contrib-tdn-sts-gen2
Both nodes appear in your palette after install and a restart of Node-RED.
Token node (sts-oidc-token)
The token node performs the full six-step authentication flow on each incoming message:
- Generates a PKCE code verifier + SHA-256 challenge
GET /oidc-provider/v1/oauth2/authorize— captures session cookies- Replays the cookies to
POST /oidc-provider/v1/oauth2/signinwith your API account credentials - Extracts the authorization
codefrom the returnedredirectUrl POST /oidc-provider/v1/oauth2/tokenwith the code + verifier- Caches the token in node context and reuses it until expiry — repeated messages do not re-authenticate while the cached token is valid
Usage
Send a message with a msg.credentials object:
msg.credentials = {
authHost: "https://<your-auth-host>", // OIDC provider host only, no path
clientId: "<client-id>",
username: "<api-account-username>",
password: "<api-account-password>",
orgShortName: "<org-short-name>"
};
return msg;
All five fields are required; the node reports a specific error and status for any missing field.
On success the message passes through with the token attached:
msg.tokenOut = {
access_token: "...",
id_token: "...", // typically used as the Bearer token for API calls
refresh_token: "...",
expires_in: "...",
token_type: "Bearer"
}
Use msg.tokenOut.id_token in the Authorization: Bearer header for
downstream API requests.
Node status
The node shows its exact state in the editor: validating input,
requesting token, cookies stored, token stored, token valid,
token expired, or a specific error state.
Poller node (sts-gen2-poller)
The poller node runs its own non-overlapping poll loop (default every 15 s) and queries the checks endpoint once per enabled (location, revenue centre) pair, capped at a configurable number of parallel requests. It emits only closed checks, exactly once each — checks without payment tenders or line items are held back so no partial receipt is ever dispatched downstream.
It is driven entirely from global context:
global.set("cfg", { apiBase: "https://<api-host>/api", orgShortName: "..." });
global.set("locations", [
{ locRef: "loc1", name: "Site 1", enabled: true,
rvcRefs: [ { rvcRef: 101, name: "Bar", enabled: true } ] }
]);
The work list is rebuilt from locations on every cycle, so enabling or
disabling a location or revenue centre takes effect on the next poll without a
redeploy.
Token handling: wire the token node's output into the poller's input — any
message carrying msg.tokenOut is consumed as a token push. The poller can
also fall back to a configurable global context key. On a 401/403 it drops the
cached token, emits a token-kind error, and keeps polling with backoff.
Outputs (4): status, closed checks, open checks (off by default), errors.
Closed-check messages carry msg.payload (full check), msg.summary (flat
record with location/revenue-centre refs, totals, and tenders), and
msg.topic = locRef/rvcRef for routing.
Input commands (msg.topic or string payload): poll, start, stop,
reset.
Why closed-only polling works: the API's sinceTime filter matches check
creation time, so every check created inside the configurable lookback window
(default 240 min) reappears in each poll until it ages out. Whenever it closes,
the next poll sees the closed status and emits it. Set the lookback longer than
the longest-lived open check.
Notes
- Credentials should come from context or a secure store — never hard-code them in a flow.
- Some providers expire API account passwords on a fixed schedule and lock the account temporarily after repeated failed sign-ins — handle credential rotation accordingly.
- The token is cached per node instance (node context) and re-requested only
after
expires_inelapses.
License
MIT