diff --git a/lib/assets/error.js b/lib/assets/error.js new file mode 100644 index 0000000..8ec020e --- /dev/null +++ b/lib/assets/error.js @@ -0,0 +1,4 @@ +/* eslint-disable max-len */ +module.exports = { + 'INVALID_AUTH_TYPE': new Error('Unknown authorizaition method') +}; diff --git a/lib/auth/auth.js b/lib/auth/auth.js new file mode 100644 index 0000000..eabdcbf --- /dev/null +++ b/lib/auth/auth.js @@ -0,0 +1,154 @@ +/** + * Contains basic authentication methods: + * - Basic Auth + * - API key Auth + * - Bearer Token Auth + * Authorizer method which calls the above methods as per the input auth + */ + +const sdk = require('postman-collection'), + errors = require('../assets/error'), + aws = require('./aws'), + { + toBase64 + } = require('../helpers'); + + +/** + * Adds necessary headers / url params for api key authentication + * In header -> key:value + * In query param -> url?key=value + * + * @param {sdk.Request} request - Request Instance + * @param {sdk.RequestAuth} auth - Auth that needs to be applied to the given request + * @returns {sdk.Request} - Requst with applied auth + */ +function apiKey (request, auth) { + let config = {}; + // creating congif obj for easy access of elements + auth.apikey.each((element) => { + config[element.key] = element.value; + }); + + // return same request if apikey header or query param is already added + if (request.headers.has(config.key) || request.url.query.get(config.key)) { + return request; + } + + // if api key `key` is empty then dont add + if (config.key === '') { + return request; + } + + // if apikey auth intype is query params + if (config.in === 'query') { + // adding new query param to request for api key + request.url.addQueryParams(new sdk.QueryParam({ + key: config.key, + value: config.value + })); + } + // if apikey auth intype is headers + else { + // adding apikey auth headers to request + request.addHeader(new sdk.Header({ + key: config.key, + value: config.value + })); + } + + return request; +} + +/** + * Adds Authorization header for bearer authorization + * Authorization: Bearer bearer_token + * + * @param {sdk.Request} request - Request Instance + * @param {sdk.RequestAuth} auth - Auth that needs to be applied to the given request + * @returns {sdk.Request} - Requst with applied auth + */ +function bearerToken (request, auth) { + // return same request if auth headers are already added + if (request.headers.has('authorization')) { + return request; + } + + let config = {}; + // creating congif obj for easy access of elements + auth.bearer.each((element) => { + config[element.key] = element.value; + }); + + // if bearer token is empty then dont add + if (config.token === '') { + return request; + } + + // Adds Authorizaition: Bearer token_value to request + request.addHeader(new sdk.Header({ + key: 'Authorization', + value: 'Bearer ' + config.token + })); + + return request; +} + +/** + * Adds Authorization header for basic authorization + * Authorization: basic buagwdnasdw== + * + * @param {sdk.Request} request - Request Instance + * @param {sdk.RequestAuth} auth - Auth that needs to be applied to the given request + * @returns {sdk.Request} - Requst with applied auth + */ +function basic (request, auth) { + // return same request if auth headers are already added + if (request.headers.has('authorization')) { + return request; + } + + let config = {}; + // creating congif obj for easy access of elements + auth.basic.each((element) => { + config[element.key] = element.value; + }); + + /** + * Authorization header: + * Basic base64(username:password) + */ + request.addHeader(new sdk.Header({ + key: 'Authorization', + value: 'Basic ' + toBase64(`${config.username}:${config.password}`) + })); + + return request; +} + +/** + * Authorizes a postman-request instance + * + * @param {sdk.Request} request - Request Instance + * @param {sdk.RequestAuth} auth - Auth that needs to be applied to the given request + * @returns {sdk.Request} - Requst with applied auth + */ +function authorize (request, auth) { + // checking for auth type and invoking related method + if (auth.type === 'apikey') { + return apiKey(request, auth); + } + else if (auth.type === 'bearer') { + return bearerToken(request, auth); + } + else if (auth.type === 'basic') { + return basic(request, auth); + } + else if (auth.type === 'awsv4') { + return aws(request, auth); + } + + throw errors.INVALID_AUTH_TYPE; +} + +module.exports = authorize; diff --git a/lib/auth/aws.js b/lib/auth/aws.js new file mode 100644 index 0000000..276599a --- /dev/null +++ b/lib/auth/aws.js @@ -0,0 +1,73 @@ +const sdk = require('postman-collection'), + getConfig = require('./utils').getAuthOptions, + aws = require('aws4'); + +/** + * Adds necessary headers / url params for aws signature 4 authorization + * Reference: https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html + * + * @note Does not support requests with form data body type + * @param {sdk.Request} request - Request Instance + * @param {sdk.RequestAuth} auth - Auth that needs to be applied to the given request + * @returns {sdk.Request} - Requst with applied auth + */ +function awsAuth (request, auth) { + let config = getConfig(auth), + options, signedRequestParams, parsedUrl; + + // adding X-Amz-Security-Token query param if session token is provided + if (config.sessionToken) { + request.url.addQueryParams({ + key: 'X-Amz-Security-Token', + value: config.sessionToken + }); + } + + /** + * options required for signing request + * - host + * - path along with query params + * - aws service, if null -> 'execute-api' + * - aws region, if null -. 'us-east-1' + * - headers (existing headers in the request) + * - stringified body (will return for form data and multipart body) + * - accessKeyId + * - secretAccessKey + * - signQuery (add auth data to query params) + * - sessionToken + */ + options = { + host: request.url.getHost(), + path: request.url.getPathWithQuery(), + headers: request.getHeaders(), + body: request.body ? request.body.toString() : undefined, + service: config.service || 'execute-api', + region: config.region || 'us-east-1', + asccessKeyId: config.accessKey, + secretAccessKey: config.secretKey, + sessionToken: config.sessionToken, + signQuery: config.addAuthDataToQuery + }; + + // signing request with above options + signedRequestParams = aws.sign(options); + + if (config.addAuthDataToQuery) { + // unparsing path build by aws.sign + // if session token is provided in the options then it will be added to the path + parsedUrl = sdk.Url.parse(signedRequestParams.path); + // repopuating request query params to eliminate unwanted duplication and to add auth query params + request.url.query.repopulate(parsedUrl.query); + // adding auth data to headers if addAuthDataToQuery is false + } + else { + request.addHeader({ + key: 'Authorization', + value: signedRequestParams.headers.Authorization + }); + } + + return request; +} + +module.exports = awsAuth; diff --git a/lib/auth/utils.js b/lib/auth/utils.js new file mode 100644 index 0000000..1264b0e --- /dev/null +++ b/lib/auth/utils.js @@ -0,0 +1,19 @@ +/** + * Pulls elements from auth instance and return a json object with all the params + * + * @param {sdk.RequestAuth} auth - auth instance + * @returns {object} - object containing all the auth parametes as key value pairs + */ +function getAuthOptions (auth) { + let config = {}; + // creating congif obj for easy access of elements + auth[auth.type].each((element) => { + config[element.key] = element.value; + }); + + return config; +} + +module.exports = { + getAuthOptions +}; diff --git a/lib/helpers.js b/lib/helpers.js new file mode 100644 index 0000000..c83a099 --- /dev/null +++ b/lib/helpers.js @@ -0,0 +1,101 @@ +'use strict'; + +var crypto = require('crypto'), + Buffer = require('safe-buffer').Buffer; + +/** + * Converts String to base64 equivalent + * + * @param {string} str - Input string + * @returns {string} - Base64 converted input string + */ +function toBase64 (str) { + return Buffer.from(str || '', 'utf8').toString('base64'); +} + +/** + * Creats a deep copy of an object; + * + * @param {object} object - Input Object + * @returns {object} - copy of input object + */ +function copy (object) { + var objectCopy = {}; + Object.keys(object).forEach(function (i) { + objectCopy[i] = object[i]; + }); + return objectCopy; +} + +/** + * Creates md5 hash for input string + * + * @param str - String whose md5 hash has to be calculated + * @returns {string} - md5 hash of input string + */ +function md5 (str) { + return crypto.createHash('md5').update(str).digest('hex'); +} + +/** + * Creates sha256 hash for input string + * + * @param str - String whose md5 hash has to be calculated + * @returns {string} - md5 hash of input string + */ +function sha256 (str) { + return crypto.createHash('sha256').update(str).digest('hex'); +} + +/** + * Creates sha512 hash for input string + * + * @param str - String whose md5 hash has to be calculated + * @returns {string} - md5 hash of input string + */ +function sha512 (str) { + return crypto.createHash('sha512').update(str).digest('hex'); +} + +/** + * Creates a HMAC hash with input secter key and algorithm + * + * @param secret - Secret key + * @param helper - String whose hash has to be calculated + * @param algorithm - algorithm to be used + */ +function hmac (secret, helper, algorithm) { + return crypto.createHmac(algorithm, secret).update(helper); +} + +/** + * Method to return current time stamp + * + * @returns {number} timestamp + */ +function getTimeStamp () { + return Math.floor(Date.now() / 1000); +} + +/** + * Function to return random string of desired length + * + * @param length + * @returns {string} random string + */ +function randomString (length) { + return Math.random().toString(36).substring(length); + +} +module.exports = { + hash: { + md5, + sha256, + sha512 + }, + hmac, + toBase64, + copy, + getTimeStamp, + randomString +}; diff --git a/npm/test-unit.js b/npm/test-unit.js index 1bd787a..648d066 100644 --- a/npm/test-unit.js +++ b/npm/test-unit.js @@ -22,6 +22,7 @@ module.exports = function (exit) { test('-d', COV_REPORT_PATH) && rm('-rf', COV_REPORT_PATH); mkdir('-p', COV_REPORT_PATH); + mkdir('-p', COV_REPORT_PATH + '/processinfo'); var Mocha = require('mocha'), nyc = new NYC({ diff --git a/package.json b/package.json index d3a2a04..c7b31f0 100644 --- a/package.json +++ b/package.json @@ -20,5 +20,23 @@ "bugs": { "url": "https://github.com/umeshp7/postman-collection-code-generators/issues" }, - "homepage": "https://github.com/umeshp7/postman-collection-code-generators#readme" + "homepage": "https://github.com/umeshp7/postman-collection-code-generators#readme", + "dependencies": { + "aws4": "^1.10.0", + "chai": "^4.2.0", + "postman-collection": "^3.6.4" + }, + "devDependencies": { + "async": "^3.2.0", + "chai": "^4.2.0", + "eslint": "^7.5.0", + "eslint-plugin-jsdoc": "^30.0.3", + "eslint-plugin-lodash": "^7.1.0", + "eslint-plugin-security": "^1.4.0", + "mocha": "^8.0.1", + "nyc": "^15.1.0", + "pretty-ms": "^7.0.0", + "recursive-readdir": "^2.2.2", + "shelljs": "^0.8.4" + } } diff --git a/test/fixtures/auth_requests.js b/test/fixtures/auth_requests.js new file mode 100644 index 0000000..c10b04f --- /dev/null +++ b/test/fixtures/auth_requests.js @@ -0,0 +1,647 @@ +const sdk = require('postman-collection'); + +/** + * JSON containing request used for requestAuth testing + * Format: + * root { + * auth_method { + * PARAMETERS_CAPS_ON : PostmanRequest instance for this auth and config + * } + * } + */ +module.exports = { + + // api key authorization + 'API_KEY': { + // if api key & value are given with input type as header + 'KEY_VAL_HEADER': new sdk.Request({ + 'url': { + 'protocol': 'https', + 'path': ['get'], + 'host': ['postman-echo', 'com'], + 'query': [{ + 'key': 'foo1', + 'value': 'bar1' + }, { + 'key': 'foo2', + 'value': 'aa' + }], + 'variable': [] + }, + 'method': 'GET', + 'auth': { + 'type': 'apikey', + 'apikey': [{ + 'type': 'any', + 'value': 'header', + 'key': 'in' + }, { + 'type': 'any', + 'value': 'key', + 'key': 'key' + }, { + 'type': 'any', + 'value': 'value', + 'key': 'value' + }] + } + }), + // if only api key is given with input type as header + 'KEY_HEADER': new sdk.Request({ + 'url': { + 'protocol': 'https', + 'path': ['get'], + 'host': ['postman-echo', 'com'], + 'query': [{ + 'key': 'foo1', + 'value': 'bar1' + }, { + 'key': 'foo2', + 'value': 'aa' + }], + 'variable': [] + }, + 'method': 'GET', + 'auth': { + 'type': 'apikey', + 'apikey': [{ + 'type': 'any', + 'value': 'header', + 'key': 'in' + }, { + 'type': 'any', + 'value': 'key', + 'key': 'key' + }, { + 'type': 'any', + 'value': '', + 'key': 'value' + }] + } + }), + // if api key is not given and input type is header + 'HEADER': new sdk.Request({ + 'url': { + 'protocol': 'https', + 'path': ['get'], + 'host': ['postman-echo', 'com'], + 'query': [{ + 'key': 'foo1', + 'value': 'bar1' + }, { + 'key': 'foo2', + 'value': 'aa' + }], + 'variable': [] + }, + 'method': 'GET', + 'auth': { + 'type': 'apikey', + 'apikey': [{ + 'type': 'any', + 'value': 'query', + 'key': 'in' + }, { + 'type': 'any', + 'value': '', + 'key': 'key' + }, { + 'type': 'any', + 'value': 'val', + 'key': 'value' + }] + } + }), + // if api key and value are given with in type as query params + 'KEY_VAL_QUERY': new sdk.Request({ + 'url': { + 'protocol': 'https', + 'path': ['get'], + 'host': ['postman-echo', 'com'], + 'query': [{ + 'key': 'foo1', + 'value': 'bar1' + }, { + 'key': 'foo2', + 'value': 'aa' + }], + 'variable': [] + }, + 'method': 'GET', + 'auth': { + 'type': 'apikey', + 'apikey': [{ + 'type': 'any', + 'value': 'query', + 'key': 'in' + }, { + 'type': 'any', + 'value': 'key', + 'key': 'key' + }, { + 'type': 'any', + 'value': 'value', + 'key': 'value' + }] + } + }), + // if only api key is given with input type as query param + 'KEY_QUERY': new sdk.Request({ + 'url': { + 'protocol': 'https', + 'path': ['get'], + 'host': ['postman-echo', 'com'], + 'query': [{ + 'key': 'foo1', + 'value': 'bar1' + }, { + 'key': 'foo2', + 'value': 'aa' + }], + 'variable': [] + }, + 'method': 'GET', + 'auth': { + 'type': 'apikey', + 'apikey': [{ + 'type': 'any', + 'value': 'query', + 'key': 'in' + }, { + 'type': 'any', + 'value': 'key', + 'key': 'key' + }, { + 'type': 'any', + 'value': '', + 'key': 'value' + }] + } + }), + // if neither api key or value is given with in type as query param + 'QUERY': new sdk.Request({ + 'url': { + 'protocol': 'https', + 'path': ['get'], + 'host': ['postman-echo', 'com'], + 'query': [{ + 'key': 'foo1', + 'value': 'bar1' + }, { + 'key': 'foo2', + 'value': 'aa' + }], + 'variable': [] + }, + 'method': 'GET', + 'auth': { + 'type': 'apikey', + 'apikey': [{ + 'type': 'any', + 'value': 'query', + 'key': 'in' + }, { + 'type': 'any', + 'value': '', + 'key': 'key' + }, { + 'type': 'any', + 'value': '', + 'key': 'value' + }] + } + }) + }, + + // bearer token authorization + 'BEARER_TOKEN': { + // when bearer token is given + 'TOKEN': new sdk.Request({ + 'url': { + 'protocol': 'https', + 'path': ['get'], + 'host': ['postman-echo', 'com'], + 'query': [{ + 'key': 'foo1', + 'value': 'bar1' + }, { + 'key': 'foo2', + 'value': 'aa' + }], + 'variable': [] + }, + 'method': 'GET', + 'auth': { + 'type': 'bearer', + 'bearer': [{ + 'type': 'any', + 'value': 'testbearertoken', + 'key': 'token' + }] + } + }) + }, + + // basic authorization + 'BASIC': { + // if username password are given + 'USERNAME_PASSWORD': new sdk.Request({ + 'url': { + 'protocol': 'https', + 'path': ['get'], + 'host': ['postman-echo', 'com'], + 'query': [{ + 'key': 'foo1', + 'value': 'bar1' + }, { + 'key': 'foo2', + 'value': 'aa' + }], + 'variable': [] + }, + 'method': 'GET', + 'auth': { + 'type': 'basic', + 'basic': [{ + 'type': 'any', + 'value': 'test', + 'key': 'password' + }, { + 'type': 'any', + 'value': 'test', + 'key': 'username' + }] + } + }), + // if only username is given + 'USERNAME': new sdk.Request({ + 'url': { + 'protocol': 'https', + 'path': ['get'], + 'host': ['postman-echo', 'com'], + 'query': [{ + 'key': 'foo1', + 'value': 'bar1' + }, { + 'key': 'foo2', + 'value': 'aa' + }], + 'variable': [] + }, + 'method': 'GET', + 'auth': { + 'type': 'basic', + 'basic': [{ + 'type': 'any', + 'value': '', + 'key': 'password' + }, { + 'type': 'any', + 'value': 'test', + 'key': 'username' + }] + } + }), + // if only password is given + 'PASSWORD': new sdk.Request({ + 'url': { + 'protocol': 'https', + 'path': ['get'], + 'host': ['postman-echo', 'com'], + 'query': [{ + 'key': 'foo1', + 'value': 'bar1' + }, { + 'key': 'foo2', + 'value': 'aa' + }], + 'variable': [] + }, + 'method': 'GET', + 'auth': { + 'type': 'basic', + 'basic': [{ + 'type': 'any', + 'value': 'test', + 'key': 'password' + }, { + 'type': 'any', + 'value': '', + 'key': 'username' + }] + } + }), + + // if neither username nor password is given + 'NO_USERNAME_NO_PASS': new sdk.Request({ + 'url': { + 'protocol': 'https', + 'path': ['get'], + 'host': ['postman-echo', 'com'], + 'query': [{ + 'key': 'foo1', + 'value': 'bar1' + }, { + 'key': 'foo2', + 'value': 'aa' + }], + 'variable': [] + }, + 'method': 'GET', + 'auth': { + 'type': 'basic', + 'basic': [{ + 'type': 'any', + 'value': '', + 'key': 'password' + }, { + 'type': 'any', + 'value': '', + 'key': 'username' + }] + } + }) + }, + 'AWSV4': { + 'NO_ACCESSKEY_NO_SECRET': new sdk.Request({ + 'url': { + 'protocol': 'https', + 'path': ['post'], + 'host': ['postman-echo', 'com'], + 'query': [], + 'variable': [] + }, + 'header': [{ + 'key': 'Content-Length', + 'value': '22' + }], + 'method': 'POST', + 'body': { + 'mode': 'formdata', + 'formdata': [{ + 'key': 'awdawd', + 'value': 'awdawd', + 'type': 'text' + }, { + 'disabled': true, + 'key': '', + 'value': '', + 'type': 'file', + 'src': '/home/wolf/Pictures/arch.png' + }] + }, + 'auth': { + 'type': 'awsv4', + 'awsv4': [{ + 'type': 'any', + 'value': '', + 'key': 'accessKey' + }, { + 'type': 'any', + 'value': false, + 'key': 'addAuthDataToQuery' + }, { + 'type': 'any', + 'value': '', + 'key': 'region' + }, { + 'type': 'any', + 'value': '', + 'key': 'secretKey' + }, { + 'type': 'any', + 'value': '', + 'key': 'service' + }, { + 'type': 'any', + 'value': '', + 'key': 'sessionToken' + }] + } + }), + 'ACCESSKEY_SECRET': new sdk.Request({ + 'url': { + 'protocol': 'https', + 'path': ['post'], + 'host': ['postman-echo', 'com'], + 'query': [], + 'variable': [] + }, + 'header': [{ + 'key': 'Content-Length', + 'value': '22' + }], + 'method': 'POST', + 'body': { + 'mode': 'formdata', + 'formdata': [{ + 'key': 'awdawd', + 'value': 'awdawd', + 'type': 'text' + }, { + 'disabled': true, + 'key': '', + 'value': '', + 'type': 'file', + 'src': '/home/wolf/Pictures/arch.png' + }] + }, + 'auth': { + 'type': 'awsv4', + 'awsv4': [{ + 'type': 'any', + 'value': 'KEY', + 'key': 'accessKey' + }, { + 'type': 'any', + 'value': false, + 'key': 'addAuthDataToQuery' + }, { + 'type': 'any', + 'value': '', + 'key': 'region' + }, { + 'type': 'any', + 'value': 'SECRET', + 'key': 'secretKey' + }, { + 'type': 'any', + 'value': '', + 'key': 'service' + }, { + 'type': 'any', + 'value': '', + 'key': 'sessionToken' + }] + } + }), + 'ACCESS_KEY_ADAVANCE_PARAM': new sdk.Request({ + 'url': { + 'protocol': 'https', + 'path': ['post'], + 'host': ['postman-echo', 'com'], + 'query': [], + 'variable': [] + }, + 'header': [{ + 'key': 'Content-Length', + 'value': '22' + }], + 'method': 'POST', + 'body': { + 'mode': 'formdata', + 'formdata': [{ + 'key': 'awdawd', + 'value': 'awdawd', + 'type': 'text' + }, { + 'disabled': true, + 'key': '', + 'value': '', + 'type': 'file', + 'src': '/home/wolf/Pictures/arch.png' + }] + }, + 'auth': { + 'type': 'awsv4', + 'awsv4': [{ + 'type': 'any', + 'value': 'KEY', + 'key': 'accessKey' + }, { + 'type': 'any', + 'value': false, + 'key': 'addAuthDataToQuery' + }, { + 'type': 'any', + 'value': 'in-east-1', + 'key': 'region' + }, { + 'type': 'any', + 'value': 'SECRET', + 'key': 'secretKey' + }, { + 'type': 'any', + 'value': 's4', + 'key': 'service' + }, { + 'type': 'any', + 'value': 'session', + 'key': 'sessionToken' + }] + } + }), + 'ACCESSKEY_SECRET_SESSION': new sdk.Request({ + 'url': { + 'protocol': 'https', + 'path': ['post'], + 'host': ['postman-echo', 'com'], + 'query': [], + 'variable': [] + }, + 'header': [{ + 'key': 'Content-Length', + 'value': '22' + }], + 'method': 'POST', + 'body': { + 'mode': 'formdata', + 'formdata': [{ + 'key': 'awdawd', + 'value': 'awdawd', + 'type': 'text' + }, { + 'disabled': true, + 'key': '', + 'value': '', + 'type': 'file', + 'src': '/home/wolf/Pictures/arch.png' + }] + }, + 'auth': { + 'type': 'awsv4', + 'awsv4': [{ + 'type': 'any', + 'value': 'KEY', + 'key': 'accessKey' + }, { + 'type': 'any', + 'value': false, + 'key': 'addAuthDataToQuery' + }, { + 'type': 'any', + 'value': 'in-east-1', + 'key': 'region' + }, { + 'type': 'any', + 'value': 'SECRET', + 'key': 'secretKey' + }, { + 'type': 'any', + 'value': 's4', + 'key': 'service' + }, { + 'type': 'any', + 'value': 'session', + 'key': 'sessionToken' + }] + } + }), + 'ALL_PARAM_IN_QUERY': new sdk.Request({ + 'url': { + 'protocol': 'https', + 'path': ['post'], + 'host': ['postman-echo', 'com'], + 'query': [], + 'variable': [] + }, + 'header': [{ + 'key': 'Content-Length', + 'value': '22' + }], + 'method': 'POST', + 'body': { + 'mode': 'formdata', + 'formdata': [{ + 'key': 'awdawd', + 'value': 'awdawd', + 'type': 'text' + }, { + 'disabled': true, + 'key': '', + 'value': '', + 'type': 'file', + 'src': '/home/wolf/Pictures/arch.png' + }] + }, + 'auth': { + 'type': 'awsv4', + 'awsv4': [{ + 'type': 'any', + 'value': 'KEY', + 'key': 'accessKey' + }, { + 'type': 'any', + 'value': true, + 'key': 'addAuthDataToQuery' + }, { + 'type': 'any', + 'value': 'in-east-1', + 'key': 'region' + }, { + 'type': 'any', + 'value': 'SECRET', + 'key': 'secretKey' + }, { + 'type': 'any', + 'value': 's4', + 'key': 'service' + }, { + 'type': 'any', + 'value': 'session', + 'key': 'sessionToken' + }] + } + }) + } +}; diff --git a/test/unit/auth.test.js b/test/unit/auth.test.js new file mode 100644 index 0000000..830e02b --- /dev/null +++ b/test/unit/auth.test.js @@ -0,0 +1,147 @@ +const expect = require('chai').expect, + sdk = require('postman-collection'), + authRequests = require('../fixtures/auth_requests'), + authorize = require('../../lib/auth/auth'); + +describe('Postman Request Authorization', function () { + + describe('API KEY authentication', function () { + it('should add api header to request when in type is header', function () { + let request = authRequests.API_KEY.KEY_VAL_HEADER; + // TODO pass this request to authorize function + request = authorize(request, request.auth); + expect(request).to.be.of.instanceOf(sdk.Request); + expect(request.headers.has('key')).to.be.true; + expect(request.getHeaders('key').key).to.be.equal('value'); + }); + + it('should add api headers to request when api value is not given', function () { + let request = authRequests.API_KEY.KEY_HEADER; + request = authorize(request, request.auth); + expect(request).to.be.of.instanceOf(sdk.Request); + expect(request.headers.has('key')).to.be.true; + expect(request.getHeaders('key').key).to.be.equal(''); + }); + + it('should not add api headers to request when api key and value is not given', function () { + let request = authRequests.API_KEY.HEADER; + request = authorize(request, request.auth); + expect(request).to.be.of.instanceOf(sdk.Request); + }); + + it('should add api key query param when api key value and in type is query', function () { + let request = authRequests.API_KEY.KEY_VAL_QUERY; + request = authorize(request, request.auth); + expect(request).to.be.of.instanceOf(sdk.Request); + expect(request.url.query.has('key')).to.be.true; + expect(request.url.query.get('key')).to.be.equal('value'); + }); + + it('should add api key query param when api key and in type is query', function () { + let request = authRequests.API_KEY.KEY_QUERY; + request = authorize(request, request.auth); + expect(request).to.be.of.instanceOf(sdk.Request); + expect(request.url.query.has('key')).to.be.true; + expect(request.url.query.get('key')).to.be.equal(''); + }); + + it('should add api key query param when api key value and in type is query', function () { + let request = authRequests.API_KEY.QUERY; + request = authorize(request, request.auth); + expect(request).to.be.of.instanceOf(sdk.Request); + }); + }); + + describe('Bearer Token Authorization', function () { + + it('should add authorization header to request when bearer token it given', function () { + let request = authRequests.BEARER_TOKEN.TOKEN; + request = authorize(request, request.auth); + expect(request).to.be.instanceOf(sdk.Request); + expect(request.headers.has('Authorization')).to.be.true; + expect(request.getHeaders('Authorization').Authorization).to.be.equal('Bearer testbearertoken'); + }); + }); + + describe('Basic Authorization', function () { + it('should add authorization header when basic authorization is used with username and password', function () { + var request = authRequests.BASIC.USERNAME_PASSWORD; + request = authorize(request, request.auth); + expect(request).to.be.instanceOf(sdk.Request); + expect(request.headers.has('Authorization')).to.be.true; + expect(request.getHeaders('Authorization').Authorization).to.be.equal('Basic dGVzdDp0ZXN0'); + }); + + it('should add authorization header when basic authorization is used with username and no password', function () { + var request = authRequests.BASIC.USERNAME; + request = authorize(request, request.auth); + expect(request).to.be.instanceOf(sdk.Request); + expect(request.headers.has('Authorization')).to.be.true; + expect(request.getHeaders('Authorization').Authorization).to.be.equal('Basic dGVzdDo='); + }); + + it('should add authorization header when basic authorization is used with just password', function () { + var request = authRequests.BASIC.PASSWORD; + request = authorize(request, request.auth); + expect(request).to.be.instanceOf(sdk.Request); + expect(request.headers.has('Authorization')).to.be.true; + expect(request.getHeaders('Authorization').Authorization).to.be.equal('Basic OnRlc3Q='); + }); + + it('should add authorization header when basic authorization is used with no username/password', function () { + var request = authRequests.BASIC.NO_USERNAME_NO_PASS; + request = authorize(request, request.auth); + expect(request).to.be.instanceOf(sdk.Request); + expect(request.headers.has('Authorization')).to.be.true; + expect(request.getHeaders('Authorization').Authorization).to.be.equal('Basic Og=='); + }); + }); + + describe('AWSv4 Authorization', function () { + it('should generate signature if acesskey and secret are not provided', function () { + var request = authRequests.AWSV4.NO_ACCESSKEY_NO_SECRET; + request = authorize(request, request.auth); + expect(request).to.be.instanceOf(sdk.Request); + expect(request.headers.has('Authorization')).to.be.true; + expect(request.getHeaders('Authorization').Authorization).to.include('AWS4-HMAC-SHA256'); + }); + + it('should generate signature with accessKey and secret provided', function () { + var request = authRequests.AWSV4.ACCESSKEY_SECRET; + request = authorize(request, request.auth); + expect(request).to.be.instanceOf(sdk.Request); + expect(request.headers.has('Authorization')).to.be.true; + expect(request.getHeaders('Authorization').Authorization).to.include('AWS4-HMAC-SHA256'); + }); + + it('should generate signature with optional parameters', function () { + var request = authRequests.AWSV4.ACCESS_KEY_ADAVANCE_PARAM; + request = authorize(request, request.auth); + expect(request).to.be.instanceOf(sdk.Request); + expect(request.headers.has('Authorization')).to.be.true; + expect(request.getHeaders('Authorization').Authorization).to.include('AWS4-HMAC-SHA256'); + expect(request.getHeaders('Authorization').Authorization).to.include('in-east-1'); + expect(request.getHeaders('Authorization').Authorization).to.include('s4'); + }); + + it('should generate signature with session token', function () { + var request = authRequests.AWSV4.ACCESSKEY_SECRET_SESSION; + request = authorize(request, request.auth); + expect(request).to.be.instanceOf(sdk.Request); + expect(request.headers.has('Authorization')).to.be.true; + expect(request.getHeaders('Authorization').Authorization).to.include('AWS4-HMAC-SHA256'); + expect(request.url.getPathWithQuery()).to.include('X-Amz-Security-Token'); + }); + + it('should generate signature with addToQuery set', function () { + var request = authRequests.AWSV4.ALL_PARAM_IN_QUERY; + request = authorize(request, request.auth); + expect(request).to.be.instanceOf(sdk.Request); + expect(request.url.getPathWithQuery()).to.include('X-Amz-Algorithm'); + expect(request.url.getPathWithQuery()).to.include('X-Amz-Credential'); + expect(request.url.getPathWithQuery()).to.include('X-Amz-Signature'); + expect(request.url.getPathWithQuery()).to.include('X-Amz-SignedHeaders'); + expect(request.url.getPathWithQuery()).to.include('X-Amz-Date'); + }); + }); +});