Skip to content
This repository was archived by the owner on May 11, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c40a9d3
Adds auth request list to fixtures
someshkoli Jul 4, 2020
ef47db8
Adds test for request authorizer
someshkoli Jul 4, 2020
39e4967
Completes API key authorizer
someshkoli Jul 4, 2020
e7d8c6f
Adds basic and bearer token authorizer
someshkoli Jul 5, 2020
79883d0
Adds test for basic and bearer token auth
someshkoli Jul 5, 2020
c278b86
Adds helper methods
someshkoli Jul 9, 2020
1b3ff82
Partialli adds digest auth and bearer token auth
someshkoli Jul 9, 2020
e1939c6
Adds Digest Authorization
someshkoli Jul 10, 2020
b192245
Adds necessary comments to auth_requests
someshkoli Jul 10, 2020
2a1f1f1
linting fix
someshkoli Jul 11, 2020
7eb61e4
Changes folder structure for auth
someshkoli Jul 12, 2020
6459ce1
Adds auth parameter to request authorizer method
someshkoli Jul 15, 2020
7a82a09
changes apikey auth insertion point
someshkoli Jul 15, 2020
c18c37e
Removes hawk auth from authorize method
someshkoli Jul 24, 2020
06a650e
fixes auth test
someshkoli Jul 25, 2020
4fdeba7
Removes auth hawk from this branch
someshkoli Jul 26, 2020
2db78e8
Removes digest auth from this branch
someshkoli Jul 26, 2020
70d119a
reverts redundant errors
someshkoli Jul 26, 2020
85c3125
adds check for existing auth headers. If present then returns the sam…
someshkoli Jul 27, 2020
7088de4
Adds aws authorization method
someshkoli Jul 29, 2020
538a773
Fixes issue with session token not being added to query param
someshkoli Jul 29, 2020
1a2e4d9
adds check for existing authorization headers/query params and fixes …
someshkoli Jul 29, 2020
e0232ab
updates package json
someshkoli Jul 29, 2020
e86eb54
adds dependencies to package
someshkoli Jul 29, 2020
e57a411
fixes npm test
someshkoli Jul 29, 2020
5cdbb9d
Merge branch 'feature/auth' of https://github.com/umeshp7/postman-col…
someshkoli Jul 30, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/assets/error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* eslint-disable max-len */
module.exports = {
'INVALID_AUTH_TYPE': new Error('Unknown authorizaition method')
};
154 changes: 154 additions & 0 deletions lib/auth/auth.js
Original file line number Diff line number Diff line change
@@ -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;
73 changes: 73 additions & 0 deletions lib/auth/aws.js
Original file line number Diff line number Diff line change
@@ -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;
19 changes: 19 additions & 0 deletions lib/auth/utils.js
Original file line number Diff line number Diff line change
@@ -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
};
101 changes: 101 additions & 0 deletions lib/helpers.js
Original file line number Diff line number Diff line change
@@ -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
};
1 change: 1 addition & 0 deletions npm/test-unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
20 changes: 19 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
Loading