-
Notifications
You must be signed in to change notification settings - Fork 208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add extra API keys as headers or query params #759
base: develop
Are you sure you want to change the base?
Changes from all commits
939e3ed
759abc5
a538acf
4272aa4
8dfa258
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1133,14 +1133,15 @@ module.exports = { | |
* Gets helper object based on the root spec and the operation.security object | ||
* @param {*} openapi - the json object representing the OAS spec | ||
* @param {Array<object>} securitySet - the security object at an operation level | ||
* @param {boolean} shouldCheckForMultipleKeys - whether we should check for multiple api keys in security rule set | ||
* @returns {object} The authHelper to use while constructing the Postman Request. This is | ||
* not directly supported in the SDK - the caller needs to determine the header/body based on the return | ||
* value | ||
* @no-unit-test | ||
*/ | ||
getAuthHelper: function(openapi, securitySet) { | ||
getAuthHelper: function(openapi, securitySet, shouldCheckForMultipleKeys) { | ||
var securityDef, | ||
helper; | ||
authHelper; | ||
|
||
// return false if security set is not defined | ||
// or is an empty array | ||
|
@@ -1150,8 +1151,10 @@ module.exports = { | |
} | ||
|
||
_.forEach(securitySet, (security) => { | ||
let helper; | ||
|
||
if (_.isObject(security) && _.isEmpty(security)) { | ||
helper = { | ||
authHelper = { | ||
type: 'noauth' | ||
}; | ||
return false; | ||
|
@@ -1293,10 +1296,72 @@ module.exports = { | |
|
||
// stop searching for helper if valid auth scheme is found | ||
if (!_.isEmpty(helper)) { | ||
if (_.isEmpty(authHelper)) { | ||
authHelper = helper; | ||
} | ||
else if (helper.type === 'apikey') { | ||
authHelper.extraAPIKeys = !authHelper.extraAPIKeys ? [] : authHelper.extraAPIKeys; | ||
authHelper.extraAPIKeys.push(helper); | ||
} | ||
} | ||
|
||
if (!_.isEmpty(authHelper) && !shouldCheckForMultipleKeys) { | ||
// Already got a security schema no need to check further | ||
return false; | ||
} | ||
}); | ||
return helper; | ||
return authHelper; | ||
}, | ||
|
||
getExtraAPIKeyParams: function (authHelper) { | ||
const extraAPIKeys = _.get(authHelper, 'extraAPIKeys', []); | ||
let headers = [], | ||
queryParams = []; | ||
|
||
// Remove extraAPIKeys property | ||
_.set(authHelper, 'extraAPIKeys', undefined); | ||
|
||
extraAPIKeys.forEach((apiKey) => { | ||
let keyValuePair = { | ||
key: _.get(apiKey, 'apikey.0.value'), | ||
value: _.get(apiKey, 'apikey.1.value') | ||
}; | ||
|
||
if (_.get(apiKey, 'apikey.2.value') === 'header') { | ||
headers.push(keyValuePair); | ||
} | ||
else { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's use |
||
queryParams.push(keyValuePair); | ||
} | ||
}); | ||
|
||
return { | ||
headers, | ||
queryParams | ||
}; | ||
}, | ||
|
||
areMultipleAPIKeysPresent: function (openapi) { | ||
const securitySet = _.get(openapi, 'security', []); | ||
let count = 0; | ||
|
||
_.forEach(securitySet, (security) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not how you should iterate for multiple API keys. Take a look at this article: there are combinations of AND and OR in case when multiple keys are mentioned. https://swagger.io/docs/specification/authentication/api-keys/?sbsearch=API%20Keys |
||
if (_.isEmpty(security)) { | ||
return; | ||
} | ||
|
||
let securityDef = _.get(openapi, ['securityDefs', Object.keys(security)[0]]); | ||
|
||
if (!_.isObject(securityDef)) { | ||
return; | ||
} | ||
|
||
if (securityDef.type === 'apiKey') { | ||
count += 1; | ||
} | ||
}); | ||
|
||
return count > 1; | ||
}, | ||
|
||
/** | ||
|
@@ -2650,7 +2715,7 @@ module.exports = { | |
|
||
// handling authentication here (for http type only) | ||
if (!options.alwaysInheritAuthentication) { | ||
authHelper = this.getAuthHelper(openapi, operation.security); | ||
authHelper = this.getAuthHelper(openapi, operation.security, true); | ||
} | ||
|
||
// creating the request object | ||
|
@@ -2723,6 +2788,23 @@ module.exports = { | |
} | ||
}); | ||
|
||
let extraAPIKeys = {}; | ||
if (!_.isEmpty(authHelper) && !_.isEmpty(authHelper.extraAPIKeys)) { | ||
extraAPIKeys = this.getExtraAPIKeyParams(authHelper); | ||
} | ||
|
||
if (_.isEmpty(authHelper) && this.areMultipleAPIKeysPresent(openapi)) { | ||
extraAPIKeys = this.getExtraAPIKeyParams(this.getAuthHelper(openapi, openapi.security, true)); | ||
} | ||
|
||
_.forEach(extraAPIKeys.queryParams, (param) => { | ||
item.request.url.addQueryParams(param); | ||
}); | ||
|
||
_.forEach(extraAPIKeys.headers, (header) => { | ||
item.request.addHeader(header); | ||
}); | ||
|
||
// adding Request Body and Content-Type header | ||
if (reqBody) { | ||
if (reqBody.$ref) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
var expect = require('chai').expect, | ||
generateAuthForCollectionFromOpenAPI = require('../../libV2/helpers/collection/generateAuthForCollectionFromOpenAPI'); | ||
|
||
describe('Helper function tests', function () { | ||
describe('getAuthHelper method - Multiple API keys', function() { | ||
it('Should include extra API keys if they are present and we ask for them', function() { | ||
const openAPISpec = { | ||
'securityDefs': { | ||
'EmptyAuth': {}, | ||
'PostmanApiKeyAuth': { | ||
'type': 'apiKey', | ||
'in': 'header', | ||
'name': 'x-api-key', | ||
'description': 'Needs a valid and active user accessToken.' | ||
}, | ||
'PostmanAccessTokenAuth': { | ||
'type': 'apiKey', | ||
'in': 'header', | ||
'name': 'x-access-token', | ||
'description': 'Needs a valid and active user accessToken.' | ||
}, | ||
'ServiceBasicAuth': { | ||
'type': 'http', | ||
'scheme': 'basic', | ||
'description': 'Need basic-auth credential for a service' | ||
} | ||
} | ||
}, | ||
securitySet = [{ PostmanAccessTokenAuth: [] }, { PostmanApiKeyAuth: [] }], | ||
helperData = generateAuthForCollectionFromOpenAPI(openAPISpec, securitySet, true); | ||
|
||
expect(helperData.type).to.be.equal('apikey'); | ||
expect(helperData).to.have.property('apikey').with.lengthOf(3); | ||
expect(helperData.apikey[0]).to.be.an('object'); | ||
expect(helperData).to.deep.equal({ | ||
'type': 'apikey', | ||
'apikey': [ | ||
{ | ||
'key': 'key', | ||
'value': 'x-access-token' | ||
}, | ||
{ | ||
'key': 'value', | ||
'value': '{{apiKey}}' | ||
}, | ||
{ | ||
'key': 'in', | ||
'value': 'header' | ||
} | ||
], | ||
'extraAPIKeys': [ | ||
{ | ||
'type': 'apikey', | ||
'apikey': [ | ||
{ | ||
'key': 'key', | ||
'value': 'x-api-key' | ||
}, | ||
{ | ||
'key': 'value', | ||
'value': '{{apiKey}}' | ||
}, | ||
{ | ||
'key': 'in', | ||
'value': 'header' | ||
} | ||
] | ||
} | ||
] | ||
}); | ||
|
||
}); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we using
authHelper
here specifically if it will anyways get assignedhelper
in line no. 1300.