@@ -19,6 +19,7 @@ import {
19
19
invoke ,
20
20
PkceCodes ,
21
21
CommonAuthorizationUrlRequest ,
22
+ HttpMethod ,
22
23
} from "@azure/msal-common/browser" ;
23
24
import { StandardInteractionClient } from "./StandardInteractionClient.js" ;
24
25
import { EventType } from "../event/EventType.js" ;
@@ -48,6 +49,7 @@ import { generatePkceCodes } from "../crypto/PkceGenerator.js";
48
49
import { isPlatformAuthAllowed } from "../broker/nativeBroker/PlatformAuthProvider.js" ;
49
50
import { generateEarKey } from "../crypto/BrowserCrypto.js" ;
50
51
import { IPlatformAuthHandler } from "../broker/nativeBroker/IPlatformAuthHandler.js" ;
52
+ import { validateRequestMethod } from "../request/RequestHelpers.js" ;
51
53
52
54
export type PopupParams = {
53
55
popup ?: Window | null ;
@@ -98,12 +100,13 @@ export class PopupClient extends StandardInteractionClient {
98
100
request : PopupRequest ,
99
101
pkceCodes ?: PkceCodes
100
102
) : Promise < AuthenticationResult > {
103
+ let popupParams : PopupParams | undefined = undefined ;
101
104
try {
102
105
const popupName = this . generatePopupName (
103
106
request . scopes || OIDC_DEFAULT_SCOPES ,
104
107
request . authority || this . config . auth . authority
105
108
) ;
106
- const popupParams : PopupParams = {
109
+ popupParams = {
107
110
popupName,
108
111
popupWindowAttributes : request . popupWindowAttributes || { } ,
109
112
popupWindowParent : request . popupWindowParent ?? window ,
@@ -124,6 +127,14 @@ export class PopupClient extends StandardInteractionClient {
124
127
pkceCodes
125
128
) ;
126
129
} else {
130
+ // Pre-validate request method to avoid opening popup if the request is invalid
131
+ const validatedRequest : PopupRequest = {
132
+ ...request ,
133
+ httpMethod : validateRequestMethod (
134
+ request ,
135
+ this . config . auth . protocolMode
136
+ ) ,
137
+ } ;
127
138
// asyncPopups flag is set to false. Opens popup before acquiring token.
128
139
this . logger . verbose (
129
140
"asyncPopup set to false, opening popup before acquiring token"
@@ -133,7 +144,7 @@ export class PopupClient extends StandardInteractionClient {
133
144
popupParams
134
145
) ;
135
146
return this . acquireTokenPopupAsync (
136
- request ,
147
+ validatedRequest ,
137
148
popupParams ,
138
149
pkceCodes
139
150
) ;
@@ -286,71 +297,80 @@ export class PopupClient extends StandardInteractionClient {
286
297
account : popupRequest . account ,
287
298
} ) ;
288
299
289
- // Create acquire token url.
290
- const navigateUrl = await invokeAsync (
291
- Authorize . getAuthCodeRequestUrl ,
292
- PerformanceEvents . GetAuthCodeUrl ,
293
- this . logger ,
294
- this . performanceClient ,
295
- correlationId
296
- ) (
297
- this . config ,
298
- authClient . authority ,
299
- popupRequest ,
300
- this . logger ,
301
- this . performanceClient
302
- ) ;
300
+ if ( popupRequest . httpMethod === HttpMethod . POST ) {
301
+ return await this . executeCodeFlowWithPost (
302
+ popupRequest ,
303
+ popupParams ,
304
+ authClient ,
305
+ pkce . verifier
306
+ ) ;
307
+ } else {
308
+ // Create acquire token url.
309
+ const navigateUrl = await invokeAsync (
310
+ Authorize . getAuthCodeRequestUrl ,
311
+ PerformanceEvents . GetAuthCodeUrl ,
312
+ this . logger ,
313
+ this . performanceClient ,
314
+ correlationId
315
+ ) (
316
+ this . config ,
317
+ authClient . authority ,
318
+ popupRequest ,
319
+ this . logger ,
320
+ this . performanceClient
321
+ ) ;
303
322
304
- // Show the UI once the url has been created. Get the window handle for the popup.
305
- const popupWindow : Window = this . initiateAuthRequest (
306
- navigateUrl ,
307
- popupParams
308
- ) ;
309
- this . eventHandler . emitEvent (
310
- EventType . POPUP_OPENED ,
311
- InteractionType . Popup ,
312
- { popupWindow } ,
313
- null
314
- ) ;
323
+ // Show the UI once the url has been created. Get the window handle for the popup.
324
+ const popupWindow : Window = this . initiateAuthRequest (
325
+ navigateUrl ,
326
+ popupParams
327
+ ) ;
328
+ this . eventHandler . emitEvent (
329
+ EventType . POPUP_OPENED ,
330
+ InteractionType . Popup ,
331
+ { popupWindow } ,
332
+ null
333
+ ) ;
315
334
316
- // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
317
- const responseString = await this . monitorPopupForHash (
318
- popupWindow ,
319
- popupParams . popupWindowParent
320
- ) ;
335
+ // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
336
+ const responseString = await this . monitorPopupForHash (
337
+ popupWindow ,
338
+ popupParams . popupWindowParent
339
+ ) ;
321
340
322
- const serverParams = invoke (
323
- ResponseHandler . deserializeResponse ,
324
- PerformanceEvents . DeserializeResponse ,
325
- this . logger ,
326
- this . performanceClient ,
327
- this . correlationId
328
- ) (
329
- responseString ,
330
- this . config . auth . OIDCOptions . serverResponseType ,
331
- this . logger
332
- ) ;
341
+ const serverParams = invoke (
342
+ ResponseHandler . deserializeResponse ,
343
+ PerformanceEvents . DeserializeResponse ,
344
+ this . logger ,
345
+ this . performanceClient ,
346
+ this . correlationId
347
+ ) (
348
+ responseString ,
349
+ this . config . auth . OIDCOptions . serverResponseType ,
350
+ this . logger
351
+ ) ;
333
352
334
- return await invokeAsync (
335
- Authorize . handleResponseCode ,
336
- PerformanceEvents . HandleResponseCode ,
337
- this . logger ,
338
- this . performanceClient ,
339
- correlationId
340
- ) (
341
- request ,
342
- serverParams ,
343
- pkce . verifier ,
344
- ApiId . acquireTokenPopup ,
345
- this . config ,
346
- authClient ,
347
- this . browserStorage ,
348
- this . nativeStorage ,
349
- this . eventHandler ,
350
- this . logger ,
351
- this . performanceClient ,
352
- this . platformAuthProvider
353
- ) ;
353
+ return await invokeAsync (
354
+ Authorize . handleResponseCode ,
355
+ PerformanceEvents . HandleResponseCode ,
356
+ this . logger ,
357
+ this . performanceClient ,
358
+ correlationId
359
+ ) (
360
+ request ,
361
+ serverParams ,
362
+ pkce . verifier ,
363
+ ApiId . acquireTokenPopup ,
364
+ this . config ,
365
+ authClient ,
366
+ this . browserStorage ,
367
+ this . nativeStorage ,
368
+ this . eventHandler ,
369
+ this . logger ,
370
+ this . performanceClient ,
371
+ this . platformAuthProvider
372
+ ) ;
373
+ }
354
374
} catch ( e ) {
355
375
// Close the synchronous popup if an error is thrown before the window unload event is registered
356
376
popupParams . popup ?. close ( ) ;
@@ -452,6 +472,84 @@ export class PopupClient extends StandardInteractionClient {
452
472
) ;
453
473
}
454
474
475
+ async executeCodeFlowWithPost (
476
+ request : CommonAuthorizationUrlRequest ,
477
+ popupParams : PopupParams ,
478
+ authClient : AuthorizationCodeClient ,
479
+ pkceVerifier : string
480
+ ) : Promise < AuthenticationResult > {
481
+ const correlationId = request . correlationId ;
482
+ // Get the frame handle for the silent request
483
+ const discoveredAuthority = await invokeAsync (
484
+ this . getDiscoveredAuthority . bind ( this ) ,
485
+ PerformanceEvents . StandardInteractionClientGetDiscoveredAuthority ,
486
+ this . logger ,
487
+ this . performanceClient ,
488
+ correlationId
489
+ ) ( {
490
+ requestAuthority : request . authority ,
491
+ requestAzureCloudOptions : request . azureCloudOptions ,
492
+ requestExtraQueryParameters : request . extraQueryParameters ,
493
+ account : request . account ,
494
+ } ) ;
495
+
496
+ const popupWindow =
497
+ popupParams . popup || this . openPopup ( "about:blank" , popupParams ) ;
498
+
499
+ const form = await Authorize . getCodeForm (
500
+ popupWindow . document ,
501
+ this . config ,
502
+ discoveredAuthority ,
503
+ request ,
504
+ this . logger ,
505
+ this . performanceClient
506
+ ) ;
507
+
508
+ form . submit ( ) ;
509
+
510
+ // Monitor the popup for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
511
+ const responseString = await invokeAsync (
512
+ this . monitorPopupForHash . bind ( this ) ,
513
+ PerformanceEvents . SilentHandlerMonitorIframeForHash ,
514
+ this . logger ,
515
+ this . performanceClient ,
516
+ correlationId
517
+ ) ( popupWindow , popupParams . popupWindowParent ) ;
518
+
519
+ const serverParams = invoke (
520
+ ResponseHandler . deserializeResponse ,
521
+ PerformanceEvents . DeserializeResponse ,
522
+ this . logger ,
523
+ this . performanceClient ,
524
+ this . correlationId
525
+ ) (
526
+ responseString ,
527
+ this . config . auth . OIDCOptions . serverResponseType ,
528
+ this . logger
529
+ ) ;
530
+
531
+ return invokeAsync (
532
+ Authorize . handleResponseCode ,
533
+ PerformanceEvents . HandleResponseCode ,
534
+ this . logger ,
535
+ this . performanceClient ,
536
+ correlationId
537
+ ) (
538
+ request ,
539
+ serverParams ,
540
+ pkceVerifier ,
541
+ ApiId . acquireTokenPopup ,
542
+ this . config ,
543
+ authClient ,
544
+ this . browserStorage ,
545
+ this . nativeStorage ,
546
+ this . eventHandler ,
547
+ this . logger ,
548
+ this . performanceClient ,
549
+ this . platformAuthProvider
550
+ ) ;
551
+ }
552
+
455
553
/**
456
554
*
457
555
* @param validRequest
0 commit comments