@@ -6,8 +6,13 @@ import { promisify } from 'util';
66import { MongoCredentials } from '../../src/cmap/auth/mongo_credentials' ;
77import { AUTH_MECHS_AUTH_SRC_EXTERNAL , AuthMechanism } from '../../src/cmap/auth/providers' ;
88import { parseOptions , resolveSRVRecord } from '../../src/connection_string' ;
9- import { MongoDriverError , MongoInvalidArgumentError , MongoParseError } from '../../src/error' ;
10- import { MongoOptions } from '../../src/mongo_client' ;
9+ import {
10+ MongoAPIError ,
11+ MongoDriverError ,
12+ MongoInvalidArgumentError ,
13+ MongoParseError
14+ } from '../../src/error' ;
15+ import { MongoClient , MongoOptions } from '../../src/mongo_client' ;
1116
1217describe ( 'Connection String' , function ( ) {
1318 it ( 'should not support auth passed with user' , function ( ) {
@@ -89,6 +94,37 @@ describe('Connection String', function () {
8994 expect ( options . credentials . source ) . to . equal ( '$external' ) ;
9095 } ) ;
9196
97+ it ( 'should omit credentials option when the only authSource is provided' , function ( ) {
98+ let options = parseOptions ( `mongodb://a/?authSource=someDb` ) ;
99+ expect ( options ) . to . not . have . property ( 'credentials' ) ;
100+ options = parseOptions ( `mongodb+srv://a/?authSource=someDb` ) ;
101+ expect ( options ) . to . not . have . property ( 'credentials' ) ;
102+ } ) ;
103+
104+ it ( 'should omit credentials and not throw a MongoAPIError if the only auth related option is authSource' , async ( ) => {
105+ // The error we're looking to **not** see is
106+ // `new MongoInvalidArgumentError('No AuthProvider for ${credentials.mechanism} defined.')`
107+ // in `prepareHandshakeDocument` and/or `performInitialHandshake`.
108+ // Neither function is exported currently but if I did export them because of the inlined callbacks
109+ // I think I would need to mock quite a bit of internals to get down to that layer.
110+ // My thinking is I can lean on server selection failing for th unit tests to assert we at least don't get an error related to auth.
111+ const client = new MongoClient ( 'mongodb://localhost:123/?authSource=someDb' , {
112+ serverSelectionTimeoutMS : 500
113+ } ) ;
114+
115+ let thrownError : Error ;
116+ try {
117+ // relies on us not running a mongod on port 123, fairly likely assumption
118+ await client . connect ( ) ;
119+ } catch ( error ) {
120+ thrownError = error ;
121+ }
122+
123+ // We should fail to connect, not fail to find an auth provider thus we should not find a MongoAPIError
124+ expect ( thrownError ) . to . not . be . instanceOf ( MongoAPIError ) ;
125+ expect ( client . options ) . to . not . have . a . property ( 'credentials' ) ;
126+ } ) ;
127+
92128 it ( 'should parse a numeric authSource with variable width' , function ( ) {
93129 const options = parseOptions ( 'mongodb://test@localhost/?authSource=0001' ) ;
94130 expect ( options . credentials . source ) . to . equal ( '0001' ) ;
@@ -334,5 +370,21 @@ describe('Connection String', function () {
334370 expect ( options ) . property ( 'credentials' ) . to . equal ( credentials ) ;
335371 expect ( options ) . to . have . nested . property ( 'credentials.source' , 'admin' ) ;
336372 } ) ;
373+
374+ it ( 'should retain specified authSource with no provided credentials' , async function ( ) {
375+ makeStub ( 'authSource=thisShouldBeAuthSource' ) ;
376+ const credentials = { } ;
377+ const options = {
378+ credentials,
379+ srvHost : 'test.mock.test.build.10gen.cc' ,
380+ srvServiceName : 'mongodb' ,
381+ userSpecifiedAuthSource : false
382+ } as MongoOptions ;
383+
384+ await resolveSRVRecordAsync ( options as any ) ;
385+ expect ( options ) . to . have . nested . property ( 'credentials.username' , '' ) ;
386+ expect ( options ) . to . have . nested . property ( 'credentials.mechanism' , 'DEFAULT' ) ;
387+ expect ( options ) . to . have . nested . property ( 'credentials.source' , 'thisShouldBeAuthSource' ) ;
388+ } ) ;
337389 } ) ;
338390} ) ;
0 commit comments