@@ -16,16 +16,18 @@ import {
1616 CONNECTION_READY
1717} from '../constants' ;
1818import {
19+ MONGODB_ERROR_CODES ,
1920 MongoError ,
2021 MongoInvalidArgumentError ,
22+ MongoMissingCredentialsError ,
2123 MongoNetworkError ,
2224 MongoRuntimeError ,
2325 MongoServerError
2426} from '../error' ;
2527import { CancellationToken , TypedEventEmitter } from '../mongo_types' ;
2628import type { Server } from '../sdam/server' ;
2729import { Callback , eachAsync , List , makeCounter } from '../utils' ;
28- import { connect } from './connect' ;
30+ import { AUTH_PROVIDERS , connect } from './connect' ;
2931import { Connection , ConnectionEvents , ConnectionOptions } from './connection' ;
3032import {
3133 ConnectionCheckedInEvent ,
@@ -544,7 +546,17 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
544546 fn ( undefined , conn , ( fnErr , result ) => {
545547 if ( typeof callback === 'function' ) {
546548 if ( fnErr ) {
547- callback ( fnErr ) ;
549+ if ( ( fnErr as MongoError ) . code === MONGODB_ERROR_CODES . Reauthenticate ) {
550+ this . reauthenticate ( conn , fn , ( error , res ) => {
551+ if ( error ) {
552+ callback ( error ) ;
553+ } else {
554+ callback ( undefined , res ) ;
555+ }
556+ } ) ;
557+ } else {
558+ callback ( fnErr ) ;
559+ }
548560 } else {
549561 callback ( undefined , result ) ;
550562 }
@@ -559,7 +571,17 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
559571 fn ( err as MongoError , conn , ( fnErr , result ) => {
560572 if ( typeof callback === 'function' ) {
561573 if ( fnErr ) {
562- callback ( fnErr ) ;
574+ if ( conn && ( fnErr as MongoError ) . code === MONGODB_ERROR_CODES . Reauthenticate ) {
575+ this . reauthenticate ( conn , fn , ( error , res ) => {
576+ if ( error ) {
577+ callback ( error ) ;
578+ } else {
579+ callback ( undefined , res ) ;
580+ }
581+ } ) ;
582+ } else {
583+ callback ( fnErr ) ;
584+ }
563585 } else {
564586 callback ( undefined , result ) ;
565587 }
@@ -572,6 +594,50 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
572594 } ) ;
573595 }
574596
597+ /**
598+ * Reauthenticate on the same connection and then retry the operation.
599+ */
600+ private reauthenticate (
601+ connection : Connection ,
602+ fn : WithConnectionCallback ,
603+ callback : Callback
604+ ) : void {
605+ const authContext = connection . authContext ;
606+ if ( ! authContext ) {
607+ return callback ( new MongoRuntimeError ( 'No auth context found on connection.' ) ) ;
608+ }
609+ authContext . reauthenticating = true ;
610+ const credentials = authContext . credentials ;
611+ if ( ! credentials ) {
612+ return callback (
613+ new MongoMissingCredentialsError (
614+ 'Connection is missing credentials when asked to reauthenticate'
615+ )
616+ ) ;
617+ }
618+ const resolvedCredentials = credentials . resolveAuthMechanism ( connection . hello || undefined ) ;
619+ const provider = AUTH_PROVIDERS . get ( resolvedCredentials . mechanism ) ;
620+ if ( ! provider ) {
621+ return callback (
622+ new MongoMissingCredentialsError (
623+ `Reauthenticate failed due to no auth provider for ${ credentials . mechanism } `
624+ )
625+ ) ;
626+ }
627+ provider . auth ( authContext , error => {
628+ authContext . reauthenticating = false ;
629+ if ( error ) {
630+ return callback ( error ) ;
631+ }
632+ return fn ( undefined , connection , ( fnErr , fnResult ) => {
633+ if ( fnErr ) {
634+ return callback ( fnErr ) ;
635+ }
636+ callback ( undefined , fnResult ) ;
637+ } ) ;
638+ } ) ;
639+ }
640+
575641 /** Clear the min pool size timer */
576642 private clearMinPoolSizeTimer ( ) : void {
577643 const minPoolSizeTimer = this [ kMinPoolSizeTimer ] ;
0 commit comments