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