Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 5 additions & 1 deletion lib/marklogic.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
* Copyright (c) 2015-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
*/
'use strict';
const http = require('http');
Expand Down Expand Up @@ -761,6 +761,10 @@ function initClient(client, inputParams) {
if(!connectionParams.apiKey) {
throw new Error('apiKey needed for MarkLogic cloud authentication.');
}
if (connectionParams.accessTokenDuration !== undefined &&
(!Number.isInteger(connectionParams.accessTokenDuration) || connectionParams.accessTokenDuration <= 0)) {
throw new Error('accessTokenDuration must be a positive integer.');
}
connectionParams.port = 443;
} else if(authType === 'OAUTH' && !connectionParams.oauthToken){
throw new Error('oauthToken required for OAuth authentication. ');
Expand Down
2 changes: 1 addition & 1 deletion lib/requester.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function getAuthenticatorKerberos(client) {

function getAccessToken(operation){
const postData = `${encodeURI('grant_type')}=${encodeURI('apikey')}&${encodeURI('key')}=${encodeURI(operation.client.connectionParams.apiKey)}`;
const path = operation.client.connectionParams.accessTokenDuration?'/token?duration='+operation.client.connectionParams.accessTokenDuration:'/token';
const path = operation.client.connectionParams.accessTokenDuration?'/token?duration='+encodeURIComponent(operation.client.connectionParams.accessTokenDuration):'/token';
Comment on lines 48 to +49
const options = {
hostname: operation.client.connectionParams.host,
port: 443,
Expand Down
48 changes: 47 additions & 1 deletion test-basic/cloud_authentication-test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
* Copyright (c) 2015-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
*/

const marklogic = require('../');
Expand Down Expand Up @@ -53,4 +53,50 @@ describe('cloud-authentication tests', function() {
done(error);
}
});

it('should URL-encode accessTokenDuration when building the token request path', function() {
const requester = require('../lib/requester');
const https = require('https');

const operation = {
client: {
connectionParams: {
host: 'example.marklogic.cloud',
apiKey: 'test-key',
accessTokenDuration: '100&extra=injected'
}
}
};

let capturedPath;
const originalRequest = https.request;
https.request = (options) => {
capturedPath = options.path;
throw new Error('stop');
};

try {
requester.getAccessToken(operation);
} catch (e) {
// ignore stubbed error
} finally {
https.request = originalRequest;
}
assert.strictEqual(capturedPath, '/token?duration=100%26extra%3Dinjected');
});

it('should throw an error when accessTokenDuration is not a positive integer', function() {
try {
marklogic.createDatabaseClient({
host: 'example.marklogic.cloud',
authType: 'cloud',
apiKey: 'test-key',
accessTokenDuration: '100&extra=injected'
});
throw new Error('Expected validation error was not thrown');
} catch (error) {
assert(error.message.includes('accessTokenDuration must be a positive integer'),
'Error message should mention accessTokenDuration validation');
}
});
});
Loading