postman-runtime
Version:
Underlying library of executing Postman Collections (used by Newman)
1,215 lines (1,043 loc) • 48 kB
JavaScript
var _ = require('lodash'),
expect = require('chai').expect,
btoa = require('btoa'),
aws4 = require('aws4'),
sdk = require('postman-collection'),
AuthLoader = require('../../lib/authorizer').AuthLoader,
createAuthInterface = require('../../lib/authorizer/auth-interface'),
Request = sdk.Request,
Url = sdk.Url,
rawRequests = require('../fixtures/auth-requests');
describe('Auth Handler:', function () {
describe('noauth', function () {
it('should work correctly', function () {
var request = new Request({
auth: {
noauth: {},
type: 'noauth'
}
}),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
expect(request).to.eql(request);
authInterface.set({foo: 'bar'});
handler.sign(authInterface, request, _.noop);
expect(request.auth.parameters().toObject()).to.eql({
foo: 'bar'
});
});
});
describe('bearer token', function () {
var requestObj = {
auth: {
type: 'bearer',
bearer: {
token: '123456789abcdefghi'
}
},
method: 'GET'
};
it('should add the auth header', function () {
var request = new Request(requestObj),
authInterface = createAuthInterface(request.auth),
expectedAuthHeader = 'Authorization: Bearer ' + requestObj.auth.bearer.token,
handler = AuthLoader.getHandler(request.auth.type),
headers,
authHeader;
handler.sign(authInterface, request, _.noop);
headers = request.headers.all();
expect(headers).to.have.lengthOf(1);
authHeader = headers[0];
expect(authHeader.toString()).to.eql(expectedAuthHeader);
expect(authHeader.system).to.be.true;
});
it('should return without signing the request when token is missing', function () {
var clonedRequestObj = _.clone(requestObj),
request,
authInterface,
handler,
valuesToCheck = [null, undefined, NaN];
_.forEach(valuesToCheck, function (value) {
clonedRequestObj.auth.bearer.token = value;
request = new Request(clonedRequestObj);
authInterface = createAuthInterface(request.auth);
handler = AuthLoader.getHandler(request.auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.all()).to.be.an('array').that.is.empty;
});
});
});
describe('basic', function () {
it('should add the Auth header', function () {
var request = new Request(rawRequests.basic),
auth = request.auth,
authInterface = createAuthInterface(auth),
username = rawRequests.basic.auth.basic.username,
password = rawRequests.basic.auth.basic.password,
expectedAuthHeader = 'Authorization: Basic ' + btoa(username + ':' + password),
handler = AuthLoader.getHandler(auth.type),
headers,
authHeader;
handler.sign(authInterface, request, _.noop);
headers = request.headers.all();
expect(headers).to.have.lengthOf(1);
authHeader = headers[0];
expect(authHeader.toString()).to.eql(expectedAuthHeader);
expect(authHeader.system).to.be.true;
});
it('should use default values for the missing parameters', function () {
var rawBasicReq = _.cloneDeep(rawRequests.basic),
request,
authInterface,
handler;
rawBasicReq.auth.basic = {username: 'foo'}; // no password present
request = new Request(rawBasicReq);
authInterface = createAuthInterface(request.auth);
handler = AuthLoader.getHandler(request.auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.toJSON()).to.eql([
{key: 'Authorization', value: 'Basic ' + btoa('foo:'), system: true}
]);
rawBasicReq.auth.basic = {password: 'foo'}; // no username present
request = new Request(rawBasicReq);
authInterface = createAuthInterface(request.auth);
handler = AuthLoader.getHandler(request.auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.toJSON()).to.eql([
{key: 'Authorization', value: 'Basic ' + btoa(':foo'), system: true}
]);
rawBasicReq.auth.basic = {}; // no username and no password present
request = new Request(rawBasicReq);
authInterface = createAuthInterface(request.auth);
handler = AuthLoader.getHandler(request.auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.toJSON()).to.eql([
{key: 'Authorization', value: 'Basic ' + btoa(':'), system: true}
]);
});
});
describe('digest', function () {
it('should add the Auth header for (algorithm="MD5", qop=""', function () {
var request = new Request(rawRequests.digest),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type),
headers,
expectedHeader,
authHeader;
handler.sign(authInterface, request, _.noop);
headers = request.headers.all();
expectedHeader = 'Authorization: Digest username="postman", realm="Users", ' +
'nonce="bcgEc5RPU1ANglyT2I0ShU0oxqPB5jXp", uri="/digest-auth", ' +
'algorithm="MD5", response="63db383a0f03744cfd45fe15de8dbe9d", opaque="5ccc069c403ebaf9f0171e9517f40e"';
authHeader;
expect(headers).to.have.lengthOf(1);
authHeader = headers[0];
expect(authHeader.toString()).to.eql(expectedHeader);
expect(authHeader.system).to.be.true;
});
it('should add the Auth header for (algorithm="MD5", qop="auth")', function () {
var clonedReqObj = _.merge({}, rawRequests.digest, {
auth: {
digest: {
qop: 'auth'
}
}
}),
request = new Request(clonedReqObj),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type),
headers,
expectedHeader,
authHeader;
handler.sign(authInterface, request, _.noop);
headers = request.headers.all();
expectedHeader = 'Authorization: Digest username="postman", realm="Users", ' +
'nonce="bcgEc5RPU1ANglyT2I0ShU0oxqPB5jXp", uri="/digest-auth", ' +
'algorithm="MD5", qop=auth, nc=00000001, cnonce="0a4f113b", ' +
'response="f83809617b00766c6f9840256eb1199e", opaque="5ccc069c403ebaf9f0171e9517f40e"';
authHeader;
expect(headers).to.have.lengthOf(1);
authHeader = headers[0];
expect(authHeader.toString()).to.eql(expectedHeader);
expect(authHeader.system).to.be.true;
});
it('should add the Auth header for (algorithm="MD5", qop="auth-int")', function () {
var clonedReqObj = _.merge({}, rawRequests.digest, {
auth: {
digest: {
qop: 'auth-int'
}
}
}),
request = new Request(clonedReqObj),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type),
headers,
expectedHeader,
authHeader;
handler.sign(authInterface, request, _.noop);
headers = request.headers.all();
expectedHeader = 'Authorization: Digest username="postman", realm="Users", ' +
'nonce="bcgEc5RPU1ANglyT2I0ShU0oxqPB5jXp", uri="/digest-auth", ' +
'algorithm="MD5", qop=auth-int, nc=00000001, cnonce="0a4f113b", ' +
'response="65d355634828a04d3a73717dc810a4bf", opaque="5ccc069c403ebaf9f0171e9517f40e"';
authHeader;
expect(headers).to.have.lengthOf(1);
authHeader = headers[0];
expect(authHeader.toString()).to.eql(expectedHeader);
expect(authHeader.system).to.be.true;
});
it('should add the Auth header for (algorithm="MD5-sess", qop="")', function () {
var clonedReqObj = _.merge({}, rawRequests.digest, {
auth: {
digest: {
algorithm: 'MD5-sess'
}
}
}),
request = new Request(clonedReqObj),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type),
headers,
expectedHeader,
authHeader;
handler.sign(authInterface, request, _.noop);
headers = request.headers.all();
expectedHeader = 'Authorization: Digest username="postman", realm="Users", ' +
'nonce="bcgEc5RPU1ANglyT2I0ShU0oxqPB5jXp", uri="/digest-auth", ' +
'algorithm="MD5-sess", nc=00000001, cnonce="0a4f113b", ' +
'response="3bf3901b3461fe15de194fa866154c21", opaque="5ccc069c403ebaf9f0171e9517f40e"';
authHeader;
expect(headers).to.have.lengthOf(1);
authHeader = headers[0];
expect(authHeader.toString()).to.eql(expectedHeader);
expect(authHeader.system).to.be.true;
});
it('should add the Auth header for (algorithm="MD5-sess", qop="auth")', function () {
var clonedReqObj = _.merge({}, rawRequests.digest, {
auth: {
digest: {
qop: 'auth',
algorithm: 'MD5-sess'
}
}
}),
request = new Request(clonedReqObj),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type),
headers,
expectedHeader,
authHeader;
handler.sign(authInterface, request, _.noop);
headers = request.headers.all();
expectedHeader = 'Authorization: Digest username="postman", realm="Users", ' +
'nonce="bcgEc5RPU1ANglyT2I0ShU0oxqPB5jXp", uri="/digest-auth", ' +
'algorithm="MD5-sess", qop=auth, nc=00000001, cnonce="0a4f113b", ' +
'response="52aa69a8b63d81b51e2d02ecebaa705e", opaque="5ccc069c403ebaf9f0171e9517f40e"';
authHeader;
expect(headers).to.have.lengthOf(1);
authHeader = headers[0];
expect(authHeader.toString()).to.eql(expectedHeader);
expect(authHeader.system).to.be.true;
});
it('should add the Auth header for (algorithm="MD5-sess", qop="auth-int")', function () {
var clonedReqObj = _.merge({}, rawRequests.digest, {
auth: {
digest: {
qop: 'auth-int',
algorithm: 'MD5-sess'
}
}
}),
request = new Request(clonedReqObj),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type),
headers,
expectedHeader,
authHeader;
handler.sign(authInterface, request, _.noop);
headers = request.headers.all();
expectedHeader = 'Authorization: Digest username="postman", realm="Users", ' +
'nonce="bcgEc5RPU1ANglyT2I0ShU0oxqPB5jXp", uri="/digest-auth", ' +
'algorithm="MD5-sess", qop=auth-int, nc=00000001, cnonce="0a4f113b", ' +
'response="eb2ec4193a936809d035976f5f20cc65", opaque="5ccc069c403ebaf9f0171e9517f40e"';
authHeader;
expect(headers).to.have.lengthOf(1);
authHeader = headers[0];
expect(authHeader.toString()).to.eql(expectedHeader);
expect(authHeader.system).to.be.true;
});
it('should add the Auth header with query params in case of request with the same', function () {
var request = new Request(rawRequests.digestWithQueryParams),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type),
authHeader,
expectedHeader;
handler.sign(authInterface, request, _.noop);
authHeader = request.headers.one('Authorization');
expectedHeader = 'Authorization: Digest username="postman", realm="Users", ' +
'nonce="bcgEc5RPU1ANglyT2I0ShU0oxqPB5jXp", uri="/digest-auth?key=value", ' +
'algorithm="MD5", response="24dfb8851ee27e4b00252a13b1fd8ec3", opaque="5ccc069c403ebaf9f0171e9517f40e"';
expect(authHeader.toString()).to.eql(expectedHeader);
});
it('should bail out for invalid requests', function () {
var request = new Request(_.omit(rawRequests.digest, 'auth.digest.username')),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.all()).to.be.an('array').that.is.empty;
// Since Nonce and Timestamp have to be generated at runtime, cannot assert anything beyond this.
expect(request.toJSON()).to.eql({
url: {
host: ['postman-echo', 'com'],
path: ['digest-auth'],
protocol: 'https',
query: [],
variable: []
},
method: 'GET',
auth: {
type: 'digest',
digest: [{
'key': 'realm',
'type': 'any',
'value': 'Users'
},
{
'key': 'password',
'type': 'any',
'value': 'password'
},
{
'key': 'nonce',
'type': 'any',
'value': 'bcgEc5RPU1ANglyT2I0ShU0oxqPB5jXp'
},
{
'key': 'nonceCount',
'type': 'any',
'value': '00000001'
},
{
'key': 'algorithm',
'type': 'any',
'value': 'MD5'
},
{
'key': 'qop',
'type': 'any',
'value': ''
},
{
'key': 'clientNonce',
'type': 'any',
'value': '0a4f113b'
},
{
'key': 'opaque',
'type': 'any',
'value': '5ccc069c403ebaf9f0171e9517f40e'
}]
}
});
});
});
describe('oauth1', function () {
it('should add the Auth header', function () {
var request = new Request(rawRequests.oauth1),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type),
headers,
authHeader,
authHeaderValueKeys;
handler.sign(authInterface, request, _.noop);
headers = request.headers.all();
authHeader;
authHeaderValueKeys;
expect(headers).to.have.lengthOf(1);
authHeader = headers[0];
// Since Nonce and Timestamp have to be generated at runtime, cannot assert anything beyond this.
expect(authHeader.key).to.equal('Authorization');
authHeaderValueKeys = authHeader.value.split(',').map((val) => {
return val.split('=')[0];
});
expect(authHeaderValueKeys).to.eql([
'OAuth realm',
'oauth_consumer_key',
'oauth_signature_method',
'oauth_timestamp',
'oauth_nonce',
'oauth_version',
'oauth_signature'
]);
expect(authHeader.system).to.be.true;
});
it('should bail out if the auth params are invalid', function () {
var request = new Request(_.omit(rawRequests.oauth1, ['header', 'auth.oauth1.consumerKey'])),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.all()).to.be.an('array').that.is.empty;
});
it('should apply sensible defaults where applicable', function () {
var rawReq = _(rawRequests.oauth1).omit(['auth.oauth1.nonce', 'auth.oauth1.timestamp']).merge({
url: {
host: ['postman-echo', 'com'],
path: ['auth', 'oauth1'],
protocol: 'https',
query: [],
variable: []
},
auth: {
oauth1: {
addEmptyParamsToSign: true,
addParamsToHeader: false
}
},
body: {
mode: 'urlencoded',
urlencoded: [{
key: 'oauth_token',
value: 'secret'
}, {
key: 'foo',
value: 'bar'
}]
}
}).value(),
request = new Request(rawReq),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.all()).to.be.an('array').that.is.empty;
expect(request.auth.parameters().toObject()).to
.eql({
consumerKey: 'RKCGzna7bv9YD57c',
consumerSecret: 'D+EdQ-gs$-%@2Nu7',
token: '',
tokenSecret: '',
signatureMethod: 'HMAC-SHA1',
version: '1.0',
realm: 'oauthrealm',
addParamsToHeader: false,
autoAddParam: true,
addEmptyParamsToSign: true
});
});
it('should correctly handle the GET request method', function () {
var rawReq = _(rawRequests.oauth1).omit(['auth.oauth1.nonce', 'auth.oauth1.timestamp']).merge({
method: 'GET',
url: 'https://postman-echo.com/auth/oauth1',
auth: {
oauth1: {
addEmptyParamsToSign: true,
addParamsToHeader: false
}
},
body: {
mode: 'urlencoded',
urlencoded: [{
key: 'oauth_token',
value: 'secret'
}, {
key: 'foo',
value: 'bar'
}]
}
}).value(),
request = new Request(rawReq),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.all()).to.be.an('array').that.is.empty;
expect(request.url.query.reference).to.deep.include.keys([
'oauth_consumer_key', 'oauth_token', 'oauth_signature_method', 'oauth_timestamp', 'oauth_nonce',
'oauth_version', 'oauth_signature'
]);
// All the query paramters added by runtime must have `system: true` property
_.forEach(request.url.query.members, function (param) {
expect(param.system).to.be.true;
});
expect(request.auth.parameters().toObject()).to
.eql({
consumerKey: 'RKCGzna7bv9YD57c',
consumerSecret: 'D+EdQ-gs$-%@2Nu7',
token: '',
tokenSecret: '',
signatureMethod: 'HMAC-SHA1',
version: '1.0',
realm: 'oauthrealm',
addParamsToHeader: false,
autoAddParam: true,
addEmptyParamsToSign: true
});
});
});
describe('oauth2', function () {
var requestObj = {
auth: {
type: 'oauth2',
oauth2: {
accessToken: '123456789abcdefghi',
addTokenTo: 'header',
tokenType: 'bearer'
}
},
url: 'https://api.github.com/user/orgs',
method: 'GET'
};
it('should sign the request by adding the token to the header', function () {
var request = new Request(requestObj),
authInterface = createAuthInterface(request.auth),
handler = AuthLoader.getHandler(request.auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.all()).to.be.an('array').that.has.lengthOf(1);
expect(request.headers.toJSON()[0]).to.eql({
key: 'Authorization',
value: 'Bearer ' + requestObj.auth.oauth2.accessToken,
system: true
});
});
it('should sign the request by adding the token to the query params', function () {
var clonedRequestObj,
request,
auth,
authInterface,
handler;
clonedRequestObj = _.cloneDeep(requestObj);
clonedRequestObj.auth.oauth2.addTokenTo = 'queryParams';
request = new Request(clonedRequestObj);
auth = request.auth;
authInterface = createAuthInterface(auth);
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.all()).to.be.an('array').that.is.empty;
expect(request.url.query.all()).to.be.an('array').that.has.lengthOf(1);
expect(request.url.query.toJSON()[0]).to.eql({
key: 'access_token',
value: requestObj.auth.oauth2.accessToken,
system: true
});
});
it('should return when token is not present', function () {
var clonedRequestObj,
request,
auth,
authInterface,
handler;
clonedRequestObj = _.cloneDeep(requestObj);
delete clonedRequestObj.auth.oauth2.accessToken;
request = new Request(clonedRequestObj);
auth = request.auth;
authInterface = createAuthInterface(auth);
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.all()).to.be.an('array').that.is.empty;
expect(request.url.query.all()).to.be.an('array').that.is.empty;
});
it('should default the token type to "Bearer"', function () {
var clonedRequestObj,
request,
auth,
authInterface,
handler;
clonedRequestObj = _.cloneDeep(requestObj);
clonedRequestObj.auth.oauth2.tokenType = '';
request = new Request(clonedRequestObj);
auth = request.auth;
authInterface = createAuthInterface(auth);
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.all()).to.be.an('array').that.has.lengthOf(1);
expect(request.headers.toJSON()[0]).to.eql({
key: 'Authorization',
value: 'Bearer ' + requestObj.auth.oauth2.accessToken,
system: true
});
});
it('should do a case insensitive check for token type', function () {
var clonedRequestObj,
request,
auth,
authInterface,
handler;
clonedRequestObj = _.cloneDeep(requestObj);
clonedRequestObj.auth.oauth2.tokenType = 'Bearer';
request = new Request(clonedRequestObj);
auth = request.auth;
authInterface = createAuthInterface(auth);
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.all()).to.be.an('array').that.has.lengthOf(1);
expect(request.headers.toJSON()[0]).to.eql({
key: 'Authorization',
value: 'Bearer ' + requestObj.auth.oauth2.accessToken,
system: true
});
clonedRequestObj.auth.oauth2.tokenType = 'bearer';
request = new Request(clonedRequestObj);
auth = request.auth;
authInterface = createAuthInterface(auth);
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.all()).to.be.an('array').that.has.lengthOf(1);
expect(request.headers.toJSON()[0]).to.eql({
key: 'Authorization',
value: 'Bearer ' + requestObj.auth.oauth2.accessToken,
system: true
});
});
it('should return when token type is not known', function () {
var clonedRequestObj,
request,
auth,
authInterface,
handler;
clonedRequestObj = _.cloneDeep(requestObj);
clonedRequestObj.auth.oauth2.tokenType = 'unknown type';
request = new Request(clonedRequestObj);
auth = request.auth;
authInterface = createAuthInterface(auth);
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.all()).to.be.an('array').that.is.empty;
expect(request.url.query.all()).to.be.an('array').that.is.empty;
});
it('should remove user defined Authorization header and query param for addTokenTo: header', function () {
var requestWithAuthHeader,
request,
auth,
authInterface,
handler;
requestWithAuthHeader = _.defaults({
header: [{key: 'Authorization', value: 'This should be removed'}],
url: 'https://postman-echo.com/get?access_token=not-anymore'
}, requestObj);
request = new Request(requestWithAuthHeader);
auth = request.auth;
authInterface = createAuthInterface(auth);
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.toJSON()).to.eql([{
key: 'Authorization',
value: 'Bearer ' + requestObj.auth.oauth2.accessToken,
system: true
}]);
expect(request.url.toJSON()).to.eql({
protocol: 'https',
path: ['get'],
host: ['postman-echo', 'com'],
query: [],
variable: []
});
});
it('should remove user defined Authorization header and query param for addTokenTo: queryParams', function () {
var requestWithAuthHeader,
request,
auth,
authInterface,
handler;
requestWithAuthHeader = _.defaults({
auth: {
type: 'oauth2',
oauth2: {
accessToken: '123456789abcdefghi',
addTokenTo: 'queryParams',
tokenType: 'bearer'
}
},
header: [{key: 'Authorization', value: 'This should be removed'}],
url: 'https://postman-echo.com/get?access_token=not-anymore'
}, requestObj);
request = new Request(requestWithAuthHeader);
auth = request.auth;
authInterface = createAuthInterface(auth);
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.toJSON()).to.eql([]);
expect(request.url.toJSON()).to.eql({
protocol: 'https',
path: ['get'],
host: ['postman-echo', 'com'],
query: [{key: 'access_token', value: '123456789abcdefghi', system: true}],
variable: []
});
});
it('should not remove user config for bail out case', function () {
var requestWithAuthHeader,
request,
auth,
authInterface,
handler;
// no access token
requestWithAuthHeader = _.defaults({
auth: {
type: 'oauth2',
oauth2: {
addTokenTo: 'queryParams',
tokenType: 'bearer'
}
},
header: [{key: 'Authorization', value: 'Old-Header'}],
url: 'https://postman-echo.com/get?access_token=old-token'
}, requestObj);
request = new Request(requestWithAuthHeader);
auth = request.auth;
authInterface = createAuthInterface(auth);
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.toJSON()).to.eql([{key: 'Authorization', value: 'Old-Header'}]);
expect(request.url.toJSON()).to.eql({
protocol: 'https',
path: ['get'],
host: ['postman-echo', 'com'],
query: [{key: 'access_token', value: 'old-token'}],
variable: []
});
// invalid token type
requestWithAuthHeader = _.defaults({
auth: {
type: 'oauth2',
oauth2: {
accessToken: '123456789abcdefghi',
addTokenTo: 'queryParams',
tokenType: 'micdrop'
}
},
header: [{key: 'Authorization', value: 'Old-Header'}],
url: 'https://postman-echo.com/get?access_token=old-token'
}, requestObj);
request = new Request(requestWithAuthHeader);
auth = request.auth;
authInterface = createAuthInterface(auth);
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.headers.toJSON()).to.eql([{key: 'Authorization', value: 'Old-Header'}]);
expect(request.url.toJSON()).to.eql({
protocol: 'https',
path: ['get'],
host: ['postman-echo', 'com'],
query: [{key: 'access_token', value: 'old-token'}],
variable: []
});
});
});
// querystring.unescape is not available in browserify's querystring module, so this goes to hell
// TODO: fix this
(typeof window === 'undefined' ? describe : describe.skip)('awsv4', function () {
it('should add the required headers', function () {
var awsv4Data = rawRequests.awsv4,
request = new Request(rawRequests.awsv4),
auth = request.auth,
authInterface = createAuthInterface(auth),
authParams = auth.parameters().toObject(),
handler = AuthLoader.getHandler(auth.type),
parsedUrl,
headers,
expectedSignedReq;
handler.sign(authInterface, request, _.noop);
parsedUrl = new Url(awsv4Data.url);
headers = request.getHeaders({
ignoreCase: true
});
expectedSignedReq = aws4.sign({
headers: {
'X-Amz-Date': headers['x-amz-date'],
'content-type': 'application/json'
},
host: parsedUrl.getRemote(),
path: parsedUrl.getPathWithQuery(),
service: authParams.serviceName,
region: authParams.region,
method: awsv4Data.method
}, {
accessKeyId: authParams.accessKey,
secretAccessKey: authParams.secretKey,
sessionToken: authParams.sessionToken
});
// Ensure that the required headers have been added.
// todo stricter tests?
expect(headers).to.deep.include({
authorization: expectedSignedReq.headers.Authorization,
'content-type': request.getHeaders({
ignoreCase: true
})['content-type']
});
expect(headers).to.include.keys(['x-amz-date', 'x-amz-security-token']);
});
it('should use sensible defaults where applicable', function () {
var headers,
rawReq = _.defaults(rawRequests.awsv4, {
body: {
mode: 'raw',
raw: '\'foo\': \'bar\''
}
}),
request = new Request(_.omit(rawReq, ['header.0', 'auth.awsv4.sessionToken', 'region'])),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
request.headers.add({
key: 'postman-token',
value: 'random-token'
});
headers = request.getHeaders({
ignoreCase: true
});
expect(headers).to.include.keys(['authorization', 'x-amz-date']);
expect(request.auth.parameters().toObject()).to.eql({
auto: true,
id: 'awsSigV4',
region: 'eu-west-1',
saveHelper: true,
service: '',
serviceName: 'execute-api',
accessKey: 'AKIAI53QRL',
secretKey: 'cr2RAfsY4IIVweutTBoBzR',
time: 1452673288848
});
});
it('should handle formdata bodies correctly', function () {
var rawReq = _.merge({}, rawRequests.awsv4, {
body: {
mode: 'formdata',
formdata: []
}
}),
request = new Request(_.omit(rawReq, 'header')),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type),
headers;
handler.sign(authInterface, request, _.noop);
headers = request.getHeaders({
ignoreCase: true
});
expect(headers).to.include.keys(['authorization', 'x-amz-date']);
expect(request.auth.parameters().toObject()).to.eql({
auto: true,
id: 'awsSigV4',
region: 'eu-west-1',
saveHelper: true,
service: '',
serviceName: 'execute-api',
accessKey: 'AKIAI53QRL',
sessionToken: '33Dhtnwf0RVHCFttmMPYt3dxx9zi8I07CBwTXaqupHQ=',
secretKey: 'cr2RAfsY4IIVweutTBoBzR',
time: 1452673288848
});
});
it('should handle graphql bodies correctly', function (done) {
var rawReq = _.merge({}, rawRequests.awsv4, {
body: {
mode: 'graphql',
graphql: {
query: 'query Test { hello }',
operationName: 'Test',
variables: '{"foo":"bar"}'
}
}
}),
request = new Request(_.omit(rawReq, 'header')),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type),
headers;
handler.sign(authInterface, request, function () {
headers = request.getHeaders({
ignoreCase: true
});
expect(headers).to.include.keys(['authorization', 'x-amz-date']);
expect(request.auth.parameters().toObject()).to.eql({
auto: true,
id: 'awsSigV4',
region: 'eu-west-1',
saveHelper: true,
service: '',
serviceName: 'execute-api',
accessKey: 'AKIAI53QRL',
sessionToken: '33Dhtnwf0RVHCFttmMPYt3dxx9zi8I07CBwTXaqupHQ=',
secretKey: 'cr2RAfsY4IIVweutTBoBzR',
time: 1452673288848
});
done();
});
});
});
describe('hawk', function () {
it('should add the Auth header', function () {
var request = new Request(rawRequests.hawk),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type),
headers;
handler.sign(authInterface, request, _.noop);
headers = request.getHeaders({
ignoreCase: true
});
// Ensure that the required headers have been added.
expect(headers).to.have.property('authorization');
});
it('should add the timestamp and nonce to the Authorized request', function () {
var request = new Request(rawRequests.hawk),
clonedRequest = new Request(request.toJSON()), // cloning it so we can assert comparing the two
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type),
headerBefore,
headerAfter,
nonceMatch,
tsMatch;
handler.sign(authInterface, clonedRequest, _.noop);
headerBefore = request.headers.all()[0].value;
headerAfter = clonedRequest.headers.all()[0].value;
nonceMatch = headerAfter.match(/nonce="([^"]*)"/);
tsMatch = headerAfter.match(/ts="([^"]*)"/);
// Original request should not have the timestamp and nonce
expect(headerBefore).to.be.eql('');
expect(request.auth).to.be.ok;
expect(_.get(nonceMatch, 1)).to.be.a('string');
expect(_.parseInt(_.get(tsMatch, 1))).to.be.a('number');
});
it('should add the hash to the Authorized request if request contains body and includePayloadHash=true',
function () {
var request = new Request(rawRequests.hawkWithBody),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type),
headers;
handler.sign(authInterface, request, _.noop);
headers = request.getHeaders({
ignoreCase: true
});
// Ensure that the required headers have been added.
expect(headers).to.have.property('authorization');
// Ensure that the body hash is included in Authorization header
expect(headers.authorization).to.include('hash');
});
it('should not add the hash to the Authorized request if request contains body but includePayloadHash=false',
function () {
var request = new Request(rawRequests.hawkWithBodyWithoutHash),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type),
headers;
handler.sign(authInterface, request, _.noop);
headers = request.getHeaders({
ignoreCase: true
});
// Ensure that the required headers have been added.
expect(headers).to.have.property('authorization');
// Ensure that the body hash is included in Authorization header
expect(headers.authorization).to.not.include('hash');
});
it('should bail out the original request if auth key is missing', function () {
var request = new Request(_.omit(rawRequests.hawk, 'auth.hawk.authKey')),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
// Original request should not have the timestamp and nonce
expect(_.get(rawRequests.hawk, 'auth.hawk.nonce')).to.not.be.ok;
expect(_.get(rawRequests.hawk, 'auth.hawk.timestamp')).to.not.be.ok;
expect(request.auth).to.be.ok;
expect(_.get(request, 'auth.hawk.nonce')).to.not.be.ok;
expect(_.get(request, 'auth.hawk.timestamp')).to.not.be.ok;
});
it('should handle formdata bodies correctly when includePayloadHash=true',
function (done) {
var rawReq = _.merge({}, rawRequests.hawkWithBody, {
body: {
mode: 'formdata',
formdata: []
}
}),
request = new Request(rawReq),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type),
headers;
handler.sign(authInterface, request, function () {
headers = request.getHeaders({
ignoreCase: true
});
// Ensure that the required headers have been added.
expect(headers).to.have.property('authorization');
// Ensure that the body hash is not included in Authorization header.
// Update this once we figure out a way to calculate hash for formdata body type.
expect(headers.authorization).to.not.include('hash');
done();
});
});
it('should handle graphql bodies correctly when includePayloadHash=true',
function (done) {
var rawReq = _.merge({}, rawRequests.hawkWithBody, {
body: {
mode: 'graphql',
graphql: {
query: 'query Test { hello }',
operationName: 'Test',
variables: '{"foo":"bar"}'
}
}
}),
request = new Request(rawReq),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type),
headers;
handler.sign(authInterface, request, function () {
headers = request.getHeaders({
ignoreCase: true
});
// Ensure that the required headers have been added.
expect(headers).to.have.property('authorization');
// Ensure that the body hash is included in Authorization header
expect(headers.authorization).to.include('hash');
done();
});
});
});
describe('ntlm', function () {
it('should be able to load all parameters from a request', function () {
var data = {
auth: {
type: 'ntlm',
ntlm: {
username: 'testuser',
password: 'testpass',
domain: 'testdomain',
workstation: 'sample.work'
}
},
url: 'httpbin.org/get'
},
request = new Request(data),
auth = request.auth,
authInterface = createAuthInterface(auth),
handler = AuthLoader.getHandler(auth.type);
handler.sign(authInterface, request, _.noop);
expect(request.auth.ntlm.toObject()).to.eql({
username: 'testuser',
password: 'testpass',
domain: 'testdomain',
workstation: 'sample.work'
});
});
});
});