From 03e632606b0491bf404e614593d4b202d9da6aee Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 20 Jan 2026 16:27:27 +0700 Subject: [PATCH 01/10] test(NODE-7329): run oidc machine prose tests in all envs --- .evergreen/run-oidc-prose-tests.sh | 15 +- package.json | 3 - .../auth/mongodb_oidc.prose.test.ts | 254 +++++++++--------- .../auth/mongodb_oidc_azure.prose.05.test.ts | 86 ------ .../auth/mongodb_oidc_gcp.prose.06.test.ts | 55 ---- .../auth/mongodb_oidc_k8s.prose.07.test.ts | 39 --- 6 files changed, 127 insertions(+), 325 deletions(-) delete mode 100644 test/integration/auth/mongodb_oidc_azure.prose.05.test.ts delete mode 100644 test/integration/auth/mongodb_oidc_gcp.prose.06.test.ts delete mode 100644 test/integration/auth/mongodb_oidc_k8s.prose.07.test.ts diff --git a/.evergreen/run-oidc-prose-tests.sh b/.evergreen/run-oidc-prose-tests.sh index 0be8b1e0dce..1e5716b0c8b 100755 --- a/.evergreen/run-oidc-prose-tests.sh +++ b/.evergreen/run-oidc-prose-tests.sh @@ -15,20 +15,11 @@ if [ -z "${MONGODB_URI_SINGLE}" ]; then exit 1 fi -if [ "$ENVIRONMENT" = "azure" ]; then - npm run check:oidc-azure -elif [ "$ENVIRONMENT" = "gcp" ]; then - npm run check:oidc-gcp -elif [ "$ENVIRONMENT" = "test" ]; then +if [ "$ENVIRONMENT" = "test" ]; then if [ -z "${OIDC_TOKEN_FILE}" ]; then echo "Must specify OIDC_TOKEN_FILE" exit 1 fi - npm run check:oidc-test -else - if [ -z "${K8S_VARIANT}" ]; then - echo "Must specify K8S_VARIANT" - exit 1 - fi - npm run check:oidc-k8s fi + +npm run check:oidc-test \ No newline at end of file diff --git a/package.json b/package.json index 3f7c7f83666..769745ce1b1 100644 --- a/package.json +++ b/package.json @@ -147,9 +147,6 @@ "check:aws": "nyc mocha --config test/mocha_mongodb.js test/integration/auth/mongodb_aws.test.ts test/integration/auth/mongodb_aws.prose.test.ts", "check:oidc-auth": "nyc mocha --config test/mocha_mongodb.js test/integration/auth/auth.spec.test.ts", "check:oidc-test": "nyc mocha --config test/mocha_mongodb.js test/integration/auth/mongodb_oidc.prose.test.ts", - "check:oidc-azure": "nyc mocha --config test/mocha_mongodb.js test/integration/auth/mongodb_oidc_azure.prose.05.test.ts", - "check:oidc-gcp": "nyc mocha --config test/mocha_mongodb.js test/integration/auth/mongodb_oidc_gcp.prose.06.test.ts", - "check:oidc-k8s": "nyc mocha --config test/mocha_mongodb.js test/integration/auth/mongodb_oidc_k8s.prose.07.test.ts", "check:kerberos": "nyc mocha --config test/manual/mocharc.js test/manual/kerberos.test.ts", "check:tls": "nyc mocha --config test/manual/mocharc.js test/manual/tls_support.test.ts", "check:ldap": "nyc mocha --config test/manual/mocharc.js test/manual/ldap.test.ts", diff --git a/test/integration/auth/mongodb_oidc.prose.test.ts b/test/integration/auth/mongodb_oidc.prose.test.ts index dceb41f2723..b94108e2670 100644 --- a/test/integration/auth/mongodb_oidc.prose.test.ts +++ b/test/integration/auth/mongodb_oidc.prose.test.ts @@ -9,10 +9,11 @@ import { type ClientSession, type Collection, MongoClient, + type MongoClientOptions, type OIDCCallbackParams, type OIDCResponse } from '../../../src'; -import { type MongoDBOIDC } from '../../../src/cmap/auth/mongodb_oidc'; +import { type MongoDBOIDC, type OIDCCallbackFunction } from '../../../src/cmap/auth/mongodb_oidc'; const createCallback = (tokenFile = 'test_user1', expiresInSeconds?: number, extraFields?: any) => { return async (params: OIDCCallbackParams) => { @@ -38,14 +39,35 @@ const generateResult = (token: string, expiresInSeconds?: number, extraFields?: return response; }; -describe('OIDC Auth Spec Tests', function () { - beforeEach(function () { - if (process.env.ENVIRONMENT !== 'test') { - this.skipReason = 'GCP OIDC prose tests require a Test OIDC environment.'; - this.skip(); - } - }); +const DEFAULT_URI = 'mongodb://127.0.0.1:27017'; +const URI_SINGLE = process.env.MONGODB_URI_SINGLE ?? DEFAULT_URI; +const isCallbackTest = process.env.ENVIRONMENT === 'test'; + +const getClientOptions = (callbackSpy?: OIDCCallbackFunction) => { + const options: MongoClientOptions = {}; + options.retryReads = false; + if (process.env.AZUREOIDC_RESOURCE) { + options.authMechanismProperties = { TOKEN_RESOURCE: process.env.AZUREOIDC_RESOURCE }; + } + if (process.env.AZUREOIDC_USERNAME) { + options.auth = { username: process.env.AZUREOIDC_USERNAME, password: undefined }; + } + if (process.env.GCPOIDC_AUDIENCE) { + options.authMechanismProperties = { TOKEN_RESOURCE: process.env.GCPOIDC_AUDIENCE }; + } + if (isCallbackTest && callbackSpy) { + options.authMechanismProperties = { OIDC_CALLBACK: callbackSpy }; + } + return options; +}; + +const getClient = (extraOptions: MongoClientOptions = {}, callbackSpy?: OIDCCallbackFunction) => { + const options = getClientOptions(callbackSpy); + const mergedOptions = { options, ...extraOptions }; + return new MongoClient(URI_SINGLE, mergedOptions); +}; +describe('OIDC Auth Spec Tests', function () { describe('Machine Authentication Flow Prose Tests', function () { const uriSingle = process.env.MONGODB_URI_SINGLE; @@ -61,21 +83,19 @@ describe('OIDC Auth Spec Tests', function () { const callbackSpy = sinon.spy(createCallback('test_machine')); // Create an OIDC configured client. // Perform a find operation that succeeds. - // Assert that the callback was called 1 time. + // `[callback-only]` Assert that the callback was called 1 time. // Close the client. beforeEach(function () { - client = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: callbackSpy - }, - retryReads: false - }); + client = getClient({}, callbackSpy); collection = client.db('test').collection('test'); }); it('successfully authenticates', async function () { - await collection.findOne(); - expect(callbackSpy).to.have.been.calledOnce; + const error = await collection.findOne().catch(error => error); + expect(error).to.not.exist; + if (isCallbackTest) { + expect(callbackSpy).to.have.been.calledOnce; + } }); }); @@ -83,31 +103,36 @@ describe('OIDC Auth Spec Tests', function () { const callbackSpy = sinon.spy(createCallback()); // Create an OIDC configured client. // Start 10 threads and run 100 find operations in each thread that all succeed. - // Assert that the callback was called 1 time. + // `[callback-only]` Assert that the callback was called 1 time. // Close the client. beforeEach(function () { - client = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: callbackSpy - }, - retryReads: false - }); + client = getClient({}, callbackSpy); collection = client.db('test').collection('test'); }); it('only calls the callback once', async function () { for (let i = 0; i < 100; i++) { - await collection.findOne(); + const error = await collection.findOne().catch(error => error); + expect(error).to.not.exist; + } + if (isCallbackTest) { + expect(callbackSpy).to.have.been.calledOnce; } - expect(callbackSpy).to.have.been.calledOnce; }); }); }); - describe('2. OIDC Callback Validation', function () { + describe('2. `[callback-only]` OIDC Callback Validation', function () { let client: MongoClient; let collection: Collection; + beforeEach(function () { + if (!isCallbackTest) { + this.skipReason = 'Callback validation tests only run in test environment'; + this.skip(); + } + }); + afterEach(async function () { await client?.close(); }); @@ -119,12 +144,7 @@ describe('OIDC Auth Spec Tests', function () { // Assert that the OIDC callback was called with the appropriate inputs, including the timeout parameter if possible. // Close the client. beforeEach(function () { - client = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: callbackSpy - }, - retryReads: false - }); + client = getClient({}, callbackSpy); collection = client.db('test').collection('test'); }); @@ -141,12 +161,7 @@ describe('OIDC Auth Spec Tests', function () { // Perform a find operation that fails. // Close the client. beforeEach(function () { - client = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: callbackSpy - }, - retryReads: false - }); + client = getClient({}, callbackSpy); collection = client.db('test').collection('test'); }); @@ -164,12 +179,7 @@ describe('OIDC Auth Spec Tests', function () { // Perform a find operation that fails. // Close the client. beforeEach(function () { - client = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: callbackSpy - }, - retryReads: false - }); + client = getClient({}, callbackSpy); collection = client.db('test').collection('test'); }); @@ -185,13 +195,7 @@ describe('OIDC Auth Spec Tests', function () { // Assert it returns a client configuration error. it('fails validation', async function () { try { - client = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: callbackSpy, - ENVIRONMENT: 'test' - }, - retryReads: false - }); + client = getClient({}, callbackSpy); } catch (error) { expect(error).to.exist; } @@ -212,15 +216,10 @@ describe('OIDC Auth Spec Tests', function () { // Create an OIDC configured client. // Poison the Client Cache with an invalid access token. // Perform a find operation that succeeds. - // Assert that the callback was called 1 time. + // `[callback-only]` Assert that the callback was called 1 time. // Close the client. beforeEach(function () { - client = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: callbackSpy - }, - retryReads: false - }); + client = getClient({}, callbackSpy); const provider = client.s.authProviders.getOrCreateProvider('MONGODB-OIDC', { OIDC_CALLBACK: callbackSpy }) as MongoDBOIDC; @@ -229,12 +228,15 @@ describe('OIDC Auth Spec Tests', function () { }); it('successfully authenticates', async function () { - await collection.findOne(); - expect(callbackSpy).to.have.been.calledOnce; + const error = await collection.findOne().catch(error => error); + expect(error).to.not.exist; + if (isCallbackTest) { + expect(callbackSpy).to.have.been.calledOnce; + } }); }); - describe('3.2 Authentication failures without cached tokens return an error', function () { + describe('3.2 `[callback-only]` Authentication failures without cached tokens return an error', function () { const callbackSpy = sinon.spy(() => { return { accessToken: 'bad' }; }); @@ -243,12 +245,11 @@ describe('OIDC Auth Spec Tests', function () { // Assert that the callback was called 1 time. // Close the client. beforeEach(function () { - client = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: callbackSpy - }, - retryReads: false - }); + if (!isCallbackTest) { + this.skipReason = 'Callback validation tests only run in test environment'; + this.skip(); + } + client = getClient({}, callbackSpy); const provider = client.s.authProviders.getOrCreateProvider('MONGODB-OIDC', { OIDC_CALLBACK: callbackSpy }) as MongoDBOIDC; @@ -281,17 +282,12 @@ describe('OIDC Auth Spec Tests', function () { // } // } // Perform a find operation that fails. - // Assert that the callback has been called once. + // `[callback-only]` Assert that the callback has been called once. // Perform a find operation that succeeds. - // Assert that the callback has been called once. + // `[callback-only]` Assert that the callback has been called once. // Close the client. beforeEach(async function () { - client = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: callbackSpy - }, - retryReads: false - }); + client = getClient({}, callbackSpy); utilClient = new MongoClient(uriSingle, { authMechanismProperties: { OIDC_CALLBACK: createCallback() @@ -325,9 +321,14 @@ describe('OIDC Auth Spec Tests', function () { it('successfully authenticates the second time', async function () { const error = await collection.findOne().catch(error => error); expect(error).to.exist; - expect(callbackSpy).to.have.been.calledOnce; - await collection.findOne(); - expect(callbackSpy).to.have.been.calledOnce; + if (isCallbackTest) { + expect(callbackSpy).to.have.been.calledOnce; + } + const nextError = await collection.findOne().catch(nextError => nextError); + expect(nextError).to.not.exist; + if (isCallbackTest) { + expect(callbackSpy).to.have.been.calledOnce; + } }); }); }); @@ -373,15 +374,10 @@ describe('OIDC Auth Spec Tests', function () { // } // } // Perform a find operation that succeeds. - // Assert that the callback was called 2 times (once during the connection handshake, and again during reauthentication). + // `[callback-only]` Assert that the callback was called 2 times (once during the connection handshake, and again during reauthentication). // Close the client. beforeEach(async function () { - client = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: callbackSpy - }, - retryReads: false - }); + client = getClient({}, callbackSpy); utilClient = new MongoClient(uriSingle, { authMechanismProperties: { OIDC_CALLBACK: createCallback() @@ -413,8 +409,11 @@ describe('OIDC Auth Spec Tests', function () { }); it('successfully authenticates', async function () { - await collection.findOne(); - expect(callbackSpy).to.have.been.calledTwice; + const error = await collection.findOne().catch(error => error); + expect(error).to.not.exist; + if (isCallbackTest) { + expect(callbackSpy).to.have.been.calledTwice; + } }); }); @@ -436,16 +435,10 @@ describe('OIDC Auth Spec Tests', function () { // } // } // Perform a find operation that succeeds. - // Assert that the callback was called 2 times (once during the connection handshake, and again during reauthentication). + // `[callback-only]` Assert that the callback was called 2 times (once during the connection handshake, and again during reauthentication). // Close the client. beforeEach(async function () { - client = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: callbackSpy - }, - retryReads: false, - promoteValues: false - }); + client = getClient({ promoteValues: false }, callbackSpy); utilClient = new MongoClient(uriSingle, { authMechanismProperties: { OIDC_CALLBACK: createCallback() @@ -477,12 +470,15 @@ describe('OIDC Auth Spec Tests', function () { }); it('successfully authenticates', async function () { - await collection.findOne(); - expect(callbackSpy).to.have.been.calledTwice; + const error = await collection.findOne().catch(error => error); + expect(error).to.not.exist; + if (isCallbackTest) { + expect(callbackSpy).to.have.been.calledTwice; + } }); }); - describe('4.2 Read Commands Fail If Reauthentication Fails', function () { + describe('4.2 `[callback-only]` Read Commands Fail If Reauthentication Fails', function () { let utilClient: MongoClient; const callbackSpy = sinon.spy(createBadCallback()); // Create a MongoClient whose OIDC callback returns one good token and then bad tokens after the first call. @@ -504,12 +500,11 @@ describe('OIDC Auth Spec Tests', function () { // Assert that the callback was called 2 times. // Close the client. beforeEach(async function () { - client = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: callbackSpy - }, - retryReads: false - }); + if (!isCallbackTest) { + this.skipReason = 'Callback validation tests only run in test environment'; + this.skip(); + } + client = getClient({}, callbackSpy); utilClient = new MongoClient(uriSingle, { authMechanismProperties: { OIDC_CALLBACK: createCallback() @@ -547,7 +542,7 @@ describe('OIDC Auth Spec Tests', function () { }); }); - describe('4.3 Write Commands Fail If Reauthentication Fails', function () { + describe('4.3 `[callback-only]` Write Commands Fail If Reauthentication Fails', function () { let utilClient: MongoClient; const callbackSpy = sinon.spy(createBadCallback()); // Create a MongoClient whose OIDC callback returns one good token and then bad tokens after the first call. @@ -569,12 +564,11 @@ describe('OIDC Auth Spec Tests', function () { // Assert that the callback was called 2 times. // Close the client. beforeEach(async function () { - client = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: callbackSpy - }, - retryReads: false - }); + if (!isCallbackTest) { + this.skipReason = 'Callback validation tests only run in test environment'; + this.skip(); + } + client = getClient({}, callbackSpy); utilClient = new MongoClient(uriSingle, { authMechanismProperties: { OIDC_CALLBACK: createCallback() @@ -619,6 +613,7 @@ describe('OIDC Auth Spec Tests', function () { const saslStarts = []; // - Create an OIDC configured client. // - Populate the *Client Cache* with a valid access token to enforce Speculative Authentication. + // - This may be done by authenticating a temporary OIDC configured client and copying the cached token. // - Perform an `insert` operation that succeeds. // - Assert that the callback was not called. // - Assert there were no `SaslStart` commands executed. @@ -638,7 +633,7 @@ describe('OIDC Auth Spec Tests', function () { // } // ``` // - Perform an `insert` operation that succeeds. - // - Assert that the callback was called once. + // - `[callback-only]` Assert that the callback was called once. // - Assert there were `SaslStart` commands executed. // - Close the client. beforeEach(async function () { @@ -649,13 +644,7 @@ describe('OIDC Auth Spec Tests', function () { retryReads: false }); - client = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: callbackSpy - }, - retryReads: false, - monitorCommands: true - }); + client = getClient({ monitorCommands: true }, callbackSpy); client.on('commandStarted', event => { if (event.commandName === 'saslStart') { saslStarts.push(event); @@ -701,7 +690,9 @@ describe('OIDC Auth Spec Tests', function () { }); await collection.insertOne({ name: 'test' }); - expect(callbackSpy).to.have.been.calledOnce; + if (isCallbackTest) { + expect(callbackSpy).to.have.been.calledOnce; + } expect(saslStarts.length).to.equal(1); }); }); @@ -726,15 +717,10 @@ describe('OIDC Auth Spec Tests', function () { // } // Start a new session. // In the started session perform a find operation that succeeds. - // Assert that the callback was called 2 times (once during the connection handshake, and again during reauthentication). + // `[callback-only]` Assert that the callback was called 2 times (once during the connection handshake, and again during reauthentication). // Close the session and the client. beforeEach(async function () { - client = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: callbackSpy - }, - retryReads: false - }); + client = getClient({}, callbackSpy); utilClient = new MongoClient(uriSingle, { authMechanismProperties: { OIDC_CALLBACK: createCallback() @@ -768,8 +754,11 @@ describe('OIDC Auth Spec Tests', function () { }); it('successfully authenticates', async function () { - await collection.findOne({}, { session }); - expect(callbackSpy).to.have.been.calledTwice; + const error = await collection.findOne({}, { session }).catch(error => error); + expect(error).to.not.exist; + if (isCallbackTest) { + expect(callbackSpy).to.have.been.calledTwice; + } }); }); }); @@ -779,6 +768,11 @@ describe('OIDC Auth Spec Tests', function () { const uriSingle = process.env.MONGODB_URI_SINGLE; const uriMulti = process.env.MONGODB_URI_MULTI; + if (!isCallbackTest) { + this.skipReason = 'OIDC human prose tests require a Test OIDC environment.'; + this.skip(); + } + describe('1. OIDC Human Callback Authentication', function () { let client: MongoClient; let collection: Collection; diff --git a/test/integration/auth/mongodb_oidc_azure.prose.05.test.ts b/test/integration/auth/mongodb_oidc_azure.prose.05.test.ts deleted file mode 100644 index f2bc91f7ebf..00000000000 --- a/test/integration/auth/mongodb_oidc_azure.prose.05.test.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { expect } from 'chai'; -import * as process from 'process'; - -import { type Collection, MongoClient, type MongoClientOptions } from '../../../src'; - -const DEFAULT_URI = 'mongodb://127.0.0.1:27017'; - -describe('OIDC Auth Spec Azure Tests', function () { - describe('5. Azure Tests', function () { - let client: MongoClient; - let collection: Collection; - - beforeEach(function () { - if (!this.configuration.isOIDC(process.env.MONGODB_URI_SINGLE, 'azure')) { - this.skipReason = 'Azure OIDC tests require an Azure OIDC environment.'; - this.skip(); - } - }); - - afterEach(async function () { - await client?.close(); - }); - - describe('5.1 Azure With No Username', function () { - // Create an OIDC configured client with ENVIRONMENT:azure and a valid TOKEN_RESOURCE and no username. - // Perform a find operation that succeeds. - // Close the client. - beforeEach(function () { - const options: MongoClientOptions = {}; - if (process.env.AZUREOIDC_RESOURCE) { - options.authMechanismProperties = { TOKEN_RESOURCE: process.env.AZUREOIDC_RESOURCE }; - } - client = new MongoClient(process.env.MONGODB_URI_SINGLE ?? DEFAULT_URI, options); - collection = client.db('test').collection('test'); - }); - - it('successfully authenticates', async function () { - const result = await collection.findOne(); - expect(result).to.not.be.null; - }); - }); - - describe('5.2 Azure With Bad Username', function () { - // Create an OIDC configured client with ENVIRONMENT:azure and a valid TOKEN_RESOURCE and a username of "bad". - // Perform a find operation that fails. - // Close the client. - beforeEach(function () { - const options: MongoClientOptions = {}; - if (process.env.AZUREOIDC_USERNAME) { - options.auth = { username: 'bad', password: undefined }; - } - if (process.env.AZUREOIDC_RESOURCE) { - options.authMechanismProperties = { TOKEN_RESOURCE: process.env.AZUREOIDC_RESOURCE }; - } - client = new MongoClient(process.env.MONGODB_URI_SINGLE ?? DEFAULT_URI, options); - collection = client.db('test').collection('test'); - }); - - it('does not authenticate', async function () { - const error = await collection.findOne().catch(error => error); - expect(error.message).to.include('Azure endpoint'); - }); - }); - - describe('5.3 Azure With Valid Username', function () { - // This prose test does not exist in the spec but the new OIDC setup scripts - // have a username in the environment so worth testing. - beforeEach(function () { - const options: MongoClientOptions = {}; - if (process.env.AZUREOIDC_USERNAME) { - options.auth = { username: process.env.AZUREOIDC_USERNAME, password: undefined }; - } - if (process.env.AZUREOIDC_RESOURCE) { - options.authMechanismProperties = { TOKEN_RESOURCE: process.env.AZUREOIDC_RESOURCE }; - } - client = new MongoClient(process.env.MONGODB_URI_SINGLE ?? DEFAULT_URI, options); - collection = client.db('test').collection('test'); - }); - - it('successfully authenticates', async function () { - const result = await collection.findOne(); - expect(result).to.not.be.null; - }); - }); - }); -}); diff --git a/test/integration/auth/mongodb_oidc_gcp.prose.06.test.ts b/test/integration/auth/mongodb_oidc_gcp.prose.06.test.ts deleted file mode 100644 index cef9ad20215..00000000000 --- a/test/integration/auth/mongodb_oidc_gcp.prose.06.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { expect } from 'chai'; -import * as process from 'process'; - -import { type Collection, MongoClient, type MongoClientOptions } from '../../../src'; - -const DEFAULT_URI = 'mongodb://127.0.0.1:27017'; - -describe('OIDC Auth Spec GCP Tests', function () { - // Note there is no spec or tests for GCP yet, these are 2 scenarios based on the - // drivers tools scripts available. - describe('6. GCP Tests', function () { - let client: MongoClient; - let collection: Collection; - - beforeEach(function () { - if (!this.configuration.isOIDC(process.env.MONGODB_URI_SINGLE, 'gcp')) { - this.skipReason = 'GCP OIDC prose tests require a GCP OIDC environment.'; - this.skip(); - } - }); - - afterEach(async function () { - await client?.close(); - }); - - describe('6.1 GCP With Valid Token Resource', function () { - beforeEach(function () { - const options: MongoClientOptions = {}; - if (process.env.GCPOIDC_AUDIENCE) { - options.authMechanismProperties = { TOKEN_RESOURCE: process.env.GCPOIDC_AUDIENCE }; - } - client = new MongoClient(process.env.MONGODB_URI_SINGLE ?? DEFAULT_URI, options); - collection = client.db('test').collection('test'); - }); - - it('successfully authenticates', async function () { - const result = await collection.findOne(); - expect(result).to.not.be.null; - }); - }); - - describe('6.2 GCP With Invalid Token Resource', function () { - beforeEach(function () { - const options: MongoClientOptions = { authMechanismProperties: { TOKEN_RESOURCE: 'bad' } }; - client = new MongoClient(process.env.MONGODB_URI_SINGLE ?? DEFAULT_URI, options); - collection = client.db('test').collection('test'); - }); - - it('successfully authenticates', async function () { - const result = await collection.findOne(); - expect(result).to.not.be.null; - }); - }); - }); -}); diff --git a/test/integration/auth/mongodb_oidc_k8s.prose.07.test.ts b/test/integration/auth/mongodb_oidc_k8s.prose.07.test.ts deleted file mode 100644 index a46a068a399..00000000000 --- a/test/integration/auth/mongodb_oidc_k8s.prose.07.test.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { expect } from 'chai'; -import * as process from 'process'; - -import { type Collection, MongoClient } from '../../../src'; - -const DEFAULT_URI = 'mongodb://127.0.0.1:27017'; - -describe('OIDC Auth Spec K8s Tests', function () { - // Note there is no spec or tests for K8s, and it's optional to run the entire - // machine prose tests on the additional environments so we do 1 sanity check - // here. This same test will run in CI on AKS, EKS, and GKE. - describe('7. K8s Tests', function () { - let client: MongoClient; - let collection: Collection; - - beforeEach(function () { - if (!this.configuration.isOIDC(process.env.MONGODB_URI_SINGLE, 'k8s')) { - this.skipReason = 'K8s OIDC prose tests require a K8s OIDC environment.'; - this.skip(); - } - }); - - afterEach(async function () { - await client?.close(); - }); - - describe('7.1 K8s With Environment Set', function () { - beforeEach(function () { - client = new MongoClient(process.env.MONGODB_URI_SINGLE ?? DEFAULT_URI); - collection = client.db('test').collection('test'); - }); - - it('successfully authenticates', async function () { - const result = await collection.findOne(); - expect(result).to.not.be.null; - }); - }); - }); -}); From 632f2da8cb788a4b869f759c01846b24e7c3dcab Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 20 Jan 2026 16:42:15 +0700 Subject: [PATCH 02/10] test: fix options parsing --- test/integration/auth/mongodb_oidc.prose.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/auth/mongodb_oidc.prose.test.ts b/test/integration/auth/mongodb_oidc.prose.test.ts index b94108e2670..0b0930e6681 100644 --- a/test/integration/auth/mongodb_oidc.prose.test.ts +++ b/test/integration/auth/mongodb_oidc.prose.test.ts @@ -63,7 +63,7 @@ const getClientOptions = (callbackSpy?: OIDCCallbackFunction) => { const getClient = (extraOptions: MongoClientOptions = {}, callbackSpy?: OIDCCallbackFunction) => { const options = getClientOptions(callbackSpy); - const mergedOptions = { options, ...extraOptions }; + const mergedOptions = extraOptions ? { ...options, ...extraOptions } : options; return new MongoClient(URI_SINGLE, mergedOptions); }; From 20b143ca17ad4e538beac6f1ee321d21289c34a9 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 20 Jan 2026 16:54:55 +0700 Subject: [PATCH 03/10] test: fix prose test --- test/integration/auth/mongodb_oidc.prose.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/auth/mongodb_oidc.prose.test.ts b/test/integration/auth/mongodb_oidc.prose.test.ts index 0b0930e6681..e18d2d54923 100644 --- a/test/integration/auth/mongodb_oidc.prose.test.ts +++ b/test/integration/auth/mongodb_oidc.prose.test.ts @@ -754,8 +754,8 @@ describe('OIDC Auth Spec Tests', function () { }); it('successfully authenticates', async function () { - const error = await collection.findOne({}, { session }).catch(error => error); - expect(error).to.not.exist; + const result = await collection.findOne({}, { session }); + expect(result).to.exist; if (isCallbackTest) { expect(callbackSpy).to.have.been.calledTwice; } From 94e1c4a87a8a0812797d38c4a57155818981997a Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 20 Jan 2026 17:11:13 +0700 Subject: [PATCH 04/10] test: fix human skip on non test env --- test/integration/auth/mongodb_oidc.prose.test.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/integration/auth/mongodb_oidc.prose.test.ts b/test/integration/auth/mongodb_oidc.prose.test.ts index e18d2d54923..cdaa7da56a2 100644 --- a/test/integration/auth/mongodb_oidc.prose.test.ts +++ b/test/integration/auth/mongodb_oidc.prose.test.ts @@ -768,10 +768,12 @@ describe('OIDC Auth Spec Tests', function () { const uriSingle = process.env.MONGODB_URI_SINGLE; const uriMulti = process.env.MONGODB_URI_MULTI; - if (!isCallbackTest) { - this.skipReason = 'OIDC human prose tests require a Test OIDC environment.'; - this.skip(); - } + beforeEach(function () { + if (!isCallbackTest) { + this.skipReason = 'OIDC human prose tests require a Test OIDC environment.'; + this.skip(); + } + }); describe('1. OIDC Human Callback Authentication', function () { let client: MongoClient; From 12152ba0296296780e326d7fd89f548f47310a30 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 20 Jan 2026 18:23:26 +0700 Subject: [PATCH 05/10] test: fix util client creation --- .../auth/mongodb_oidc.prose.test.ts | 68 +++++++------------ 1 file changed, 24 insertions(+), 44 deletions(-) diff --git a/test/integration/auth/mongodb_oidc.prose.test.ts b/test/integration/auth/mongodb_oidc.prose.test.ts index cdaa7da56a2..79c3d105f48 100644 --- a/test/integration/auth/mongodb_oidc.prose.test.ts +++ b/test/integration/auth/mongodb_oidc.prose.test.ts @@ -14,6 +14,7 @@ import { type OIDCResponse } from '../../../src'; import { type MongoDBOIDC, type OIDCCallbackFunction } from '../../../src/cmap/auth/mongodb_oidc'; +import { getEnvironmentData } from 'node:worker_threads'; const createCallback = (tokenFile = 'test_user1', expiresInSeconds?: number, extraFields?: any) => { return async (params: OIDCCallbackParams) => { @@ -61,6 +62,13 @@ const getClientOptions = (callbackSpy?: OIDCCallbackFunction) => { return options; }; +const getProviderLookupProperties = (callbackSpy?: OIDCCallbackFunction) => { + if (isCallbackTest && callbackSpy) { + return { OIDC_CALLBACK: callbackSpy }; + } + return { ENVIRONMENT: process.env.ENVIRONMENT }; +} + const getClient = (extraOptions: MongoClientOptions = {}, callbackSpy?: OIDCCallbackFunction) => { const options = getClientOptions(callbackSpy); const mergedOptions = extraOptions ? { ...options, ...extraOptions } : options; @@ -91,8 +99,7 @@ describe('OIDC Auth Spec Tests', function () { }); it('successfully authenticates', async function () { - const error = await collection.findOne().catch(error => error); - expect(error).to.not.exist; + await collection.findOne(); if (isCallbackTest) { expect(callbackSpy).to.have.been.calledOnce; } @@ -112,8 +119,7 @@ describe('OIDC Auth Spec Tests', function () { it('only calls the callback once', async function () { for (let i = 0; i < 100; i++) { - const error = await collection.findOne().catch(error => error); - expect(error).to.not.exist; + await collection.findOne(); } if (isCallbackTest) { expect(callbackSpy).to.have.been.calledOnce; @@ -220,16 +226,16 @@ describe('OIDC Auth Spec Tests', function () { // Close the client. beforeEach(function () { client = getClient({}, callbackSpy); - const provider = client.s.authProviders.getOrCreateProvider('MONGODB-OIDC', { - OIDC_CALLBACK: callbackSpy - }) as MongoDBOIDC; + const provider = client.s.authProviders.getOrCreateProvider( + 'MONGODB-OIDC', + getProviderLookupProperties(callbackSpy) + ) as MongoDBOIDC; provider.workflow.cache.put({ idpServerResponse: { accessToken: 'bad' } }); collection = client.db('test').collection('test'); }); it('successfully authenticates', async function () { - const error = await collection.findOne().catch(error => error); - expect(error).to.not.exist; + await collection.findOne(); if (isCallbackTest) { expect(callbackSpy).to.have.been.calledOnce; } @@ -288,12 +294,7 @@ describe('OIDC Auth Spec Tests', function () { // Close the client. beforeEach(async function () { client = getClient({}, callbackSpy); - utilClient = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: createCallback() - }, - retryReads: false - }); + utilClient = getClient({}, callbackSpy); collection = client.db('test').collection('test'); await utilClient .db() @@ -378,12 +379,7 @@ describe('OIDC Auth Spec Tests', function () { // Close the client. beforeEach(async function () { client = getClient({}, callbackSpy); - utilClient = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: createCallback() - }, - retryReads: false - }); + utilClient = getClient({}, callbackSpy); collection = client.db('test').collection('test'); await utilClient .db() @@ -439,12 +435,7 @@ describe('OIDC Auth Spec Tests', function () { // Close the client. beforeEach(async function () { client = getClient({ promoteValues: false }, callbackSpy); - utilClient = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: createCallback() - }, - retryReads: false - }); + utilClient = getClient({ promoteValues: false }, callbackSpy); collection = client.db('test').collection('test'); await utilClient .db() @@ -501,8 +492,8 @@ describe('OIDC Auth Spec Tests', function () { // Close the client. beforeEach(async function () { if (!isCallbackTest) { - this.skipReason = 'Callback validation tests only run in test environment'; - this.skip(); + this.test.skipReason = 'Callback validation tests only run in test environment'; + this.test.skip(); } client = getClient({}, callbackSpy); utilClient = new MongoClient(uriSingle, { @@ -565,8 +556,8 @@ describe('OIDC Auth Spec Tests', function () { // Close the client. beforeEach(async function () { if (!isCallbackTest) { - this.skipReason = 'Callback validation tests only run in test environment'; - this.skip(); + this.test.skipReason = 'Callback validation tests only run in test environment'; + this.test.skip(); } client = getClient({}, callbackSpy); utilClient = new MongoClient(uriSingle, { @@ -637,13 +628,7 @@ describe('OIDC Auth Spec Tests', function () { // - Assert there were `SaslStart` commands executed. // - Close the client. beforeEach(async function () { - utilClient = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: createCallback() - }, - retryReads: false - }); - + utilClient = getClient({}, callbackSpy); client = getClient({ monitorCommands: true }, callbackSpy); client.on('commandStarted', event => { if (event.commandName === 'saslStart') { @@ -721,12 +706,7 @@ describe('OIDC Auth Spec Tests', function () { // Close the session and the client. beforeEach(async function () { client = getClient({}, callbackSpy); - utilClient = new MongoClient(uriSingle, { - authMechanismProperties: { - OIDC_CALLBACK: createCallback() - }, - retryReads: false - }); + utilClient = getClient({}, callbackSpy); collection = client.db('test').collection('test'); await utilClient .db() From 04602cd92bf86e2563c41b4b7d74617fdacf3a3a Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 20 Jan 2026 18:30:52 +0700 Subject: [PATCH 06/10] test: fix util client --- test/integration/auth/mongodb_oidc.prose.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/integration/auth/mongodb_oidc.prose.test.ts b/test/integration/auth/mongodb_oidc.prose.test.ts index 79c3d105f48..2b3a3b853cd 100644 --- a/test/integration/auth/mongodb_oidc.prose.test.ts +++ b/test/integration/auth/mongodb_oidc.prose.test.ts @@ -294,7 +294,7 @@ describe('OIDC Auth Spec Tests', function () { // Close the client. beforeEach(async function () { client = getClient({}, callbackSpy); - utilClient = getClient({}, callbackSpy); + utilClient = getClient({}, createCallback()); collection = client.db('test').collection('test'); await utilClient .db() @@ -379,7 +379,7 @@ describe('OIDC Auth Spec Tests', function () { // Close the client. beforeEach(async function () { client = getClient({}, callbackSpy); - utilClient = getClient({}, callbackSpy); + utilClient = getClient({}, createCallback()); collection = client.db('test').collection('test'); await utilClient .db() @@ -435,7 +435,7 @@ describe('OIDC Auth Spec Tests', function () { // Close the client. beforeEach(async function () { client = getClient({ promoteValues: false }, callbackSpy); - utilClient = getClient({ promoteValues: false }, callbackSpy); + utilClient = getClient({ promoteValues: false }, createCallback()); collection = client.db('test').collection('test'); await utilClient .db() @@ -628,7 +628,7 @@ describe('OIDC Auth Spec Tests', function () { // - Assert there were `SaslStart` commands executed. // - Close the client. beforeEach(async function () { - utilClient = getClient({}, callbackSpy); + utilClient = getClient({}, createCallback()); client = getClient({ monitorCommands: true }, callbackSpy); client.on('commandStarted', event => { if (event.commandName === 'saslStart') { @@ -706,7 +706,7 @@ describe('OIDC Auth Spec Tests', function () { // Close the session and the client. beforeEach(async function () { client = getClient({}, callbackSpy); - utilClient = getClient({}, callbackSpy); + utilClient = getClient({}, createCallback()); collection = client.db('test').collection('test'); await utilClient .db() From 79347ffbbc6d01590e4789a9a988fdc01bae143b Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 20 Jan 2026 18:48:59 +0700 Subject: [PATCH 07/10] test: fix non callback tests --- .../auth/mongodb_oidc.prose.test.ts | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/test/integration/auth/mongodb_oidc.prose.test.ts b/test/integration/auth/mongodb_oidc.prose.test.ts index 2b3a3b853cd..0993397cb57 100644 --- a/test/integration/auth/mongodb_oidc.prose.test.ts +++ b/test/integration/auth/mongodb_oidc.prose.test.ts @@ -325,8 +325,7 @@ describe('OIDC Auth Spec Tests', function () { if (isCallbackTest) { expect(callbackSpy).to.have.been.calledOnce; } - const nextError = await collection.findOne().catch(nextError => nextError); - expect(nextError).to.not.exist; + await collection.findOne(); if (isCallbackTest) { expect(callbackSpy).to.have.been.calledOnce; } @@ -405,8 +404,7 @@ describe('OIDC Auth Spec Tests', function () { }); it('successfully authenticates', async function () { - const error = await collection.findOne().catch(error => error); - expect(error).to.not.exist; + await collection.findOne(); if (isCallbackTest) { expect(callbackSpy).to.have.been.calledTwice; } @@ -461,8 +459,7 @@ describe('OIDC Auth Spec Tests', function () { }); it('successfully authenticates', async function () { - const error = await collection.findOne().catch(error => error); - expect(error).to.not.exist; + await collection.findOne(); if (isCallbackTest) { expect(callbackSpy).to.have.been.calledTwice; } @@ -519,11 +516,11 @@ describe('OIDC Auth Spec Tests', function () { }); afterEach(async function () { - await utilClient.db().admin().command({ + await utilClient?.db().admin().command({ configureFailPoint: 'failCommand', mode: 'off' }); - await utilClient.close(); + await utilClient?.close(); }); it('does not successfully authenticate', async function () { @@ -584,11 +581,11 @@ describe('OIDC Auth Spec Tests', function () { }); afterEach(async function () { - await utilClient.db().admin().command({ + await utilClient?.db().admin().command({ configureFailPoint: 'failCommand', mode: 'off' }); - await utilClient.close(); + await utilClient?.close(); }); it('does not successfully authenticate', async function () { @@ -636,9 +633,10 @@ describe('OIDC Auth Spec Tests', function () { } }); - const provider = client.s.authProviders.getOrCreateProvider('MONGODB-OIDC', { - OIDC_CALLBACK: callbackSpy - }) as MongoDBOIDC; + const provider = client.s.authProviders.getOrCreateProvider( + 'MONGODB-OIDC', + getProviderLookupProperties(callbackSpy) + ) as MongoDBOIDC; const token = await readFile(path.join(process.env.OIDC_TOKEN_DIR, 'test_user1'), { encoding: 'utf8' }); @@ -648,11 +646,11 @@ describe('OIDC Auth Spec Tests', function () { }); afterEach(async function () { - await utilClient.db().admin().command({ + await utilClient?.db().admin().command({ configureFailPoint: 'failCommand', mode: 'off' }); - await utilClient.close(); + await utilClient?.close(); }); it('successfully authenticates', async function () { From da287e542a189f3bd690368ce8e79e56196b5059 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 20 Jan 2026 20:43:05 +0700 Subject: [PATCH 08/10] test: last callback changes --- .../auth/mongodb_oidc.prose.test.ts | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/test/integration/auth/mongodb_oidc.prose.test.ts b/test/integration/auth/mongodb_oidc.prose.test.ts index 0993397cb57..456a7051792 100644 --- a/test/integration/auth/mongodb_oidc.prose.test.ts +++ b/test/integration/auth/mongodb_oidc.prose.test.ts @@ -633,15 +633,17 @@ describe('OIDC Auth Spec Tests', function () { } }); - const provider = client.s.authProviders.getOrCreateProvider( - 'MONGODB-OIDC', - getProviderLookupProperties(callbackSpy) - ) as MongoDBOIDC; - const token = await readFile(path.join(process.env.OIDC_TOKEN_DIR, 'test_user1'), { - encoding: 'utf8' - }); + if (isCallbackTest) { + const provider = client.s.authProviders.getOrCreateProvider( + 'MONGODB-OIDC', + getProviderLookupProperties(callbackSpy) + ) as MongoDBOIDC; + const token = await readFile(path.join(process.env.OIDC_TOKEN_DIR, 'test_user1'), { + encoding: 'utf8' + }); + provider.workflow.cache.put({ accessToken: token }); + } - provider.workflow.cache.put({ accessToken: token }); collection = client.db('test').collection('test'); }); @@ -655,7 +657,9 @@ describe('OIDC Auth Spec Tests', function () { it('successfully authenticates', async function () { await collection.insertOne({ name: 'test' }); - expect(callbackSpy).to.not.have.been.called; + if (isCallbackTest) { + expect(callbackSpy).to.not.have.been.called; + } expect(saslStarts).to.be.empty; await utilClient From 019b9579f91a6b506ddcefdd9e41d6a409f52bb0 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 20 Jan 2026 22:01:30 +0700 Subject: [PATCH 09/10] fix: lint --- test/integration/auth/mongodb_oidc.prose.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/integration/auth/mongodb_oidc.prose.test.ts b/test/integration/auth/mongodb_oidc.prose.test.ts index 456a7051792..ad4a67f432d 100644 --- a/test/integration/auth/mongodb_oidc.prose.test.ts +++ b/test/integration/auth/mongodb_oidc.prose.test.ts @@ -14,7 +14,6 @@ import { type OIDCResponse } from '../../../src'; import { type MongoDBOIDC, type OIDCCallbackFunction } from '../../../src/cmap/auth/mongodb_oidc'; -import { getEnvironmentData } from 'node:worker_threads'; const createCallback = (tokenFile = 'test_user1', expiresInSeconds?: number, extraFields?: any) => { return async (params: OIDCCallbackParams) => { @@ -67,7 +66,7 @@ const getProviderLookupProperties = (callbackSpy?: OIDCCallbackFunction) => { return { OIDC_CALLBACK: callbackSpy }; } return { ENVIRONMENT: process.env.ENVIRONMENT }; -} +}; const getClient = (extraOptions: MongoClientOptions = {}, callbackSpy?: OIDCCallbackFunction) => { const options = getClientOptions(callbackSpy); From 909443a237eed33009c0e163f5bfb12b679b8c4c Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Wed, 21 Jan 2026 00:10:33 +0700 Subject: [PATCH 10/10] test: fix main run --- test/integration/auth/mongodb_oidc.prose.test.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/integration/auth/mongodb_oidc.prose.test.ts b/test/integration/auth/mongodb_oidc.prose.test.ts index ad4a67f432d..66aabda7e84 100644 --- a/test/integration/auth/mongodb_oidc.prose.test.ts +++ b/test/integration/auth/mongodb_oidc.prose.test.ts @@ -75,6 +75,13 @@ const getClient = (extraOptions: MongoClientOptions = {}, callbackSpy?: OIDCCall }; describe('OIDC Auth Spec Tests', function () { + beforeEach(function () { + if (!process.env.ENVIRONMENT) { + this.skipReason = 'OIDC prose tests require a Test OIDC environment.'; + this.skip(); + } + }); + describe('Machine Authentication Flow Prose Tests', function () { const uriSingle = process.env.MONGODB_URI_SINGLE;