@azure/msal-browser 3.20.0 → 3.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/dist/app/IPublicClientApplication.d.ts +53 -53
  2. package/dist/app/IPublicClientApplication.mjs +105 -105
  3. package/dist/app/PublicClientApplication.d.ts +293 -293
  4. package/dist/app/PublicClientApplication.mjs +364 -364
  5. package/dist/app/PublicClientNext.d.ts +276 -276
  6. package/dist/app/PublicClientNext.mjs +354 -354
  7. package/dist/broker/nativeBroker/NativeMessageHandler.d.ts +62 -62
  8. package/dist/broker/nativeBroker/NativeMessageHandler.mjs +254 -254
  9. package/dist/broker/nativeBroker/NativeRequest.d.ts +45 -45
  10. package/dist/broker/nativeBroker/NativeResponse.d.ts +48 -48
  11. package/dist/broker/nativeBroker/NativeStatusCodes.d.ts +7 -7
  12. package/dist/broker/nativeBroker/NativeStatusCodes.mjs +11 -11
  13. package/dist/cache/AccountManager.d.ts +48 -48
  14. package/dist/cache/AccountManager.mjs +126 -126
  15. package/dist/cache/AsyncMemoryStorage.d.ts +50 -50
  16. package/dist/cache/AsyncMemoryStorage.mjs +131 -131
  17. package/dist/cache/BrowserCacheManager.d.ts +385 -385
  18. package/dist/cache/BrowserCacheManager.mjs +1294 -1294
  19. package/dist/cache/BrowserStorage.d.ts +11 -11
  20. package/dist/cache/BrowserStorage.mjs +32 -32
  21. package/dist/cache/DatabaseStorage.d.ts +56 -56
  22. package/dist/cache/DatabaseStorage.mjs +200 -200
  23. package/dist/cache/IAsyncStorage.d.ts +27 -27
  24. package/dist/cache/ITokenCache.d.ts +11 -11
  25. package/dist/cache/IWindowStorage.d.ts +27 -27
  26. package/dist/cache/MemoryStorage.d.ts +11 -11
  27. package/dist/cache/MemoryStorage.mjs +31 -31
  28. package/dist/cache/TokenCache.d.ts +77 -77
  29. package/dist/cache/TokenCache.mjs +195 -195
  30. package/dist/config/Configuration.d.ts +213 -208
  31. package/dist/config/Configuration.d.ts.map +1 -1
  32. package/dist/config/Configuration.mjs +128 -128
  33. package/dist/config/Configuration.mjs.map +1 -1
  34. package/dist/controllers/ControllerFactory.d.ts +5 -5
  35. package/dist/controllers/ControllerFactory.mjs +25 -25
  36. package/dist/controllers/IController.d.ts +60 -60
  37. package/dist/controllers/NestedAppAuthController.d.ts +202 -202
  38. package/dist/controllers/NestedAppAuthController.mjs +473 -473
  39. package/dist/controllers/StandardController.d.ts +405 -405
  40. package/dist/controllers/StandardController.d.ts.map +1 -1
  41. package/dist/controllers/StandardController.mjs +1334 -1316
  42. package/dist/controllers/StandardController.mjs.map +1 -1
  43. package/dist/controllers/UnknownOperatingContextController.d.ts +86 -86
  44. package/dist/controllers/UnknownOperatingContextController.mjs +256 -256
  45. package/dist/crypto/BrowserCrypto.d.ts +52 -52
  46. package/dist/crypto/BrowserCrypto.mjs +151 -151
  47. package/dist/crypto/CryptoOps.d.ts +74 -74
  48. package/dist/crypto/CryptoOps.mjs +176 -176
  49. package/dist/crypto/PkceGenerator.d.ts +8 -8
  50. package/dist/crypto/PkceGenerator.mjs +54 -54
  51. package/dist/crypto/SignedHttpRequest.d.ts +30 -30
  52. package/dist/crypto/SignedHttpRequest.mjs +39 -39
  53. package/dist/encode/Base64Decode.d.ts +9 -9
  54. package/dist/encode/Base64Decode.mjs +36 -36
  55. package/dist/encode/Base64Encode.d.ts +19 -19
  56. package/dist/encode/Base64Encode.mjs +43 -43
  57. package/dist/error/BrowserAuthError.d.ts +255 -255
  58. package/dist/error/BrowserAuthError.mjs +263 -263
  59. package/dist/error/BrowserAuthErrorCodes.d.ts +46 -46
  60. package/dist/error/BrowserAuthErrorCodes.mjs +50 -50
  61. package/dist/error/BrowserConfigurationAuthError.d.ts +33 -33
  62. package/dist/error/BrowserConfigurationAuthError.mjs +40 -40
  63. package/dist/error/BrowserConfigurationAuthError.mjs.map +1 -1
  64. package/dist/error/BrowserConfigurationAuthErrorCodes.d.ts +3 -3
  65. package/dist/error/BrowserConfigurationAuthErrorCodes.mjs +7 -7
  66. package/dist/error/NativeAuthError.d.ts +29 -29
  67. package/dist/error/NativeAuthError.mjs +60 -60
  68. package/dist/error/NativeAuthErrorCodes.d.ts +2 -2
  69. package/dist/error/NativeAuthErrorCodes.mjs +6 -6
  70. package/dist/error/NestedAppAuthError.d.ts +14 -14
  71. package/dist/error/NestedAppAuthError.mjs +23 -23
  72. package/dist/event/EventHandler.d.ts +41 -41
  73. package/dist/event/EventHandler.mjs +125 -125
  74. package/dist/event/EventMessage.d.ts +25 -25
  75. package/dist/event/EventMessage.mjs +68 -68
  76. package/dist/event/EventType.d.ts +29 -29
  77. package/dist/event/EventType.mjs +32 -32
  78. package/dist/index.d.ts +40 -40
  79. package/dist/index.mjs +1 -1
  80. package/dist/interaction_client/BaseInteractionClient.d.ts +50 -50
  81. package/dist/interaction_client/BaseInteractionClient.mjs +106 -106
  82. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.d.ts +4 -4
  83. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs +10 -10
  84. package/dist/interaction_client/NativeInteractionClient.d.ts +151 -151
  85. package/dist/interaction_client/NativeInteractionClient.mjs +621 -621
  86. package/dist/interaction_client/PopupClient.d.ts +105 -105
  87. package/dist/interaction_client/PopupClient.d.ts.map +1 -1
  88. package/dist/interaction_client/PopupClient.mjs +433 -433
  89. package/dist/interaction_client/PopupClient.mjs.map +1 -1
  90. package/dist/interaction_client/RedirectClient.d.ts +50 -50
  91. package/dist/interaction_client/RedirectClient.d.ts.map +1 -1
  92. package/dist/interaction_client/RedirectClient.mjs +315 -314
  93. package/dist/interaction_client/RedirectClient.mjs.map +1 -1
  94. package/dist/interaction_client/SilentAuthCodeClient.d.ts +23 -23
  95. package/dist/interaction_client/SilentAuthCodeClient.mjs +57 -57
  96. package/dist/interaction_client/SilentCacheClient.d.ts +16 -16
  97. package/dist/interaction_client/SilentCacheClient.mjs +42 -42
  98. package/dist/interaction_client/SilentIframeClient.d.ts +32 -32
  99. package/dist/interaction_client/SilentIframeClient.d.ts.map +1 -1
  100. package/dist/interaction_client/SilentIframeClient.mjs +110 -100
  101. package/dist/interaction_client/SilentIframeClient.mjs.map +1 -1
  102. package/dist/interaction_client/SilentRefreshClient.d.ts +20 -20
  103. package/dist/interaction_client/SilentRefreshClient.mjs +47 -47
  104. package/dist/interaction_client/StandardInteractionClient.d.ts +48 -48
  105. package/dist/interaction_client/StandardInteractionClient.mjs +199 -199
  106. package/dist/interaction_handler/InteractionHandler.d.ts +33 -33
  107. package/dist/interaction_handler/InteractionHandler.mjs +93 -93
  108. package/dist/interaction_handler/RedirectHandler.d.ts +32 -32
  109. package/dist/interaction_handler/RedirectHandler.mjs +134 -134
  110. package/dist/interaction_handler/SilentHandler.d.ts +13 -13
  111. package/dist/interaction_handler/SilentHandler.mjs +134 -134
  112. package/dist/naa/AccountInfo.d.ts +11 -11
  113. package/dist/naa/AuthBridge.d.ts +8 -8
  114. package/dist/naa/AuthResult.d.ts +6 -6
  115. package/dist/naa/BridgeAccountContext.d.ts +12 -12
  116. package/dist/naa/BridgeCapabilities.d.ts +3 -3
  117. package/dist/naa/BridgeError.d.ts +9 -9
  118. package/dist/naa/BridgeError.mjs +7 -7
  119. package/dist/naa/BridgeProxy.d.ts +67 -67
  120. package/dist/naa/BridgeProxy.mjs +148 -148
  121. package/dist/naa/BridgeRequest.d.ts +7 -7
  122. package/dist/naa/BridgeRequestEnvelope.d.ts +12 -12
  123. package/dist/naa/BridgeResponseEnvelope.d.ts +13 -13
  124. package/dist/naa/BridgeStatusCode.d.ts +11 -11
  125. package/dist/naa/BridgeStatusCode.mjs +14 -14
  126. package/dist/naa/IBridgeProxy.d.ts +10 -10
  127. package/dist/naa/InitContext.d.ts +8 -8
  128. package/dist/naa/TokenRequest.d.ts +18 -18
  129. package/dist/naa/TokenResponse.d.ts +13 -13
  130. package/dist/naa/mapping/NestedAppAuthAdapter.d.ts +35 -35
  131. package/dist/naa/mapping/NestedAppAuthAdapter.mjs +179 -179
  132. package/dist/navigation/INavigationClient.d.ts +16 -16
  133. package/dist/navigation/NavigationClient.d.ts +22 -22
  134. package/dist/navigation/NavigationClient.mjs +40 -40
  135. package/dist/navigation/NavigationOptions.d.ts +12 -12
  136. package/dist/network/FetchClient.d.ts +26 -26
  137. package/dist/network/FetchClient.mjs +99 -99
  138. package/dist/operatingcontext/BaseOperatingContext.d.ts +41 -41
  139. package/dist/operatingcontext/BaseOperatingContext.mjs +94 -94
  140. package/dist/operatingcontext/NestedAppOperatingContext.d.ts +34 -34
  141. package/dist/operatingcontext/NestedAppOperatingContext.mjs +71 -71
  142. package/dist/operatingcontext/StandardOperatingContext.d.ts +25 -25
  143. package/dist/operatingcontext/StandardOperatingContext.mjs +43 -43
  144. package/dist/operatingcontext/UnknownOperatingContext.d.ts +25 -25
  145. package/dist/operatingcontext/UnknownOperatingContext.mjs +42 -42
  146. package/dist/packageMetadata.d.ts +2 -2
  147. package/dist/packageMetadata.mjs +4 -4
  148. package/dist/request/AuthorizationCodeRequest.d.ts +8 -8
  149. package/dist/request/AuthorizationUrlRequest.d.ts +8 -8
  150. package/dist/request/ClearCacheRequest.d.ts +10 -10
  151. package/dist/request/EndSessionPopupRequest.d.ts +18 -18
  152. package/dist/request/EndSessionRequest.d.ts +15 -15
  153. package/dist/request/InitializeApplicationRequest.d.ts +8 -8
  154. package/dist/request/PopupRequest.d.ts +34 -34
  155. package/dist/request/PopupWindowAttributes.d.ts +15 -15
  156. package/dist/request/RedirectRequest.d.ts +40 -35
  157. package/dist/request/RedirectRequest.d.ts.map +1 -1
  158. package/dist/request/RequestHelpers.d.ts +13 -13
  159. package/dist/request/RequestHelpers.mjs +53 -53
  160. package/dist/request/SilentRequest.d.ts +33 -33
  161. package/dist/request/SsoSilentRequest.d.ts +29 -29
  162. package/dist/response/AuthenticationResult.d.ts +4 -4
  163. package/dist/response/ResponseHandler.d.ts +7 -7
  164. package/dist/response/ResponseHandler.mjs +36 -36
  165. package/dist/telemetry/BrowserPerformanceClient.d.ts +34 -34
  166. package/dist/telemetry/BrowserPerformanceClient.mjs +162 -162
  167. package/dist/telemetry/BrowserPerformanceMeasurement.d.ts +21 -21
  168. package/dist/telemetry/BrowserPerformanceMeasurement.mjs +92 -92
  169. package/dist/utils/BrowserConstants.d.ts +180 -180
  170. package/dist/utils/BrowserConstants.mjs +212 -212
  171. package/dist/utils/BrowserProtocolUtils.d.ts +11 -11
  172. package/dist/utils/BrowserProtocolUtils.mjs +21 -21
  173. package/dist/utils/BrowserUtils.d.ts +75 -75
  174. package/dist/utils/BrowserUtils.mjs +157 -157
  175. package/lib/msal-browser.cjs +18884 -18855
  176. package/lib/msal-browser.cjs.map +1 -1
  177. package/lib/msal-browser.js +18884 -18855
  178. package/lib/msal-browser.js.map +1 -1
  179. package/lib/msal-browser.min.js +59 -59
  180. package/package.json +2 -2
  181. package/src/config/Configuration.ts +9 -1
  182. package/src/controllers/StandardController.ts +30 -12
  183. package/src/interaction_client/PopupClient.ts +1 -0
  184. package/src/interaction_client/RedirectClient.ts +4 -1
  185. package/src/interaction_client/SilentIframeClient.ts +40 -3
  186. package/src/packageMetadata.ts +1 -1
  187. package/src/request/RedirectRequest.ts +5 -0
@@ -1,4 +1,4 @@
1
- /*! @azure/msal-browser v3.20.0 2024-07-23 */
1
+ /*! @azure/msal-browser v3.22.0 2024-08-28 */
2
2
  'use strict';
3
3
  import { OIDC_DEFAULT_SCOPES, invokeAsync, PerformanceEvents, invoke, ThrottlingUtils, ProtocolUtils, AuthError, ProtocolMode, UrlString, ServerResponseType } from '@azure/msal-common';
4
4
  import { StandardInteractionClient } from './StandardInteractionClient.mjs';
@@ -12,438 +12,438 @@ import { InteractionHandler } from '../interaction_handler/InteractionHandler.mj
12
12
  import { deserializeResponse } from '../response/ResponseHandler.mjs';
13
13
  import { nativeConnectionNotEstablished, emptyNavigateUri, userCancelled, emptyWindowError, popupWindowError } from '../error/BrowserAuthErrorCodes.mjs';
14
14
 
15
- /*
16
- * Copyright (c) Microsoft Corporation. All rights reserved.
17
- * Licensed under the MIT License.
18
- */
19
- class PopupClient extends StandardInteractionClient {
20
- constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeStorageImpl, nativeMessageHandler, correlationId) {
21
- super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeMessageHandler, correlationId);
22
- // Properly sets this reference for the unload event.
23
- this.unloadWindow = this.unloadWindow.bind(this);
24
- this.nativeStorage = nativeStorageImpl;
25
- }
26
- /**
27
- * Acquires tokens by opening a popup window to the /authorize endpoint of the authority
28
- * @param request
29
- */
30
- acquireToken(request) {
31
- try {
32
- const popupName = this.generatePopupName(request.scopes || OIDC_DEFAULT_SCOPES, request.authority || this.config.auth.authority);
33
- const popupWindowAttributes = request.popupWindowAttributes || {};
34
- // asyncPopups flag is true. Acquires token without first opening popup. Popup will be opened later asynchronously.
35
- if (this.config.system.asyncPopups) {
36
- this.logger.verbose("asyncPopups set to true, acquiring token");
37
- // Passes on popup position and dimensions if in request
38
- return this.acquireTokenPopupAsync(request, popupName, popupWindowAttributes);
39
- }
40
- else {
41
- // asyncPopups flag is set to false. Opens popup before acquiring token.
42
- this.logger.verbose("asyncPopup set to false, opening popup before acquiring token");
43
- const popup = this.openSizedPopup("about:blank", popupName, popupWindowAttributes);
44
- return this.acquireTokenPopupAsync(request, popupName, popupWindowAttributes, popup);
45
- }
46
- }
47
- catch (e) {
48
- return Promise.reject(e);
49
- }
50
- }
51
- /**
52
- * Clears local cache for the current user then opens a popup window prompting the user to sign-out of the server
53
- * @param logoutRequest
54
- */
55
- logout(logoutRequest) {
56
- try {
57
- this.logger.verbose("logoutPopup called");
58
- const validLogoutRequest = this.initializeLogoutRequest(logoutRequest);
59
- const popupName = this.generateLogoutPopupName(validLogoutRequest);
60
- const authority = logoutRequest && logoutRequest.authority;
61
- const mainWindowRedirectUri = logoutRequest && logoutRequest.mainWindowRedirectUri;
62
- const popupWindowAttributes = logoutRequest?.popupWindowAttributes || {};
63
- // asyncPopups flag is true. Acquires token without first opening popup. Popup will be opened later asynchronously.
64
- if (this.config.system.asyncPopups) {
65
- this.logger.verbose("asyncPopups set to true");
66
- // Passes on popup position and dimensions if in request
67
- return this.logoutPopupAsync(validLogoutRequest, popupName, popupWindowAttributes, authority, undefined, mainWindowRedirectUri);
68
- }
69
- else {
70
- // asyncPopups flag is set to false. Opens popup before logging out.
71
- this.logger.verbose("asyncPopup set to false, opening popup");
72
- const popup = this.openSizedPopup("about:blank", popupName, popupWindowAttributes);
73
- return this.logoutPopupAsync(validLogoutRequest, popupName, popupWindowAttributes, authority, popup, mainWindowRedirectUri);
74
- }
75
- }
76
- catch (e) {
77
- // Since this function is synchronous we need to reject
78
- return Promise.reject(e);
79
- }
80
- }
81
- /**
82
- * Helper which obtains an access_token for your API via opening a popup window in the user's browser
83
- * @param validRequest
84
- * @param popupName
85
- * @param popup
86
- * @param popupWindowAttributes
87
- *
88
- * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.
89
- */
90
- async acquireTokenPopupAsync(request, popupName, popupWindowAttributes, popup) {
91
- this.logger.verbose("acquireTokenPopupAsync called");
92
- const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenPopup);
93
- const validRequest = await invokeAsync(this.initializeAuthorizationRequest.bind(this), PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest, this.logger, this.performanceClient, this.correlationId)(request, InteractionType.Popup);
94
- preconnect(validRequest.authority);
95
- try {
96
- // Create auth code request and generate PKCE params
97
- const authCodeRequest = await invokeAsync(this.initializeAuthorizationCodeRequest.bind(this), PerformanceEvents.StandardInteractionClientInitializeAuthorizationCodeRequest, this.logger, this.performanceClient, this.correlationId)(validRequest);
98
- // Initialize the client
99
- const authClient = await invokeAsync(this.createAuthCodeClient.bind(this), PerformanceEvents.StandardInteractionClientCreateAuthCodeClient, this.logger, this.performanceClient, this.correlationId)(serverTelemetryManager, validRequest.authority, validRequest.azureCloudOptions, validRequest.account);
100
- const isNativeBroker = NativeMessageHandler.isNativeAvailable(this.config, this.logger, this.nativeMessageHandler, request.authenticationScheme);
101
- // Start measurement for server calls with native brokering enabled
102
- let fetchNativeAccountIdMeasurement;
103
- if (isNativeBroker) {
104
- fetchNativeAccountIdMeasurement =
105
- this.performanceClient.startMeasurement(PerformanceEvents.FetchAccountIdWithNativeBroker, request.correlationId);
106
- }
107
- // Create acquire token url.
108
- const navigateUrl = await authClient.getAuthCodeUrl({
109
- ...validRequest,
110
- nativeBroker: isNativeBroker,
111
- });
112
- // Create popup interaction handler.
113
- const interactionHandler = new InteractionHandler(authClient, this.browserStorage, authCodeRequest, this.logger, this.performanceClient);
114
- // Show the UI once the url has been created. Get the window handle for the popup.
115
- const popupParameters = {
116
- popup,
117
- popupName,
118
- popupWindowAttributes,
119
- };
120
- const popupWindow = this.initiateAuthRequest(navigateUrl, popupParameters);
121
- this.eventHandler.emitEvent(EventType.POPUP_OPENED, InteractionType.Popup, { popupWindow }, null);
122
- // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
123
- const responseString = await this.monitorPopupForHash(popupWindow);
124
- const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, this.correlationId)(responseString, this.config.auth.OIDCOptions.serverResponseType, this.logger);
125
- // Remove throttle if it exists
126
- ThrottlingUtils.removeThrottle(this.browserStorage, this.config.auth.clientId, authCodeRequest);
127
- if (serverParams.accountId) {
128
- this.logger.verbose("Account id found in hash, calling WAM for token");
129
- // end measurement for server call with native brokering enabled
130
- if (fetchNativeAccountIdMeasurement) {
131
- fetchNativeAccountIdMeasurement.end({
132
- success: true,
133
- isNativeBroker: true,
134
- });
135
- }
136
- if (!this.nativeMessageHandler) {
137
- throw createBrowserAuthError(nativeConnectionNotEstablished);
138
- }
139
- const nativeInteractionClient = new NativeInteractionClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.acquireTokenPopup, this.performanceClient, this.nativeMessageHandler, serverParams.accountId, this.nativeStorage, validRequest.correlationId);
140
- const { userRequestState } = ProtocolUtils.parseRequestState(this.browserCrypto, validRequest.state);
141
- return await nativeInteractionClient.acquireToken({
142
- ...validRequest,
143
- state: userRequestState,
144
- prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently
145
- });
146
- }
147
- // Handle response from hash string.
148
- const result = await interactionHandler.handleCodeResponse(serverParams, validRequest);
149
- return result;
150
- }
151
- catch (e) {
152
- if (popup) {
153
- // Close the synchronous popup if an error is thrown before the window unload event is registered
154
- popup.close();
155
- }
156
- if (e instanceof AuthError) {
157
- e.setCorrelationId(this.correlationId);
158
- serverTelemetryManager.cacheFailedRequest(e);
159
- }
160
- throw e;
161
- }
162
- }
163
- /**
164
- *
165
- * @param validRequest
166
- * @param popupName
167
- * @param requestAuthority
168
- * @param popup
169
- * @param mainWindowRedirectUri
170
- * @param popupWindowAttributes
171
- */
172
- async logoutPopupAsync(validRequest, popupName, popupWindowAttributes, requestAuthority, popup, mainWindowRedirectUri) {
173
- this.logger.verbose("logoutPopupAsync called");
174
- this.eventHandler.emitEvent(EventType.LOGOUT_START, InteractionType.Popup, validRequest);
175
- const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.logoutPopup);
176
- try {
177
- // Clear cache on logout
178
- await this.clearCacheOnLogout(validRequest.account);
179
- // Initialize the client
180
- const authClient = await invokeAsync(this.createAuthCodeClient.bind(this), PerformanceEvents.StandardInteractionClientCreateAuthCodeClient, this.logger, this.performanceClient, this.correlationId)(serverTelemetryManager, requestAuthority, undefined, // AzureCloudOptions
181
- validRequest.account || undefined);
182
- try {
183
- authClient.authority.endSessionEndpoint;
184
- }
185
- catch {
186
- if (validRequest.account?.homeAccountId &&
187
- validRequest.postLogoutRedirectUri &&
188
- authClient.authority.protocolMode === ProtocolMode.OIDC) {
189
- void this.browserStorage.removeAccount(validRequest.account?.homeAccountId);
190
- this.eventHandler.emitEvent(EventType.LOGOUT_SUCCESS, InteractionType.Popup, validRequest);
191
- if (mainWindowRedirectUri) {
192
- const navigationOptions = {
193
- apiId: ApiId.logoutPopup,
194
- timeout: this.config.system.redirectNavigationTimeout,
195
- noHistory: false,
196
- };
197
- const absoluteUrl = UrlString.getAbsoluteUrl(mainWindowRedirectUri, getCurrentUri());
198
- await this.navigationClient.navigateInternal(absoluteUrl, navigationOptions);
199
- }
200
- if (popup) {
201
- popup.close();
202
- }
203
- return;
204
- }
205
- }
206
- // Create logout string and navigate user window to logout.
207
- const logoutUri = authClient.getLogoutUri(validRequest);
208
- this.eventHandler.emitEvent(EventType.LOGOUT_SUCCESS, InteractionType.Popup, validRequest);
209
- // Open the popup window to requestUrl.
210
- const popupWindow = this.openPopup(logoutUri, {
211
- popupName,
212
- popupWindowAttributes,
213
- popup,
214
- });
215
- this.eventHandler.emitEvent(EventType.POPUP_OPENED, InteractionType.Popup, { popupWindow }, null);
216
- await this.monitorPopupForHash(popupWindow).catch(() => {
217
- // Swallow any errors related to monitoring the window. Server logout is best effort
218
- });
219
- if (mainWindowRedirectUri) {
220
- const navigationOptions = {
221
- apiId: ApiId.logoutPopup,
222
- timeout: this.config.system.redirectNavigationTimeout,
223
- noHistory: false,
224
- };
225
- const absoluteUrl = UrlString.getAbsoluteUrl(mainWindowRedirectUri, getCurrentUri());
226
- this.logger.verbose("Redirecting main window to url specified in the request");
227
- this.logger.verbosePii(`Redirecting main window to: ${absoluteUrl}`);
228
- await this.navigationClient.navigateInternal(absoluteUrl, navigationOptions);
229
- }
230
- else {
231
- this.logger.verbose("No main window navigation requested");
232
- }
233
- }
234
- catch (e) {
235
- if (popup) {
236
- // Close the synchronous popup if an error is thrown before the window unload event is registered
237
- popup.close();
238
- }
239
- if (e instanceof AuthError) {
240
- e.setCorrelationId(this.correlationId);
241
- serverTelemetryManager.cacheFailedRequest(e);
242
- }
243
- this.browserStorage.setInteractionInProgress(false);
244
- this.eventHandler.emitEvent(EventType.LOGOUT_FAILURE, InteractionType.Popup, null, e);
245
- this.eventHandler.emitEvent(EventType.LOGOUT_END, InteractionType.Popup);
246
- throw e;
247
- }
248
- this.eventHandler.emitEvent(EventType.LOGOUT_END, InteractionType.Popup);
249
- }
250
- /**
251
- * Opens a popup window with given request Url.
252
- * @param requestUrl
253
- */
254
- initiateAuthRequest(requestUrl, params) {
255
- // Check that request url is not empty.
256
- if (requestUrl) {
257
- this.logger.infoPii(`Navigate to: ${requestUrl}`);
258
- // Open the popup window to requestUrl.
259
- return this.openPopup(requestUrl, params);
260
- }
261
- else {
262
- // Throw error if request URL is empty.
263
- this.logger.error("Navigate url is empty");
264
- throw createBrowserAuthError(emptyNavigateUri);
265
- }
266
- }
267
- /**
268
- * Monitors a window until it loads a url with the same origin.
269
- * @param popupWindow - window that is being monitored
270
- * @param timeout - timeout for processing hash once popup is redirected back to application
271
- */
272
- monitorPopupForHash(popupWindow) {
273
- return new Promise((resolve, reject) => {
274
- this.logger.verbose("PopupHandler.monitorPopupForHash - polling started");
275
- const intervalId = setInterval(() => {
276
- // Window is closed
277
- if (popupWindow.closed) {
278
- this.logger.error("PopupHandler.monitorPopupForHash - window closed");
279
- clearInterval(intervalId);
280
- reject(createBrowserAuthError(userCancelled));
281
- return;
282
- }
283
- let href = "";
284
- try {
285
- /*
286
- * Will throw if cross origin,
287
- * which should be caught and ignored
288
- * since we need the interval to keep running while on STS UI.
289
- */
290
- href = popupWindow.location.href;
291
- }
292
- catch (e) { }
293
- // Don't process blank pages or cross domain
294
- if (!href || href === "about:blank") {
295
- return;
296
- }
297
- clearInterval(intervalId);
298
- let responseString = "";
299
- const responseType = this.config.auth.OIDCOptions.serverResponseType;
300
- if (popupWindow) {
301
- if (responseType === ServerResponseType.QUERY) {
302
- responseString = popupWindow.location.search;
303
- }
304
- else {
305
- responseString = popupWindow.location.hash;
306
- }
307
- }
308
- this.logger.verbose("PopupHandler.monitorPopupForHash - popup window is on same origin as caller");
309
- resolve(responseString);
310
- }, this.config.system.pollIntervalMilliseconds);
311
- }).finally(() => {
312
- this.cleanPopup(popupWindow);
313
- });
314
- }
315
- /**
316
- * @hidden
317
- *
318
- * Configures popup window for login.
319
- *
320
- * @param urlNavigate
321
- * @param title
322
- * @param popUpWidth
323
- * @param popUpHeight
324
- * @param popupWindowAttributes
325
- * @ignore
326
- * @hidden
327
- */
328
- openPopup(urlNavigate, popupParams) {
329
- try {
330
- let popupWindow;
331
- // Popup window passed in, setting url to navigate to
332
- if (popupParams.popup) {
333
- popupWindow = popupParams.popup;
334
- this.logger.verbosePii(`Navigating popup window to: ${urlNavigate}`);
335
- popupWindow.location.assign(urlNavigate);
336
- }
337
- else if (typeof popupParams.popup === "undefined") {
338
- // Popup will be undefined if it was not passed in
339
- this.logger.verbosePii(`Opening popup window to: ${urlNavigate}`);
340
- popupWindow = this.openSizedPopup(urlNavigate, popupParams.popupName, popupParams.popupWindowAttributes);
341
- }
342
- // Popup will be null if popups are blocked
343
- if (!popupWindow) {
344
- throw createBrowserAuthError(emptyWindowError);
345
- }
346
- if (popupWindow.focus) {
347
- popupWindow.focus();
348
- }
349
- this.currentWindow = popupWindow;
350
- window.addEventListener("beforeunload", this.unloadWindow);
351
- return popupWindow;
352
- }
353
- catch (e) {
354
- this.logger.error("error opening popup " + e.message);
355
- this.browserStorage.setInteractionInProgress(false);
356
- throw createBrowserAuthError(popupWindowError);
357
- }
358
- }
359
- /**
360
- * Helper function to set popup window dimensions and position
361
- * @param urlNavigate
362
- * @param popupName
363
- * @param popupWindowAttributes
364
- * @returns
365
- */
366
- openSizedPopup(urlNavigate, popupName, popupWindowAttributes) {
367
- /**
368
- * adding winLeft and winTop to account for dual monitor
369
- * using screenLeft and screenTop for IE8 and earlier
370
- */
371
- const winLeft = window.screenLeft ? window.screenLeft : window.screenX;
372
- const winTop = window.screenTop ? window.screenTop : window.screenY;
373
- /**
374
- * window.innerWidth displays browser window"s height and width excluding toolbars
375
- * using document.documentElement.clientWidth for IE8 and earlier
376
- */
377
- const winWidth = window.innerWidth ||
378
- document.documentElement.clientWidth ||
379
- document.body.clientWidth;
380
- const winHeight = window.innerHeight ||
381
- document.documentElement.clientHeight ||
382
- document.body.clientHeight;
383
- let width = popupWindowAttributes.popupSize?.width;
384
- let height = popupWindowAttributes.popupSize?.height;
385
- let top = popupWindowAttributes.popupPosition?.top;
386
- let left = popupWindowAttributes.popupPosition?.left;
387
- if (!width || width < 0 || width > winWidth) {
388
- this.logger.verbose("Default popup window width used. Window width not configured or invalid.");
389
- width = BrowserConstants.POPUP_WIDTH;
390
- }
391
- if (!height || height < 0 || height > winHeight) {
392
- this.logger.verbose("Default popup window height used. Window height not configured or invalid.");
393
- height = BrowserConstants.POPUP_HEIGHT;
394
- }
395
- if (!top || top < 0 || top > winHeight) {
396
- this.logger.verbose("Default popup window top position used. Window top not configured or invalid.");
397
- top = Math.max(0, winHeight / 2 - BrowserConstants.POPUP_HEIGHT / 2 + winTop);
398
- }
399
- if (!left || left < 0 || left > winWidth) {
400
- this.logger.verbose("Default popup window left position used. Window left not configured or invalid.");
401
- left = Math.max(0, winWidth / 2 - BrowserConstants.POPUP_WIDTH / 2 + winLeft);
402
- }
403
- return window.open(urlNavigate, popupName, `width=${width}, height=${height}, top=${top}, left=${left}, scrollbars=yes`);
404
- }
405
- /**
406
- * Event callback to unload main window.
407
- */
408
- unloadWindow(e) {
409
- this.browserStorage.cleanRequestByInteractionType(InteractionType.Popup);
410
- if (this.currentWindow) {
411
- this.currentWindow.close();
412
- }
413
- // Guarantees browser unload will happen, so no other errors will be thrown.
414
- e.preventDefault();
415
- }
416
- /**
417
- * Closes popup, removes any state vars created during popup calls.
418
- * @param popupWindow
419
- */
420
- cleanPopup(popupWindow) {
421
- if (popupWindow) {
422
- // Close window.
423
- popupWindow.close();
424
- }
425
- // Remove window unload function
426
- window.removeEventListener("beforeunload", this.unloadWindow);
427
- // Interaction is completed - remove interaction status.
428
- this.browserStorage.setInteractionInProgress(false);
429
- }
430
- /**
431
- * Generates the name for the popup based on the client id and request
432
- * @param clientId
433
- * @param request
434
- */
435
- generatePopupName(scopes, authority) {
436
- return `${BrowserConstants.POPUP_NAME_PREFIX}.${this.config.auth.clientId}.${scopes.join("-")}.${authority}.${this.correlationId}`;
437
- }
438
- /**
439
- * Generates the name for the popup based on the client id and request for logouts
440
- * @param clientId
441
- * @param request
442
- */
443
- generateLogoutPopupName(request) {
444
- const homeAccountId = request.account && request.account.homeAccountId;
445
- return `${BrowserConstants.POPUP_NAME_PREFIX}.${this.config.auth.clientId}.${homeAccountId}.${this.correlationId}`;
446
- }
15
+ /*
16
+ * Copyright (c) Microsoft Corporation. All rights reserved.
17
+ * Licensed under the MIT License.
18
+ */
19
+ class PopupClient extends StandardInteractionClient {
20
+ constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeStorageImpl, nativeMessageHandler, correlationId) {
21
+ super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeMessageHandler, correlationId);
22
+ // Properly sets this reference for the unload event.
23
+ this.unloadWindow = this.unloadWindow.bind(this);
24
+ this.nativeStorage = nativeStorageImpl;
25
+ }
26
+ /**
27
+ * Acquires tokens by opening a popup window to the /authorize endpoint of the authority
28
+ * @param request
29
+ */
30
+ acquireToken(request) {
31
+ try {
32
+ const popupName = this.generatePopupName(request.scopes || OIDC_DEFAULT_SCOPES, request.authority || this.config.auth.authority);
33
+ const popupWindowAttributes = request.popupWindowAttributes || {};
34
+ // asyncPopups flag is true. Acquires token without first opening popup. Popup will be opened later asynchronously.
35
+ if (this.config.system.asyncPopups) {
36
+ this.logger.verbose("asyncPopups set to true, acquiring token");
37
+ // Passes on popup position and dimensions if in request
38
+ return this.acquireTokenPopupAsync(request, popupName, popupWindowAttributes);
39
+ }
40
+ else {
41
+ // asyncPopups flag is set to false. Opens popup before acquiring token.
42
+ this.logger.verbose("asyncPopup set to false, opening popup before acquiring token");
43
+ const popup = this.openSizedPopup("about:blank", popupName, popupWindowAttributes);
44
+ return this.acquireTokenPopupAsync(request, popupName, popupWindowAttributes, popup);
45
+ }
46
+ }
47
+ catch (e) {
48
+ return Promise.reject(e);
49
+ }
50
+ }
51
+ /**
52
+ * Clears local cache for the current user then opens a popup window prompting the user to sign-out of the server
53
+ * @param logoutRequest
54
+ */
55
+ logout(logoutRequest) {
56
+ try {
57
+ this.logger.verbose("logoutPopup called");
58
+ const validLogoutRequest = this.initializeLogoutRequest(logoutRequest);
59
+ const popupName = this.generateLogoutPopupName(validLogoutRequest);
60
+ const authority = logoutRequest && logoutRequest.authority;
61
+ const mainWindowRedirectUri = logoutRequest && logoutRequest.mainWindowRedirectUri;
62
+ const popupWindowAttributes = logoutRequest?.popupWindowAttributes || {};
63
+ // asyncPopups flag is true. Acquires token without first opening popup. Popup will be opened later asynchronously.
64
+ if (this.config.system.asyncPopups) {
65
+ this.logger.verbose("asyncPopups set to true");
66
+ // Passes on popup position and dimensions if in request
67
+ return this.logoutPopupAsync(validLogoutRequest, popupName, popupWindowAttributes, authority, undefined, mainWindowRedirectUri);
68
+ }
69
+ else {
70
+ // asyncPopups flag is set to false. Opens popup before logging out.
71
+ this.logger.verbose("asyncPopup set to false, opening popup");
72
+ const popup = this.openSizedPopup("about:blank", popupName, popupWindowAttributes);
73
+ return this.logoutPopupAsync(validLogoutRequest, popupName, popupWindowAttributes, authority, popup, mainWindowRedirectUri);
74
+ }
75
+ }
76
+ catch (e) {
77
+ // Since this function is synchronous we need to reject
78
+ return Promise.reject(e);
79
+ }
80
+ }
81
+ /**
82
+ * Helper which obtains an access_token for your API via opening a popup window in the user's browser
83
+ * @param validRequest
84
+ * @param popupName
85
+ * @param popup
86
+ * @param popupWindowAttributes
87
+ *
88
+ * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.
89
+ */
90
+ async acquireTokenPopupAsync(request, popupName, popupWindowAttributes, popup) {
91
+ this.logger.verbose("acquireTokenPopupAsync called");
92
+ const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenPopup);
93
+ const validRequest = await invokeAsync(this.initializeAuthorizationRequest.bind(this), PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest, this.logger, this.performanceClient, this.correlationId)(request, InteractionType.Popup);
94
+ preconnect(validRequest.authority);
95
+ try {
96
+ // Create auth code request and generate PKCE params
97
+ const authCodeRequest = await invokeAsync(this.initializeAuthorizationCodeRequest.bind(this), PerformanceEvents.StandardInteractionClientInitializeAuthorizationCodeRequest, this.logger, this.performanceClient, this.correlationId)(validRequest);
98
+ // Initialize the client
99
+ const authClient = await invokeAsync(this.createAuthCodeClient.bind(this), PerformanceEvents.StandardInteractionClientCreateAuthCodeClient, this.logger, this.performanceClient, this.correlationId)(serverTelemetryManager, validRequest.authority, validRequest.azureCloudOptions, validRequest.account);
100
+ const isNativeBroker = NativeMessageHandler.isNativeAvailable(this.config, this.logger, this.nativeMessageHandler, request.authenticationScheme);
101
+ // Start measurement for server calls with native brokering enabled
102
+ let fetchNativeAccountIdMeasurement;
103
+ if (isNativeBroker) {
104
+ fetchNativeAccountIdMeasurement =
105
+ this.performanceClient.startMeasurement(PerformanceEvents.FetchAccountIdWithNativeBroker, request.correlationId);
106
+ }
107
+ // Create acquire token url.
108
+ const navigateUrl = await authClient.getAuthCodeUrl({
109
+ ...validRequest,
110
+ nativeBroker: isNativeBroker,
111
+ });
112
+ // Create popup interaction handler.
113
+ const interactionHandler = new InteractionHandler(authClient, this.browserStorage, authCodeRequest, this.logger, this.performanceClient);
114
+ // Show the UI once the url has been created. Get the window handle for the popup.
115
+ const popupParameters = {
116
+ popup,
117
+ popupName,
118
+ popupWindowAttributes,
119
+ };
120
+ const popupWindow = this.initiateAuthRequest(navigateUrl, popupParameters);
121
+ this.eventHandler.emitEvent(EventType.POPUP_OPENED, InteractionType.Popup, { popupWindow }, null);
122
+ // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
123
+ const responseString = await this.monitorPopupForHash(popupWindow);
124
+ const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, this.correlationId)(responseString, this.config.auth.OIDCOptions.serverResponseType, this.logger);
125
+ // Remove throttle if it exists
126
+ ThrottlingUtils.removeThrottle(this.browserStorage, this.config.auth.clientId, authCodeRequest);
127
+ if (serverParams.accountId) {
128
+ this.logger.verbose("Account id found in hash, calling WAM for token");
129
+ // end measurement for server call with native brokering enabled
130
+ if (fetchNativeAccountIdMeasurement) {
131
+ fetchNativeAccountIdMeasurement.end({
132
+ success: true,
133
+ isNativeBroker: true,
134
+ });
135
+ }
136
+ if (!this.nativeMessageHandler) {
137
+ throw createBrowserAuthError(nativeConnectionNotEstablished);
138
+ }
139
+ const nativeInteractionClient = new NativeInteractionClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.acquireTokenPopup, this.performanceClient, this.nativeMessageHandler, serverParams.accountId, this.nativeStorage, validRequest.correlationId);
140
+ const { userRequestState } = ProtocolUtils.parseRequestState(this.browserCrypto, validRequest.state);
141
+ return await nativeInteractionClient.acquireToken({
142
+ ...validRequest,
143
+ state: userRequestState,
144
+ prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently
145
+ });
146
+ }
147
+ // Handle response from hash string.
148
+ const result = await interactionHandler.handleCodeResponse(serverParams, validRequest);
149
+ return result;
150
+ }
151
+ catch (e) {
152
+ if (popup) {
153
+ // Close the synchronous popup if an error is thrown before the window unload event is registered
154
+ popup.close();
155
+ }
156
+ if (e instanceof AuthError) {
157
+ e.setCorrelationId(this.correlationId);
158
+ serverTelemetryManager.cacheFailedRequest(e);
159
+ }
160
+ throw e;
161
+ }
162
+ }
163
+ /**
164
+ *
165
+ * @param validRequest
166
+ * @param popupName
167
+ * @param requestAuthority
168
+ * @param popup
169
+ * @param mainWindowRedirectUri
170
+ * @param popupWindowAttributes
171
+ */
172
+ async logoutPopupAsync(validRequest, popupName, popupWindowAttributes, requestAuthority, popup, mainWindowRedirectUri) {
173
+ this.logger.verbose("logoutPopupAsync called");
174
+ this.eventHandler.emitEvent(EventType.LOGOUT_START, InteractionType.Popup, validRequest);
175
+ const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.logoutPopup);
176
+ try {
177
+ // Clear cache on logout
178
+ await this.clearCacheOnLogout(validRequest.account);
179
+ // Initialize the client
180
+ const authClient = await invokeAsync(this.createAuthCodeClient.bind(this), PerformanceEvents.StandardInteractionClientCreateAuthCodeClient, this.logger, this.performanceClient, this.correlationId)(serverTelemetryManager, requestAuthority, undefined, // AzureCloudOptions
181
+ validRequest.account || undefined);
182
+ try {
183
+ authClient.authority.endSessionEndpoint;
184
+ }
185
+ catch {
186
+ if (validRequest.account?.homeAccountId &&
187
+ validRequest.postLogoutRedirectUri &&
188
+ authClient.authority.protocolMode === ProtocolMode.OIDC) {
189
+ void this.browserStorage.removeAccount(validRequest.account?.homeAccountId);
190
+ this.eventHandler.emitEvent(EventType.LOGOUT_SUCCESS, InteractionType.Popup, validRequest);
191
+ if (mainWindowRedirectUri) {
192
+ const navigationOptions = {
193
+ apiId: ApiId.logoutPopup,
194
+ timeout: this.config.system.redirectNavigationTimeout,
195
+ noHistory: false,
196
+ };
197
+ const absoluteUrl = UrlString.getAbsoluteUrl(mainWindowRedirectUri, getCurrentUri());
198
+ await this.navigationClient.navigateInternal(absoluteUrl, navigationOptions);
199
+ }
200
+ if (popup) {
201
+ popup.close();
202
+ }
203
+ return;
204
+ }
205
+ }
206
+ // Create logout string and navigate user window to logout.
207
+ const logoutUri = authClient.getLogoutUri(validRequest);
208
+ this.eventHandler.emitEvent(EventType.LOGOUT_SUCCESS, InteractionType.Popup, validRequest);
209
+ // Open the popup window to requestUrl.
210
+ const popupWindow = this.openPopup(logoutUri, {
211
+ popupName,
212
+ popupWindowAttributes,
213
+ popup,
214
+ });
215
+ this.eventHandler.emitEvent(EventType.POPUP_OPENED, InteractionType.Popup, { popupWindow }, null);
216
+ await this.monitorPopupForHash(popupWindow).catch(() => {
217
+ // Swallow any errors related to monitoring the window. Server logout is best effort
218
+ });
219
+ if (mainWindowRedirectUri) {
220
+ const navigationOptions = {
221
+ apiId: ApiId.logoutPopup,
222
+ timeout: this.config.system.redirectNavigationTimeout,
223
+ noHistory: false,
224
+ };
225
+ const absoluteUrl = UrlString.getAbsoluteUrl(mainWindowRedirectUri, getCurrentUri());
226
+ this.logger.verbose("Redirecting main window to url specified in the request");
227
+ this.logger.verbosePii(`Redirecting main window to: ${absoluteUrl}`);
228
+ await this.navigationClient.navigateInternal(absoluteUrl, navigationOptions);
229
+ }
230
+ else {
231
+ this.logger.verbose("No main window navigation requested");
232
+ }
233
+ }
234
+ catch (e) {
235
+ if (popup) {
236
+ // Close the synchronous popup if an error is thrown before the window unload event is registered
237
+ popup.close();
238
+ }
239
+ if (e instanceof AuthError) {
240
+ e.setCorrelationId(this.correlationId);
241
+ serverTelemetryManager.cacheFailedRequest(e);
242
+ }
243
+ this.browserStorage.setInteractionInProgress(false);
244
+ this.eventHandler.emitEvent(EventType.LOGOUT_FAILURE, InteractionType.Popup, null, e);
245
+ this.eventHandler.emitEvent(EventType.LOGOUT_END, InteractionType.Popup);
246
+ throw e;
247
+ }
248
+ this.eventHandler.emitEvent(EventType.LOGOUT_END, InteractionType.Popup);
249
+ }
250
+ /**
251
+ * Opens a popup window with given request Url.
252
+ * @param requestUrl
253
+ */
254
+ initiateAuthRequest(requestUrl, params) {
255
+ // Check that request url is not empty.
256
+ if (requestUrl) {
257
+ this.logger.infoPii(`Navigate to: ${requestUrl}`);
258
+ // Open the popup window to requestUrl.
259
+ return this.openPopup(requestUrl, params);
260
+ }
261
+ else {
262
+ // Throw error if request URL is empty.
263
+ this.logger.error("Navigate url is empty");
264
+ throw createBrowserAuthError(emptyNavigateUri);
265
+ }
266
+ }
267
+ /**
268
+ * Monitors a window until it loads a url with the same origin.
269
+ * @param popupWindow - window that is being monitored
270
+ * @param timeout - timeout for processing hash once popup is redirected back to application
271
+ */
272
+ monitorPopupForHash(popupWindow) {
273
+ return new Promise((resolve, reject) => {
274
+ this.logger.verbose("PopupHandler.monitorPopupForHash - polling started");
275
+ const intervalId = setInterval(() => {
276
+ // Window is closed
277
+ if (popupWindow.closed) {
278
+ this.logger.error("PopupHandler.monitorPopupForHash - window closed");
279
+ clearInterval(intervalId);
280
+ reject(createBrowserAuthError(userCancelled));
281
+ return;
282
+ }
283
+ let href = "";
284
+ try {
285
+ /*
286
+ * Will throw if cross origin,
287
+ * which should be caught and ignored
288
+ * since we need the interval to keep running while on STS UI.
289
+ */
290
+ href = popupWindow.location.href;
291
+ }
292
+ catch (e) { }
293
+ // Don't process blank pages or cross domain
294
+ if (!href || href === "about:blank") {
295
+ return;
296
+ }
297
+ clearInterval(intervalId);
298
+ let responseString = "";
299
+ const responseType = this.config.auth.OIDCOptions.serverResponseType;
300
+ if (popupWindow) {
301
+ if (responseType === ServerResponseType.QUERY) {
302
+ responseString = popupWindow.location.search;
303
+ }
304
+ else {
305
+ responseString = popupWindow.location.hash;
306
+ }
307
+ }
308
+ this.logger.verbose("PopupHandler.monitorPopupForHash - popup window is on same origin as caller");
309
+ resolve(responseString);
310
+ }, this.config.system.pollIntervalMilliseconds);
311
+ }).finally(() => {
312
+ this.cleanPopup(popupWindow);
313
+ });
314
+ }
315
+ /**
316
+ * @hidden
317
+ *
318
+ * Configures popup window for login.
319
+ *
320
+ * @param urlNavigate
321
+ * @param title
322
+ * @param popUpWidth
323
+ * @param popUpHeight
324
+ * @param popupWindowAttributes
325
+ * @ignore
326
+ * @hidden
327
+ */
328
+ openPopup(urlNavigate, popupParams) {
329
+ try {
330
+ let popupWindow;
331
+ // Popup window passed in, setting url to navigate to
332
+ if (popupParams.popup) {
333
+ popupWindow = popupParams.popup;
334
+ this.logger.verbosePii(`Navigating popup window to: ${urlNavigate}`);
335
+ popupWindow.location.assign(urlNavigate);
336
+ }
337
+ else if (typeof popupParams.popup === "undefined") {
338
+ // Popup will be undefined if it was not passed in
339
+ this.logger.verbosePii(`Opening popup window to: ${urlNavigate}`);
340
+ popupWindow = this.openSizedPopup(urlNavigate, popupParams.popupName, popupParams.popupWindowAttributes);
341
+ }
342
+ // Popup will be null if popups are blocked
343
+ if (!popupWindow) {
344
+ throw createBrowserAuthError(emptyWindowError);
345
+ }
346
+ if (popupWindow.focus) {
347
+ popupWindow.focus();
348
+ }
349
+ this.currentWindow = popupWindow;
350
+ window.addEventListener("beforeunload", this.unloadWindow);
351
+ return popupWindow;
352
+ }
353
+ catch (e) {
354
+ this.logger.error("error opening popup " + e.message);
355
+ this.browserStorage.setInteractionInProgress(false);
356
+ throw createBrowserAuthError(popupWindowError);
357
+ }
358
+ }
359
+ /**
360
+ * Helper function to set popup window dimensions and position
361
+ * @param urlNavigate
362
+ * @param popupName
363
+ * @param popupWindowAttributes
364
+ * @returns
365
+ */
366
+ openSizedPopup(urlNavigate, popupName, popupWindowAttributes) {
367
+ /**
368
+ * adding winLeft and winTop to account for dual monitor
369
+ * using screenLeft and screenTop for IE8 and earlier
370
+ */
371
+ const winLeft = window.screenLeft ? window.screenLeft : window.screenX;
372
+ const winTop = window.screenTop ? window.screenTop : window.screenY;
373
+ /**
374
+ * window.innerWidth displays browser window"s height and width excluding toolbars
375
+ * using document.documentElement.clientWidth for IE8 and earlier
376
+ */
377
+ const winWidth = window.innerWidth ||
378
+ document.documentElement.clientWidth ||
379
+ document.body.clientWidth;
380
+ const winHeight = window.innerHeight ||
381
+ document.documentElement.clientHeight ||
382
+ document.body.clientHeight;
383
+ let width = popupWindowAttributes.popupSize?.width;
384
+ let height = popupWindowAttributes.popupSize?.height;
385
+ let top = popupWindowAttributes.popupPosition?.top;
386
+ let left = popupWindowAttributes.popupPosition?.left;
387
+ if (!width || width < 0 || width > winWidth) {
388
+ this.logger.verbose("Default popup window width used. Window width not configured or invalid.");
389
+ width = BrowserConstants.POPUP_WIDTH;
390
+ }
391
+ if (!height || height < 0 || height > winHeight) {
392
+ this.logger.verbose("Default popup window height used. Window height not configured or invalid.");
393
+ height = BrowserConstants.POPUP_HEIGHT;
394
+ }
395
+ if (!top || top < 0 || top > winHeight) {
396
+ this.logger.verbose("Default popup window top position used. Window top not configured or invalid.");
397
+ top = Math.max(0, winHeight / 2 - BrowserConstants.POPUP_HEIGHT / 2 + winTop);
398
+ }
399
+ if (!left || left < 0 || left > winWidth) {
400
+ this.logger.verbose("Default popup window left position used. Window left not configured or invalid.");
401
+ left = Math.max(0, winWidth / 2 - BrowserConstants.POPUP_WIDTH / 2 + winLeft);
402
+ }
403
+ return window.open(urlNavigate, popupName, `width=${width}, height=${height}, top=${top}, left=${left}, scrollbars=yes`);
404
+ }
405
+ /**
406
+ * Event callback to unload main window.
407
+ */
408
+ unloadWindow(e) {
409
+ this.browserStorage.cleanRequestByInteractionType(InteractionType.Popup);
410
+ if (this.currentWindow) {
411
+ this.currentWindow.close();
412
+ }
413
+ // Guarantees browser unload will happen, so no other errors will be thrown.
414
+ e.preventDefault();
415
+ }
416
+ /**
417
+ * Closes popup, removes any state vars created during popup calls.
418
+ * @param popupWindow
419
+ */
420
+ cleanPopup(popupWindow) {
421
+ if (popupWindow) {
422
+ // Close window.
423
+ popupWindow.close();
424
+ }
425
+ // Remove window unload function
426
+ window.removeEventListener("beforeunload", this.unloadWindow);
427
+ // Interaction is completed - remove interaction status.
428
+ this.browserStorage.setInteractionInProgress(false);
429
+ }
430
+ /**
431
+ * Generates the name for the popup based on the client id and request
432
+ * @param clientId
433
+ * @param request
434
+ */
435
+ generatePopupName(scopes, authority) {
436
+ return `${BrowserConstants.POPUP_NAME_PREFIX}.${this.config.auth.clientId}.${scopes.join("-")}.${authority}.${this.correlationId}`;
437
+ }
438
+ /**
439
+ * Generates the name for the popup based on the client id and request for logouts
440
+ * @param clientId
441
+ * @param request
442
+ */
443
+ generateLogoutPopupName(request) {
444
+ const homeAccountId = request.account && request.account.homeAccountId;
445
+ return `${BrowserConstants.POPUP_NAME_PREFIX}.${this.config.auth.clientId}.${homeAccountId}.${this.correlationId}`;
446
+ }
447
447
  }
448
448
 
449
449
  export { PopupClient };