@xpsolutions/cdr-sdk
v2.0.1
Published
NodeJS middleware to handle error generation in line with Australian Consumer Data Standards technical specifications
Readme
CDR SDK
This repo was forked from the published code on Github here.git pull
Using the CDR SDK
BREAKING CHANGES IN V2
THE MIDDLEWARE FUNCTIONS cdrJwtScopes, cdrScopeValidator, cdrTokenValidator FROM V1 ARE NOW OBSOLETE.
THE NEW FUNCTION cdrAuthorisationValidator AND THE MODIFIED cdrResourceValidator HANDLE THE VALIDATION OF SCOPES AND CONSENTED RESOURCES.
This SDK is intended for developers implementing CDR-compliant APIs in NodeJS/ExpressJS applications. It reduces the complexity and repetition involved in coding compliant APIs by providing ready-to-use middleware that handles common requirements such as error checking, header validation, and endpoint verification.
This code is offered as an npm package available in the NPM registry. You can easily install this package in your project using npm. For more information, refer to the Quick Start section below.
Explore the key middleware functions provided by the JS Holder SDK in the Middleware Functions section below.
Quick Start
To integrate the SDK into your NodeJS/ExpressJS application, ensure npm is installed on your system and run the following command:
npm install @xpsolutions/cdr-sdkImport the necessary middleware functions and configure them as needed:
import { cdrHeaderValidator, cdrResourceValidator, cdrEndpointValidator } from '@xpsolutions/cdr-sdk';
// Example configuration
const dsbOptions = {
// configuration details here
};
app.use(cdrHeaderValidator(dsbOptions));The middleware functions cdrHeaderValidator, cdrEndpointValidator, can optionally accept a configuration object (CdrConfig) that specifies each endpoint the application implements, defined by the request type (GET/POST/DELETE) and path as outlined in the CDS. If the config parameter is not provided, the middleware defaults to using predefined endpoints (DefaultEnergyEndpoints, DefaultBankingEndpoints, and DefaultCommonEndpoints) specified in this repository.
const implementedEndpoints = [
{
"requestType":
"GET",
"requestPath": "/banking/payments/scheduled",
"minSupportedVersion": 1,
"maxSupportedVersion": 1
},
{
"requestType": "GET",
"requestPath": "/banking/accounts/{accountId}/balance",
"minSupportedVersion": 1,
"maxSupportedVersion": 1
}
]
const config: CdrConfig = {
endpoints: implementedEndpoints
}
app.use(cdrHeaderValidator(config))The cdrResourceValidator, cdrAuthorisationValidator, cdrTlsCertValidator require implementation of ISessionService as a parameter. This interface is to be implemented by the consumer of this function and will serve to get access to session data, and in particular access to the cdr arrangement information.
Middleware Functions
Below is a detailed overview of the key middleware functions provided by the JS Holder SDK:
cdrHeaderValidator
Validates request headers and constructs CDR-compliant error responses as necessary.
| Scenario | Description | | --- | --- | | No x-v header is provided in the request | - Http status code 400- An ErrorList is returned with Header/Missing. | | Invalid x-v header is provided with the request, eg alpha character | - Http status code 400- An ErrorList is returned with Header/Invalid. | | Invalid x-min-v header is provided with the request | Http status code 400- An ErrorList is returned with Header/Invalid. | | A requested version is not supported | - Http status code 406- An ErrorList is returned with Header/UnsupportedVersion. | | No x-fapi-interaction-id in the request | An x-fapi-interaction-id header is set in the response header | | Request has x-fapi-interaction-id header | The x-fapi-interaction-id from the request is returned with the response header | | Invalid x-fapi-interaction-id header is provided with the request | - Http status code 400- An ErrorList is returned with Header/Invalid. |
cdrEndpointValidator
Checks if the request URL corresponds to a CDR endpoint and constructs CDR-compliant error responses as necessary.
| Scenario | Description | | --- | --- | | Endpoint not implemented | Http status code 404- An ErrorList is returned with Resource/NotImplemented. | | Endpoint not is not a CDR endpoint | Http status code 404- An ErrorList is returned with Resource/NotFound. |
cdrAuthorisationValidator
This function will:
- check for the presence of an access token
- validate the token based on the getSessionData consumer implementation of the ISessionService
- log any error received from the call to the introspection endpoint of the OIDC provider if the implementation of verfiyAccessToken does such a call
- neutralise the error returned to the consumer of this function
- construct the appropriate return header for the response, eg WWW-authenticate
| Scenario | Description | | --- | --- | | No access token in header | Http status code 401- invalid_request error object as per RFC 6750 | | No session data | Http status code 401- invalid_token error object as per RFC 6750 | | Invalid token, eg expired | Http status code 401- invalid_token error object as per RFC 6750 | | Valid token but insufficient scope | Http status code 403- error message as per CDR standard |
cdrResourceValidator
This function will:
- evaluate the resource identifier against the resources consent was given for
- evaluate the request body of a POST request when it contains resource identifiers
- construct an error object appropriate to the validation failures as defined
- in the technical standards published under the CDR regime by the Data Standards Body
| Scenario | Description | | --- | --- | | No access token in header | Http status code 401- invalid_request error object as per RFC 6750 | | Request body for POST request is invalid | Http status code 400- error message as per CDR standard | | Invalid resource identifiers, eg in POST body|Http status code 404- error message as per CDR standard |
cdrTlsCertValidator
This function will:
- evaluate the thumbprint read from the access token cnf paramater and evaluate against the certificate presented for the request
- construct an error object appropriate to the validation failures as defined in the technical standards published under the CDR regime by the Data Standards Body
| Scenario | Description | | --- | --- | | No client certificate is presented| Http status code 401- invalid_token error object | | The thumbprint (cnf) value doesn't match the certificate|Http status code 401- invalid_token error object |
Utility Functions
buildErrorMessage
This function will return a ReponseErrorListV2. It will use the standard error codes as published by the Data Standards Body (eg urn:au-cds:error:cds-banking:
Authorisation/InvalidBankingAccount) depending on the errorMessageId being passed in
| Parameter | Description |
| --- | --- |
| errorMessageId | an identifier as per DsbStandardError defintions |
| errorDetail | which will be the details property on the returned error object |
| errorList (optional) | an existing error list. The error object wil be appendd to that list |
| metaData (optional) | options metadata object |
Example:
let msg = buildErrorMessage(DsbStandardError.INVALID_BANK_ACCOUNT, "123456");
// returns this as msg
"errors": [
{
"code": "urn:au-cds:error:cds-banking:Authorisation/InvalidBankingAccount",
"title": "Invalid Banking Account",
"detail": "123456"
}
]getLinksPaginated
| Parameter | Description | | --- | --- | | req | The request object | | totalRecords | The total number of records in the dataset |
Example:
if the req object has a url https://api.xpsol.com.au/cds-au/v1/energy/plans?category=ALL&page=4&page-size=2
getLinksPaginated(req, 1000)will return
{
self: "https://api.xpsol.com.au/cds-au/v1/energy/plans?category=ALL&page=4&page-size=2",
next: "https://api.xpsol.com.au/cds-au/v1/energy/plans?category=ALL&page=5&page-size=2",
prev: "https://api.xpsol.com.au/cds-au/v1/energy/plans?category=ALL&page=3&page-size=2",
first: "https://api.xpsol.com.au/cds-au/v1/energy/plans?category=ALL&page=1&page-size=2",
last: "https://api.xpsol.com.au/cds-au/v1/energy/plans?category=ALL&page=500&page-size=2"
}getMetaPaginated
Will return a MetaPaginated object
| Parameter | Description |
| --- | --- |
| totalRecords | The total number of records in the dataset |
| query (optional) | The query property from the Request object |
Example:
getMetaPaginated(1000)
This use the default page-size=25 since no query parameters are passes in.
Therefore, this will return
{
totalRecords: 1000,
totalPages: 40
}paginateData
This will return a subset of data depending on the page-size and page properties from the Request query object
| Parameter | Description | | --- | --- | | data | an array of data objects. | | query | typycally this will be the query property from the Request object |
Example:
let data: any = [
{
"amount": "4439.65",
"description": "payment transaction at Durgan and Sons using card ending with ***(...6407) for XAU 365.41 in account ***06028839",
},
{
"accountId": "d339f6db-cd8d-413f-95e4-ec9e8e9d806f",
"amount": "318.99",
"description": "payment transaction at Gleason - Fadel using card ending with ***(...6904) for SYP 219.10 in
},
{
"extendedData": {
"service": "X2P1.01",
"payer": "Angelica Beatty"
},
},
{
"amount": "4013.89",
"description": "payment transaction at Watson, Braun and Bartell using card ending with ***(...6802) for GEL 281.13 in account ***74872985",
"isDetailAvailable": true,
},
{
"executionDateTime": "2024-01-20T12:49:36.782Z",
"apcaNumber": "572618"
},
]and a query object
let query: any = {
"page-size": "2",
"page" : "2"
}then paginateData(data, query) returns
[
{
"extendedData": {
"service": "X2P1.01",
"payer": "Angelica Beatty"
},
},
{
"amount": "4013.89",
"description": "payment transaction at Watson, Braun and Bartell using card ending with ***(...6802) for GEL 281.13 in account ***74872985",
"isDetailAvailable": true,
}
].
Licensing Information
This repository contains code from a project originally created by Consumer Data Standards Australia, which is licensed under the MIT License. All code in this repository remains under its original license.
