@unito/integration-debugger
Version:
The Unito Integration Debugger
77 lines (76 loc) • 3.46 kB
JavaScript
// Check: An integration answers a "401 Unauthorized" when passed invalid credentials.
//
// Each request receives a X-Unito-Credentials header which contains a
// Base64-encoded JSON of the credentials required to contact the provider.
//
// The integration must return a 401 when the credentials in X-Unito-Credentials are
// invalid or insufficient to perform the request. Encompass 403.
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const headers_1 = __importDefault(require("../../resources/headers"));
function extractCredentials(step) {
if (!step.headersIn || !step.headersIn[headers_1.default.CREDENTIALS]) {
return;
}
return JSON.parse(Buffer.from(step.headersIn[headers_1.default.CREDENTIALS], 'base64').toString('utf8'));
}
const check = {
label: 'Error - Invalid credentials',
prepareOnPreparedSteps: false,
validateOnError: true,
activatedByDefault: false,
prepare: async (stepResult, _crawlerDriver) => {
const step = stepResult.step;
const credentials = extractCredentials(step);
// This check is only performed when credentials were meant to sent to the integration.
if (!credentials || Object.keys(credentials).length === 0) {
return [];
}
// Invalid credentials are produced based on real credentials, so the shape of the credentials stay the same.
const invalidCredentials = Object.entries(credentials).reduce((h, [key, validValue]) => {
let invalidValue;
if (typeof validValue === 'boolean') {
invalidValue = !validValue;
}
else if (typeof validValue === 'number') {
invalidValue = validValue + 1;
}
else if (typeof validValue === 'object') {
invalidValue = {};
}
else {
invalidValue = [validValue?.toString(), 'invalid'].join('-');
}
h[key] = invalidValue;
return h;
}, {});
step.headersIn ??= {};
// We inject a key in the credentials to know later on that those credentials are supposed to be invalid.
step.headersIn[headers_1.default.CREDENTIALS] = Buffer.from(JSON.stringify({ ...invalidCredentials, integrationDebuggerCheck: true })).toString('base64');
return [step];
},
validate: (step, _crawlerDriver) => {
const credentials = extractCredentials(step);
if (!credentials || !credentials.integrationDebuggerCheck) {
return;
}
const payload = step.payloadOut;
const isError = payload?.code && payload?.message;
if (isError && payload?.code !== '401') {
step.errors.push({
keyword: 'unito',
message: `Return a 401 Unauthorized HTTP response when the credentials are invalid or the user doesn't have access to a resource (403).`,
detailedMessage: `Your integration was sent invalid credentials but did not respond with a 401 Unauthorized`,
instancePath: step.path,
schemaPath: step.schemaPath ?? '',
params: {
code: 'INVALID_CREDENTIALS_UNHANDLED',
},
});
}
},
};
exports.default = check;
;