functions/security-requirements.js (52 lines of code) (raw):
// Check:
// - each entry of a global or operation `security` property references a defined
// security scheme.
// - all scopes referenced by an "oauth2" entry are defined in the corresponding
// security scheme.
// @param input - a security property (global or operation)
module.exports = (input, _, context) => {
if (input === null || !Array.isArray(input)) {
return [];
}
const isObject = (obj) => obj && typeof obj === 'object';
const oas2Schemes = (doc) => (isObject(doc.securityDefinitions) ? doc.securityDefinitions : {});
const oas3Schemes = (doc) => (isObject(doc.components) && isObject(doc.components.securitySchemes)
? doc.components.securitySchemes : {});
const oasDoc = context.document.data;
const schemes = oasDoc.swagger ? oas2Schemes(oasDoc) : oas3Schemes(oasDoc);
const path = context.path || [];
const errors = [];
input.forEach((securityReq, index) => {
// oas2-schema requires securityReq to be an object.
// Checking here just to avoid runtime errors.
if (isObject(securityReq)) {
// security with no elements will be flagged by az-security-min-length
Object.keys(securityReq).forEach((key) => {
if (!schemes[key]) {
errors.push({
message: `Security scheme "${key}" is not defined.`,
path: [...path, index, key],
});
return;
}
const scheme = schemes[key];
// oas2-schema requires scheme to be an object.
// Checking here just to avoid runtime errors.
if (!isObject(scheme)) { return; }
const scopes = securityReq[key];
// oas2-schema requires scopes to be an array.
// Checking here just to avoid runtime errors.
if (!Array.isArray(scopes)) { return; }
if (scheme.type === 'oauth2') {
if (scopes.length === 0) {
errors.push({
message: 'OAuth2 security scheme requires at least one scope.',
path: [...path, index, key],
});
}
scopes.forEach((scope, scopeIndex) => {
if (!(scope in scheme.scopes)) {
errors.push({
message: `Scope "${scope}" is not defined for security scheme "${key}".`,
path: [...path, index, key, scopeIndex],
});
}
});
} else if (scopes.length > 0) {
errors.push({
message: `Security scheme "${key}" does not support scopes.`,
path: [...path, index, key],
});
}
});
}
});
return errors;
};