diff --git a/lib/Frame.js b/lib/Frame.js deleted file mode 100644 index f575622..0000000 --- a/lib/Frame.js +++ /dev/null @@ -1,40 +0,0 @@ -var {Client} = require('./main.js') - -function Frame (ikey, skey, host) { - Client.call(this, ikey, skey, host, 4) -} - -Frame.prototype = Object.create(Client.prototype) -Frame.prototype.constructor = Frame - -Frame.prototype.init = function (username, app_blob, expire, client_version, enroll_only = false, callback) { - var init_txid_path = '/frame/api/v3/init' - var method = 'POST' - var params = { - 'user': username, - 'app_blob': app_blob, - 'expire': expire, - 'client_version': client_version - } - - if (enroll_only) { - params.enroll_only = enroll_only - } - this.jsonApiCall(method, init_txid_path, params, (txid) => { - callback(txid) - }) -} - -Frame.prototype.auth_response = function (response_txid, callback) { - var method = 'POST' - var endpoint = '/frame/api/v3/auth_response' - var params = { - 'response_txid': response_txid - } - this.jsonApiCall(method, endpoint, params, (txid) => { - callback(txid) - }) -} -module.exports = { - 'Frame': Frame -} diff --git a/lib/duo_sig.js b/lib/duo_sig.js index 727fb2d..a6433a3 100644 --- a/lib/duo_sig.js +++ b/lib/duo_sig.js @@ -55,36 +55,20 @@ function canonParams (params) { } // Return a request's canonical representation as a string to sign. -function canonicalize (method, host, path, params, date, sig_version) { - let canon = '' - if (sig_version === 2) { - canon = [ - date, - method.toUpperCase(), - host.toLowerCase(), - path, - canonParams(params) - ].join('\n') - } else if (sig_version === 4) { - let hashed_body = crypto.createHash('sha512') - .update(JSON.stringify(params)) - .digest('hex') - canon = [ - date, - method.toUpperCase(), - host.toLowerCase(), - path, - '', - hashed_body - ].join('\n') - } - return canon +function canonicalize (method, host, path, params, date) { + return [ + date, + method.toUpperCase(), + host.toLowerCase(), + path, + canonParams(params) + ].join('\n') } // Return the Authorization header for an HMAC signed request. -function sign (ikey, skey, method, host, path, params, date, sig_version, digestmod) { - var canon = canonicalize(method, host, path, params, date, sig_version) - var sig = crypto.createHmac(digestmod, skey) +function sign (ikey, skey, method, host, path, params, date) { + var canon = canonicalize(method, host, path, params, date) + var sig = crypto.createHmac('sha1', skey) .update(canon) .digest('hex') diff --git a/lib/main.js b/lib/main.js index 637aa8d..ca2a4c9 100644 --- a/lib/main.js +++ b/lib/main.js @@ -7,13 +7,10 @@ const _MAX_BACKOFF_WAIT_SECS = 32 const _BACKOFF_FACTOR = 2 const _RATE_LIMITED_RESP_CODE = 429 -function Client (ikey, skey, host, sig_version = 2) { +function Client (ikey, skey, host) { this.ikey = ikey this.skey = skey this.host = host - this.sig_version = sig_version - - this.digestmod = (sig_version === 4) ? 'sha512' : 'sha1' } Client.prototype.apiCall = function (method, path, params, callback) { @@ -23,19 +20,13 @@ Client.prototype.apiCall = function (method, path, params, callback) { 'Host': this.host } headers['Authorization'] = duo_sig.sign( - this.ikey, this.skey, method, this.host, path, params, date, this.sig_version, this.digestmod) + this.ikey, this.skey, method, this.host, path, params, date) var qs = querystring.stringify(params) var body = '' if (method === 'POST' || method === 'PUT') { - if (this.sig_version === 4) { - body = JSON.stringify(params) - headers['Content-type'] = 'application/json' - } else { - body = qs - headers['Content-type'] = 'application/x-www-form-urlencoded' - } - headers['content-length'] = Buffer.byteLength(body) + body = qs + headers['Content-type'] = 'application/x-www-form-urlencoded' } else if (qs) { path += '?' + qs } diff --git a/package.json b/package.json index 8f145f1..96042e6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@duosecurity/duo_api", - "version": "1.2.0", + "version": "1.2.1", "license": "BSD-3-Clause", "description": "Duo API SDK for Node.js applications", "homepage": "https://www.duosecurity.com/api", diff --git a/tests/duo_sig.js b/tests/duo_sig.js index 69bc1aa..f741ec5 100644 --- a/tests/duo_sig.js +++ b/tests/duo_sig.js @@ -1,18 +1,7 @@ -/* global describe it beforeEach */ -var crypto = require('crypto') +/* global describe it */ var assert = require('assert') var duo_api = require('../lib/duo_sig.js') -var {Frame} = require('../lib/Frame') -var nock = require('nock') -let JSON_BODY = { - 'alpha': ['a', 'b', 'c', 'd'], - 'data': 'abc123', - 'info': { - 'test': 1, - 'another': 2 - } -} module.exports = [] describe('Query Parameter Checks', function () { @@ -112,109 +101,3 @@ describe('Query Parameter Checks', function () { done() }) }) - -describe('Signature Checks', function () { - it('HMAC-SHA1', function (done) { - var actual = duo_api.sign( - 'test_ikey', - 'gtdfxv9YgVBYcF6dl2Eq17KUQJN2PLM2ODVTkvoT', - 'PoSt', - 'foO.BAr52.cOm', - '/Foo/BaR2/qux', - { - '\u469a\u287b\u35d0\u8ef3\u6727\u502a\u0810\ud091\xc8\uc170': ['\u0f45\u1a76\u341a\u654c\uc23f\u9b09\uabe2\u8343\u1b27\u60d0'], - '\u7449\u7e4b\uccfb\u59ff\ufe5f\u83b7\uadcc\u900c\ucfd1\u7813': ['\u8db7\u5022\u92d3\u42ef\u207d\u8730\uacfe\u5617\u0946\u4e30'], - '\u7470\u9314\u901c\u9eae\u40d8\u4201\u82d8\u8c70\u1d31\ua042': ['\u17d9\u0ba8\u9358\uaadf\ua42a\u48be\ufb96\u6fe9\ub7ff\u32f3'], - '\uc2c5\u2c1d\u2620\u3617\u96b3F\u8605\u20e8\uac21\u5934': ['\ufba9\u41aa\ubd83\u840b\u2615\u3e6e\u652d\ua8b5\ud56bU'] - }, - 'Fri, 07 Dec 2012 17:18:00 -0000', - 2, - 'sha1' - ) - assert.equal(actual, 'Basic dGVzdF9pa2V5OmYwMTgxMWNiYmY5NTYxNjIzYWI0NWI4OTMwOTYyNjdmZDQ2YTUxNzg=') - done() - }) - - it('HMAC-SHA512', function (done) { - let params = JSON_BODY - var actual = duo_api.sign( - 'test_ikey', - 'gtdfxv9YgVBYcF6dl2Eq17KUQJN2PLM2ODVTkvoT', - 'PoSt', - 'foO.BAr52.cOm', - '/Foo/BaR2/qux', - params, - 'Fri, 07 Dec 2012 17:18:00 -0000', - 4, - 'sha512' - ) - assert.equal(actual, 'Basic dGVzdF9pa2V5OmJjZTVkMGRkNjdlNjRjYmExZTFlOTQyMDhkOGQ2ZTRjNzYwNGRlYzhhN2FjYTBjYmU5Y2JhMDc3OTY5NWNlNGI4MDQzYmNjMTFkMmU3Njc2ZmJjMTMzOGY2ZDJmMjk0YTc3ZTc3MzYxNjViNDZjYjAyMGUyZmI3YTFmMjlkYzQy') - done() - }) -}) - -describe('Canonicalization Checks', function () { - it('test-v2', function (done) { - var actual = duo_api._canonicalize( - 'POST', - 'foO.BAr52.cOm', - '/Foo/BaR2/qux', - { - '\u469a\u287b\u35d0\u8ef3\u6727\u502a\u0810\ud091\xc8\uc170': ['\u0f45\u1a76\u341a\u654c\uc23f\u9b09\uabe2\u8343\u1b27\u60d0'], - '\u7449\u7e4b\uccfb\u59ff\ufe5f\u83b7\uadcc\u900c\ucfd1\u7813': ['\u8db7\u5022\u92d3\u42ef\u207d\u8730\uacfe\u5617\u0946\u4e30'], - '\u7470\u9314\u901c\u9eae\u40d8\u4201\u82d8\u8c70\u1d31\ua042': ['\u17d9\u0ba8\u9358\uaadf\ua42a\u48be\ufb96\u6fe9\ub7ff\u32f3'], - '\uc2c5\u2c1d\u2620\u3617\u96b3F\u8605\u20e8\uac21\u5934': ['\ufba9\u41aa\ubd83\u840b\u2615\u3e6e\u652d\ua8b5\ud56bU'] - }, - 'Fri, 07 Dec 2012 17:18:00 -0000', - 2 - ) - assert.equal(actual, 'Fri, 07 Dec 2012 17:18:00 -0000\nPOST\nfoo.bar52.com\n/Foo/BaR2/qux\n%E4%9A%9A%E2%A1%BB%E3%97%90%E8%BB%B3%E6%9C%A7%E5%80%AA%E0%A0%90%ED%82%91%C3%88%EC%85%B0=%E0%BD%85%E1%A9%B6%E3%90%9A%E6%95%8C%EC%88%BF%E9%AC%89%EA%AF%A2%E8%8D%83%E1%AC%A7%E6%83%90&%E7%91%89%E7%B9%8B%EC%B3%BB%E5%A7%BF%EF%B9%9F%E8%8E%B7%EA%B7%8C%E9%80%8C%EC%BF%91%E7%A0%93=%E8%B6%B7%E5%80%A2%E9%8B%93%E4%8B%AF%E2%81%BD%E8%9C%B0%EA%B3%BE%E5%98%97%E0%A5%86%E4%B8%B0&%E7%91%B0%E9%8C%94%E9%80%9C%E9%BA%AE%E4%83%98%E4%88%81%E8%8B%98%E8%B1%B0%E1%B4%B1%EA%81%82=%E1%9F%99%E0%AE%A8%E9%8D%98%EA%AB%9F%EA%90%AA%E4%A2%BE%EF%AE%96%E6%BF%A9%EB%9F%BF%E3%8B%B3&%EC%8B%85%E2%B0%9D%E2%98%A0%E3%98%97%E9%9A%B3F%E8%98%85%E2%83%A8%EA%B0%A1%E5%A4%B4=%EF%AE%A9%E4%86%AA%EB%B6%83%E8%90%8B%E2%98%95%E3%B9%AE%E6%94%AD%EA%A2%B5%ED%95%ABU') - done() - }) - - it('test-v4', function (done) { - let params = JSON_BODY - let hashed_body = crypto.createHash('sha512') - .update(JSON.stringify(JSON_BODY)) - .digest('hex') - var actual = duo_api._canonicalize( - 'POST', - 'foO.BAr52.cOm', - '/Foo/BaR2/qux', - params, - 'Tue, 04 Jul 2017 14:12:00', - 4 - ) - - assert.equal(actual, `Tue, 04 Jul 2017 14:12:00\nPOST\nfoo.bar52.com\n/Foo/BaR2/qux\n\n${hashed_body}`) - done() - }) -}) - -var IKEY = 'DIXXXXXXXXXXXXXXXXXX' -var SKEY = 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -var API_HOSTNAME = 'api_hostname' -var APP_BLOB = 'blob' -var USER = 'testuser' -let frame = new Frame(IKEY, SKEY, API_HOSTNAME) - -describe('Verifying initialize_auth', function () { - beforeEach(function () { - var date = new Date().toUTCString() - nock('https://' + API_HOSTNAME, { - reqheaders: { - 'Content-type': 'application/json', - 'Date': date, - 'Host': API_HOSTNAME - } - }).post('/frame/api/v3/init', {'user': USER, 'app_blob': APP_BLOB, 'expire': 100000, 'client_version': '2.0'}).reply(200, {'response': {txid: 'txid'}, 'stat': 'OK'}) - }) - - it('verify response on valid initialize_auth', function (done) { - frame.init(USER, APP_BLOB, 100000, '2.0', false, function (resp) { - assert.equal(resp.response.txid, 'txid') - assert.equal(resp.stat, 'OK') - done() - }) - }) -})