@@ -19,6 +19,7 @@ import {
1919 invoke ,
2020 PkceCodes ,
2121 CommonAuthorizationUrlRequest ,
22+ HttpMethod ,
2223} from "@azure/msal-common/browser" ;
2324import { StandardInteractionClient } from "./StandardInteractionClient.js" ;
2425import { EventType } from "../event/EventType.js" ;
@@ -48,6 +49,7 @@ import { generatePkceCodes } from "../crypto/PkceGenerator.js";
4849import { isPlatformAuthAllowed } from "../broker/nativeBroker/PlatformAuthProvider.js" ;
4950import { generateEarKey } from "../crypto/BrowserCrypto.js" ;
5051import { IPlatformAuthHandler } from "../broker/nativeBroker/IPlatformAuthHandler.js" ;
52+ import { validateRequestMethod } from "../request/RequestHelpers.js" ;
5153
5254export type PopupParams = {
5355 popup ?: Window | null ;
@@ -98,12 +100,13 @@ export class PopupClient extends StandardInteractionClient {
98100 request : PopupRequest ,
99101 pkceCodes ?: PkceCodes
100102 ) : Promise < AuthenticationResult > {
103+ let popupParams : PopupParams | undefined = undefined ;
101104 try {
102105 const popupName = this . generatePopupName (
103106 request . scopes || OIDC_DEFAULT_SCOPES ,
104107 request . authority || this . config . auth . authority
105108 ) ;
106- const popupParams : PopupParams = {
109+ popupParams = {
107110 popupName,
108111 popupWindowAttributes : request . popupWindowAttributes || { } ,
109112 popupWindowParent : request . popupWindowParent ?? window ,
@@ -124,6 +127,14 @@ export class PopupClient extends StandardInteractionClient {
124127 pkceCodes
125128 ) ;
126129 } 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+ } ;
127138 // asyncPopups flag is set to false. Opens popup before acquiring token.
128139 this . logger . verbose (
129140 "asyncPopup set to false, opening popup before acquiring token"
@@ -133,7 +144,7 @@ export class PopupClient extends StandardInteractionClient {
133144 popupParams
134145 ) ;
135146 return this . acquireTokenPopupAsync (
136- request ,
147+ validatedRequest ,
137148 popupParams ,
138149 pkceCodes
139150 ) ;
@@ -286,71 +297,80 @@ export class PopupClient extends StandardInteractionClient {
286297 account : popupRequest . account ,
287298 } ) ;
288299
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+ ) ;
303322
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+ ) ;
315334
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+ ) ;
321340
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+ ) ;
333352
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+ }
354374 } catch ( e ) {
355375 // Close the synchronous popup if an error is thrown before the window unload event is registered
356376 popupParams . popup ?. close ( ) ;
@@ -452,6 +472,84 @@ export class PopupClient extends StandardInteractionClient {
452472 ) ;
453473 }
454474
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+
455553 /**
456554 *
457555 * @param validRequest
0 commit comments