@@ -77,6 +77,19 @@ async function delay(ms: number) {
7777 return await new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
7878}
7979
80+ function testAuthCodeFlow (
81+ fn : ( opts : Partial < MongoDBOIDCPluginOptions > ) => Mocha . Func
82+ ) : void {
83+ for ( const skipNonceInAuthCodeRequest of [ true , false ] ) {
84+ describe ( `with skipNonceInAuthCodeRequest: ${ skipNonceInAuthCodeRequest . toString ( ) } ` , function ( ) {
85+ it (
86+ 'can successfully authenticate with auth code flow' ,
87+ fn ( { skipNonceInAuthCodeRequest } )
88+ ) ;
89+ } ) ;
90+ }
91+ }
92+
8093describe ( 'OIDC plugin (local OIDC provider)' , function ( ) {
8194 this . timeout ( 90_000 ) ;
8295
@@ -138,18 +151,42 @@ describe('OIDC plugin (local OIDC provider)', function () {
138151 plugin = createMongoDBOIDCPlugin ( pluginOptions ) ;
139152 } ) ;
140153
141- it ( 'can request tokens through the browser' , async function ( ) {
142- const result = await requestToken (
143- plugin ,
144- provider . getMongodbOIDCDBInfo ( )
145- ) ;
146- const accessTokenContents = getJWTContents ( result . accessToken ) ;
147- expect ( accessTokenContents . sub ) . to . equal ( 'testuser' ) ;
148- expect ( accessTokenContents . client_id ) . to . equal (
149- provider . getMongodbOIDCDBInfo ( ) . clientId
150- ) ;
151- verifySuccessfulAuthCodeFlowLog ( await readLog ( ) ) ;
152- } ) ;
154+ testAuthCodeFlow (
155+ ( opts ) =>
156+ async function ( ) {
157+ pluginOptions = {
158+ ...pluginOptions ,
159+ ...opts ,
160+ } ;
161+ plugin = createMongoDBOIDCPlugin ( pluginOptions ) ;
162+ let idToken : string | undefined ;
163+ plugin . logger . once ( 'mongodb-oidc-plugin:auth-succeeded' , ( event ) => {
164+ idToken = event . tokens . idToken ;
165+ } ) ;
166+
167+ const result = await requestToken (
168+ plugin ,
169+ provider . getMongodbOIDCDBInfo ( )
170+ ) ;
171+ const accessTokenContents = getJWTContents ( result . accessToken ) ;
172+ expect ( accessTokenContents . sub ) . to . equal ( 'testuser' ) ;
173+ expect ( accessTokenContents . client_id ) . to . equal (
174+ provider . getMongodbOIDCDBInfo ( ) . clientId
175+ ) ;
176+
177+ verifySuccessfulAuthCodeFlowLog ( await readLog ( ) ) ;
178+
179+ expect ( idToken ) . to . not . be . undefined ;
180+
181+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- we know it's non-null from the above check
182+ const idTokenContents = getJWTContents ( idToken ! ) ;
183+ if ( opts . skipNonceInAuthCodeRequest ) {
184+ expect ( idTokenContents . nonce ) . to . be . undefined ;
185+ } else {
186+ expect ( idTokenContents . nonce ) . to . not . be . undefined ;
187+ }
188+ }
189+ ) ;
153190
154191 it ( 'will re-use tokens while they are valid if no username was provided' , async function ( ) {
155192 const skipAuthAttemptEvent = once (
@@ -1017,18 +1054,22 @@ describe('OIDC plugin (local OIDC provider)', function () {
10171054 } ;
10181055 } ) ;
10191056
1020- it ( 'can successfully authenticate with Okta using auth code flow' , async function ( ) {
1021- plugin = createMongoDBOIDCPlugin ( {
1022- ...defaultOpts ,
1023- allowedFlows : [ 'auth-code' ] ,
1024- openBrowser : ( opts ) =>
1025- oktaBrowserAuthCodeFlow ( { ...opts , username, password } ) ,
1026- } ) ;
1027- const result = await requestToken ( plugin , metadata ) ;
1057+ testAuthCodeFlow (
1058+ ( opts ) =>
1059+ async function ( ) {
1060+ plugin = createMongoDBOIDCPlugin ( {
1061+ ...defaultOpts ,
1062+ allowedFlows : [ 'auth-code' ] ,
1063+ openBrowser : ( opts ) =>
1064+ oktaBrowserAuthCodeFlow ( { ...opts , username, password } ) ,
1065+ ...opts ,
1066+ } ) ;
1067+ const result = await requestToken ( plugin , metadata ) ;
10281068
1029- validateToken ( getJWTContents ( result . accessToken ) ) ;
1030- verifySuccessfulAuthCodeFlowLog ( await readLog ( ) ) ;
1031- } ) ;
1069+ validateToken ( getJWTContents ( result . accessToken ) ) ;
1070+ verifySuccessfulAuthCodeFlowLog ( await readLog ( ) ) ;
1071+ }
1072+ ) ;
10321073
10331074 it ( 'can successfully authenticate with Okta using device auth flow' , async function ( ) {
10341075 plugin = createMongoDBOIDCPlugin ( {
@@ -1087,18 +1128,22 @@ describe('OIDC plugin (local OIDC provider)', function () {
10871128 } ;
10881129 } ) ;
10891130
1090- it ( 'can successfully authenticate with Azure using auth code flow' , async function ( ) {
1091- plugin = createMongoDBOIDCPlugin ( {
1092- ...defaultOpts ,
1093- allowedFlows : [ 'auth-code' ] ,
1094- openBrowser : ( opts ) =>
1095- azureBrowserAuthCodeFlow ( { ...opts , username, password } ) ,
1096- } ) ;
1097- const result = await requestToken ( plugin , metadata ) ;
1131+ testAuthCodeFlow (
1132+ ( opts ) =>
1133+ async function ( ) {
1134+ plugin = createMongoDBOIDCPlugin ( {
1135+ ...defaultOpts ,
1136+ allowedFlows : [ 'auth-code' ] ,
1137+ openBrowser : ( opts ) =>
1138+ azureBrowserAuthCodeFlow ( { ...opts , username, password } ) ,
1139+ ...opts ,
1140+ } ) ;
1141+ const result = await requestToken ( plugin , metadata ) ;
10981142
1099- validateToken ( getJWTContents ( result . accessToken ) ) ;
1100- verifySuccessfulAuthCodeFlowLog ( await readLog ( ) ) ;
1101- } ) ;
1143+ validateToken ( getJWTContents ( result . accessToken ) ) ;
1144+ verifySuccessfulAuthCodeFlowLog ( await readLog ( ) ) ;
1145+ }
1146+ ) ;
11021147
11031148 it ( 'can successfully authenticate with Azure using device auth flow' , async function ( ) {
11041149 plugin = createMongoDBOIDCPlugin ( {
0 commit comments