bnw-ims-client
v1.0.1
Published
Identity Microservice (IMS) client SDK — Zero Trust auth for Node.js microservices
Readme
bnw-ims-client
Node.js SDK for the Identity Microservice (IMS). Provides Zero Trust authentication and authorization for services in this ecosystem — validate session tokens and API keys, with optional ACL checks, in a single line.
Installation
During development (local monorepo):
"bnw-ims-client": "file:../identity-service/sdk"Via private registry (production):
npm install bnw-ims-clientSetup
Create a single client instance at service startup and reuse it everywhere.
const { createIMSClient } = require('bnw-ims-client');
const ims = createIMSClient({
baseUrl: process.env.IMS_BASE_URL, // e.g. 'https://ims.internal'
apiKey: process.env.IMS_API_KEY, // This service's own IMS API key secret
});| Option | Type | Required | Description |
| --------- | ------ | -------- | --------------------------------------- |
| baseUrl | string | yes | Base URL of the IMS (no trailing slash) |
| apiKey | string | yes | This microservice's IMS API key secret |
| timeout | number | no | Request timeout in ms (default: 10000) |
Middleware (recommended usage)
The middleware factories return objects compatible with the createHandler middleware chain used across this ecosystem. On success they augment rc.meta.ims with the validation result so the endpoint handler can read it directly.
ims.requireToken([opts])
Validates a Bearer session token from the Authorization header.
const { createHandler } = require('@app-core/server');
// Token validity only — populates rc.meta.ims
module.exports = createHandler({
path: '/businesses',
method: 'get',
middlewares: [ims.requireToken()],
async handler(rc, helpers) {
const { identityId, sessionId, expiresAt } = rc.meta.ims;
// ...
},
});With ACL check — resource ID pulled dynamically from the route param:
module.exports = createHandler({
path: '/businesses/:id',
method: 'delete',
middlewares: [
ims.requireToken({
acl: 'business.delete',
resourceType: 'business',
resourceIdFrom: 'params.id', // dot-path into rc
}),
],
async handler(rc, helpers) {
const { identityId } = rc.meta.ims;
// ...
},
});ims.requireApiKey([opts])
Validates an ApiKey secret from the Authorization header.
// API key validity only
module.exports = createHandler({
path: '/reports',
method: 'get',
middlewares: [ims.requireApiKey()],
async handler(rc, helpers) {
const { identityId, apiKeyId, environment } = rc.meta.ims;
// ...
},
});With ACL check — resource ID from request body:
module.exports = createHandler({
path: '/payments',
method: 'post',
middlewares: [
ims.requireApiKey({
acl: 'payment.create',
resourceType: 'business',
resourceIdFrom: 'body.business_id',
}),
],
async handler(rc, helpers) {
const { identityId, environment } = rc.meta.ims;
// ...
},
});Middleware options
| Option | Type | Description |
| ---------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
| acl | string | ACL action key to check (e.g. 'business.create'). When set, resourceType and one of resourceId/resourceIdFrom are also required. |
| resourceType | string | The type of resource to check access against (e.g. 'business') |
| resourceId | string | Static resource ID (use when the ID is always the same) |
| resourceIdFrom | string | Dot-path into rc to resolve the resource ID at request time (e.g. 'params.id', 'body.business_id', 'query.resource_id') |
rc.meta.ims shape
After a successful requireToken:
| Field | Type | Description |
| ------------ | ------- | ------------------------------- |
| authorized | boolean | Always true |
| identityId | string | The authenticated identity's ID |
| sessionId | string | Active session ID |
| expiresAt | number | Session expiry timestamp (ms) |
After a successful requireApiKey:
| Field | Type | Description |
| ------------- | ------- | ----------------------------------- |
| authorized | boolean | Always true |
| identityId | string | The identity the API key belongs to |
| apiKeyId | string | The API key record ID |
| environment | string | live or test |
Raw validation
For use in background workers, queue consumers, or any code outside an endpoint handler.
// Token check — no ACL
const result = await ims.validateToken({ token: rawToken });
// Token check — with ACL
const result = await ims.validateToken({
token: rawToken,
acl: 'report.export',
resourceId: businessId,
resourceType: 'business',
});
// API key check — no ACL
const result = await ims.validateApiKey({ apiKey: rawSecret });
// API key check — with ACL
const result = await ims.validateApiKey({
apiKey: rawSecret,
acl: 'payment.create',
resourceId: businessId,
resourceType: 'business',
});Error handling
All validation failures throw typed errors. In middleware they propagate up to the framework's error handler automatically. In raw calls, catch them explicitly.
const {
IMSError,
IMSTokenInvalidError,
IMSTokenExpiredError,
IMSUnauthorizedError,
IMSNoResourceAccessError,
} = require('bnw-ims-client');
try {
await ims.validateToken({ token });
} catch (err) {
if (err instanceof IMSTokenExpiredError) {
/* session expired */
}
if (err instanceof IMSUnauthorizedError) {
/* valid token, no ACL rights */
}
if (err instanceof IMSNoResourceAccessError) {
/* no resource access record */
}
if (err instanceof IMSTokenInvalidError) {
/* invalid/missing token */
}
if (err instanceof IMSError) {
/* any other IMS error, check err.statusCode */
}
}| Class | When thrown |
| -------------------------- | ---------------------------------------------------------------- |
| IMSTokenInvalidError | Token/key is missing, malformed, revoked, or not found |
| IMSTokenExpiredError | Session or API key has passed its expiry |
| IMSUnauthorizedError | Identity found but ACL check failed |
| IMSNoResourceAccessError | No resource access record for the identity + resource |
| IMSError | Base class; network failures, IMS unavailable, unexpected errors |
All error instances expose:
err.statusCode— HTTP status from IMS (0for network errors)err.raw— Raw IMS response body (useful for debugging)
Environment variables
| Variable | Description |
| -------------- | ------------------------------------------------- |
| IMS_BASE_URL | Base URL of the IMS (e.g. https://ims.internal) |
| IMS_API_KEY | This service's IMS API key secret |
