From aec15c28fa5cf8494e2db064fdedc881280cd9ca Mon Sep 17 00:00:00 2001 From: Anton Nikitiuk Date: Thu, 16 Jul 2026 16:32:36 +0300 Subject: [PATCH 1/2] Add ca bundle version --- lib/main.js | 2 +- tests/main.js | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/main.js b/lib/main.js index d899f0b..76548f6 100644 --- a/lib/main.js +++ b/lib/main.js @@ -20,7 +20,7 @@ Client.prototype.apiCall = function (method, path, params, callback) { var headers = { 'Date': date, 'Host': this.host, - 'User-Agent': `duo_api_nodejs/${_PACKAGE_VERSION}` + 'User-Agent': `duo_api_nodejs/${_PACKAGE_VERSION} ca_bundle/1.0 (ca_pinning=${this.enableCAPinning ? 'enabled' : 'disabled'})` } var body = '' var params_go_in_body = ['POST', 'PUT', 'PATCH'].includes(method) diff --git a/tests/main.js b/tests/main.js index a5daad3..32ff45f 100644 --- a/tests/main.js +++ b/tests/main.js @@ -234,4 +234,26 @@ describe('CA Pinning Configuration', function () { done() }) }) + + it('User agent includes ca_bundle version and ca_pinning=enabled when pinning is on', function (done) { + var client = new duo_api.Client(IKEY, SKEY, API_HOSTNAME) + client.jsonApiCall('GET', '/foo/bar', {}, function (resp) { + var options = requestSpy.firstCall.args[0] + var ua = options.headers['User-Agent'] + assert(ua.includes('ca_bundle/1.0')) + assert(ua.includes('(ca_pinning=enabled)')) + done() + }) + }) + + it('User agent includes ca_pinning=disabled when pinning is off', function (done) { + var client = new duo_api.Client(IKEY, SKEY, API_HOSTNAME, duo_api.SIGNATURE_VERSION_2, false) + client.jsonApiCall('GET', '/foo/bar', {}, function (resp) { + var options = requestSpy.firstCall.args[0] + var ua = options.headers['User-Agent'] + assert(ua.includes('ca_bundle/1.0')) + assert(ua.includes('(ca_pinning=disabled)')) + done() + }) + }) }) From 75b9ac087f017415b72650ebc571922329807a16 Mon Sep 17 00:00:00 2001 From: Anton Nikitiuk Date: Fri, 17 Jul 2026 17:18:18 +0300 Subject: [PATCH 2/2] Add CA_BUNDLE_VERSION const --- lib/constants.js | 2 ++ lib/main.js | 2 +- tests/main.js | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/constants.js b/lib/constants.js index 7d340cd..905f823 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -2,6 +2,7 @@ const _MAX_BACKOFF_WAIT_SECS = 32 const _BACKOFF_FACTOR = 2 const _RATE_LIMITED_RESP_CODE = 429 +const _CA_BUNDLE_VERSION = '1.0' const DUO_PINNED_CERT = ` # Source URL: https://www.amazontrust.com/repository/AmazonRootCA1.cer @@ -468,5 +469,6 @@ module.exports = { '_MAX_BACKOFF_WAIT_SECS': _MAX_BACKOFF_WAIT_SECS, '_BACKOFF_FACTOR': _BACKOFF_FACTOR, '_RATE_LIMITED_RESP_CODE': _RATE_LIMITED_RESP_CODE, + '_CA_BUNDLE_VERSION': _CA_BUNDLE_VERSION, 'DUO_PINNED_CERT': DUO_PINNED_CERT } diff --git a/lib/main.js b/lib/main.js index 76548f6..c62f4a8 100644 --- a/lib/main.js +++ b/lib/main.js @@ -20,7 +20,7 @@ Client.prototype.apiCall = function (method, path, params, callback) { var headers = { 'Date': date, 'Host': this.host, - 'User-Agent': `duo_api_nodejs/${_PACKAGE_VERSION} ca_bundle/1.0 (ca_pinning=${this.enableCAPinning ? 'enabled' : 'disabled'})` + 'User-Agent': `duo_api_nodejs/${_PACKAGE_VERSION} ca_bundle/${constants._CA_BUNDLE_VERSION} (ca_pinning=${this.enableCAPinning ? 'enabled' : 'disabled'})` } var body = '' var params_go_in_body = ['POST', 'PUT', 'PATCH'].includes(method) diff --git a/tests/main.js b/tests/main.js index 32ff45f..b307ed1 100644 --- a/tests/main.js +++ b/tests/main.js @@ -240,7 +240,7 @@ describe('CA Pinning Configuration', function () { client.jsonApiCall('GET', '/foo/bar', {}, function (resp) { var options = requestSpy.firstCall.args[0] var ua = options.headers['User-Agent'] - assert(ua.includes('ca_bundle/1.0')) + assert(ua.includes('ca_bundle/' + constants._CA_BUNDLE_VERSION)) assert(ua.includes('(ca_pinning=enabled)')) done() }) @@ -251,7 +251,7 @@ describe('CA Pinning Configuration', function () { client.jsonApiCall('GET', '/foo/bar', {}, function (resp) { var options = requestSpy.firstCall.args[0] var ua = options.headers['User-Agent'] - assert(ua.includes('ca_bundle/1.0')) + assert(ua.includes('ca_bundle/' + constants._CA_BUNDLE_VERSION)) assert(ua.includes('(ca_pinning=disabled)')) done() })