Skip to content

Commit

Permalink
Added support for NTLM auth support in cURL codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
VShingala committed Jul 11, 2024
1 parent cec1e43 commit e9648ea
Show file tree
Hide file tree
Showing 3 changed files with 183 additions and 19 deletions.
31 changes: 21 additions & 10 deletions codegens/curl/lib/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
var sanitize = require('./util').sanitize,
sanitizeOptions = require('./util').sanitizeOptions,
getUrlStringfromUrlObject = require('./util').getUrlStringfromUrlObject,
addFormParam = require('./util').addFormParam,
form = require('./util').form,
shouldAddHttpMethod = require('./util').shouldAddHttpMethod,
_ = require('./lodash'),
self;
const {
sanitize,
sanitizeOptions,
getUrlStringfromUrlObject,
getNtlmAuthInfo,
addFormParam,
form,
shouldAddHttpMethod
} = require('./util'),
_ = require('./lodash');

var self;

self = module.exports = {
convert: function (request, options, callback) {
Expand All @@ -16,7 +20,7 @@ self = module.exports = {
options = sanitizeOptions(options, self.getOptions());

var indent, trim, headersData, body, redirect, timeout, multiLine,
format, snippet, silent, url, quoteType;
format, snippet, silent, url, quoteType, ntlmAuth;

redirect = options.followRedirect;
timeout = options.requestTimeoutInSeconds;
Expand All @@ -26,9 +30,16 @@ self = module.exports = {
silent = options.silent;
quoteType = options.quoteType === 'single' ? '\'' : '"';
url = getUrlStringfromUrlObject(request.url, quoteType);
ntlmAuth = getNtlmAuthInfo(request.auth, quoteType, format);

snippet = silent ? `curl ${form('-s', format)}` : 'curl';
snippet = 'curl';

if (ntlmAuth) {
snippet += ntlmAuth;
}
if (silent) {
snippet += ` ${form('-s', format)}`;
}
if (redirect) {
snippet += ` ${form('-L', format)}`;
}
Expand Down
51 changes: 43 additions & 8 deletions codegens/curl/lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,49 @@ var self = module.exports = {
},

/**
*
* @param {*} urlObject The request sdk request.url object
* @param {boolean} quoteType The user given quoteType
* @returns {String} The final string after parsing all the parameters of the url including
* protocol, auth, host, port, path, query, hash
* This will be used because the url.toString() method returned the URL with non encoded query string
* and hence a manual call is made to getQueryString() method with encode option set as true.
*/
* Generates args required for NTLM authentication to happen
*
* @param {*} auth - The request sdk request.auth object
* @param {string} quoteType - user provided option to decide whether to use single or double quotes
* @param {string} format - user provided option to decide whether to use long format or not
* @returns {string} - The string to be added if NTLM auth is required
*/
getNtlmAuthInfo: function (auth, quoteType, format) {
const ntlmAuth = auth && auth.ntlm;

if (!auth || auth.type !== 'ntlm' || !ntlmAuth || !ntlmAuth.count || !ntlmAuth.count()) {
return '';
}

const username = ntlmAuth.has('username') && ntlmAuth.get('username'),
password = ntlmAuth.has('password') && ntlmAuth.get('password'),
domain = ntlmAuth.has('domain') && ntlmAuth.get('domain');

if (!username && !password) {
return '';
}

var userArg = format ? '--user ' : '-u ',
ntlmString = ' --ntlm ' + userArg + quoteType;

if (domain) {
ntlmString += self.sanitize(domain, true, quoteType) + '\\';
}
ntlmString += self.sanitize(username, true, quoteType) + ':' + self.sanitize(password, true, quoteType);
ntlmString += quoteType;

return ntlmString;
},

/**
*
* @param {*} urlObject The request sdk request.url object
* @param {boolean} quoteType The user given quoteType
* @returns {String} The final string after parsing all the parameters of the url including
* protocol, auth, host, port, path, query, hash
* This will be used because the url.toString() method returned the URL with non encoded query string
* and hence a manual call is made to getQueryString() method with encode option set as true.
*/
getUrlStringfromUrlObject: function (urlObject, quoteType) {
var url = '';
if (!urlObject) {
Expand Down
120 changes: 119 additions & 1 deletion codegens/curl/test/unit/convert.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var expect = require('chai').expect,
var _ = require('lodash'),
expect = require('chai').expect,
{ Request } = require('postman-collection/lib/collection/request'),
{ Url } = require('postman-collection/lib/collection/url'),
convert = require('../../index').convert,
Expand Down Expand Up @@ -1026,5 +1027,122 @@ describe('curl convert function', function () {
});
});
});

describe('should correctly handle NTLM auth', function () {
const sampleRequest = {
'method': 'POST',
'header': [],
'auth': {
'type': 'ntlm',
'ntlm': []
},
'url': {
'raw': 'https://postman-echo.com/post',
'protocol': 'https',
'host': [
'postman-echo',
'com'
],
'path': [
'post'
]
}
};

it('when no username or password is present', function () {
const request = new Request(sampleRequest);

convert(request, {}, function (error, snippet) {
if (error) {
expect.fail(null, null, error);
}
expect(snippet).to.be.a('string');
expect(snippet).to.not.include('--ntlm');
});
});

it('when empty username and password is present', function () {
const request = new Request(Object.assign({ auth: {
'type': 'ntlm',
'ntlm': [
{key: 'username', value: ''},
{key: 'password', value: ''}
]
}}, sampleRequest));

convert(request, {}, function (error, snippet) {
if (error) {
expect.fail(null, null, error);
}
expect(snippet).to.be.a('string');
expect(snippet).to.not.include('--ntlm');
});
});

it('when correct username and password is present with single quotes as option', function () {
const request = new Request(_.set(sampleRequest, 'auth.ntlm', [
{key: 'username', value: 'joh\'n'},
{key: 'password', value: 'tennesse"e'}
]));

convert(request, { quoteType: 'single' }, function (error, snippet) {
if (error) {
expect.fail(null, null, error);
}
expect(snippet).to.be.a('string');
expect(snippet).to.equal('curl --ntlm --user \'joh\'\\\'\'n:tennesse"e\' --location' +
' --request POST \'https://postman-echo.com/post\'');
});
});

it('when correct username and password is present with double as option', function () {
const request = new Request(_.set(sampleRequest, 'auth.ntlm', [
{key: 'username', value: 'joh\'n'},
{key: 'password', value: 'tennesse"e'}
]));

convert(request, { quoteType: 'double' }, function (error, snippet) {
if (error) {
expect.fail(null, null, error);
}
expect(snippet).to.be.a('string');
expect(snippet).to.equal('curl --ntlm --user "joh\'n:tennesse\\"e" --location' +
' --request POST "https://postman-echo.com/post"');
});
});

it('when correct username and password is present with long format option disabled', function () {
const request = new Request(_.set(sampleRequest, 'auth.ntlm', [
{key: 'username', value: 'joh\'n'},
{key: 'password', value: 'tennesse"e'}
]));

convert(request, { longFormat: false }, function (error, snippet) {
if (error) {
expect.fail(null, null, error);
}
expect(snippet).to.be.a('string');
expect(snippet).to.equal('curl --ntlm -u \'joh\'\\\'\'n:tennesse"e\' -L' +
' -X POST \'https://postman-echo.com/post\'');
});
});

it('when username and password is present with domain as well', function () {
const request = new Request(_.set(sampleRequest, 'auth.ntlm', [
{key: 'username', value: 'joh\'n'},
{key: 'password', value: 'tennesse"e'},
{key: 'domain', value: 'radio'}
]));

convert(request, {}, function (error, snippet) {
if (error) {
expect.fail(null, null, error);
}
expect(snippet).to.be.a('string');
expect(snippet).to.equal('curl --ntlm --user \'radio\\joh\'\\\'\'n:tennesse"e\' --location' +
' --request POST \'https://postman-echo.com/post\'');
});
});
});
});
});

0 comments on commit e9648ea

Please sign in to comment.