@azure/msal-browser 3.0.2 → 3.1.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 (256) hide show
  1. package/dist/app/IPublicClientApplication.d.ts +2 -0
  2. package/dist/app/IPublicClientApplication.d.ts.map +1 -1
  3. package/dist/app/IPublicClientApplication.mjs +4 -1
  4. package/dist/app/IPublicClientApplication.mjs.map +1 -1
  5. package/dist/app/PublicClientApplication.d.ts +6 -0
  6. package/dist/app/PublicClientApplication.d.ts.map +1 -1
  7. package/dist/app/PublicClientApplication.mjs +8 -1
  8. package/dist/app/PublicClientApplication.mjs.map +1 -1
  9. package/dist/broker/nativeBroker/NativeMessageHandler.d.ts.map +1 -1
  10. package/dist/broker/nativeBroker/NativeMessageHandler.mjs +5 -4
  11. package/dist/broker/nativeBroker/NativeMessageHandler.mjs.map +1 -1
  12. package/dist/cache/AsyncMemoryStorage.mjs +4 -3
  13. package/dist/cache/AsyncMemoryStorage.mjs.map +1 -1
  14. package/dist/cache/BrowserCacheManager.d.ts +9 -2
  15. package/dist/cache/BrowserCacheManager.d.ts.map +1 -1
  16. package/dist/cache/BrowserCacheManager.mjs +54 -26
  17. package/dist/cache/BrowserCacheManager.mjs.map +1 -1
  18. package/dist/cache/BrowserStorage.mjs +1 -1
  19. package/dist/cache/BrowserStorage.mjs.map +1 -1
  20. package/dist/cache/CryptoKeyStore.mjs +1 -1
  21. package/dist/cache/CryptoKeyStore.mjs.map +1 -1
  22. package/dist/cache/DatabaseStorage.d.ts.map +1 -1
  23. package/dist/cache/DatabaseStorage.mjs +9 -8
  24. package/dist/cache/DatabaseStorage.mjs.map +1 -1
  25. package/dist/cache/MemoryStorage.mjs +1 -1
  26. package/dist/cache/MemoryStorage.mjs.map +1 -1
  27. package/dist/cache/TokenCache.d.ts.map +1 -1
  28. package/dist/cache/TokenCache.mjs +30 -30
  29. package/dist/cache/TokenCache.mjs.map +1 -1
  30. package/dist/config/Configuration.d.ts +1 -0
  31. package/dist/config/Configuration.d.ts.map +1 -1
  32. package/dist/config/Configuration.mjs +7 -11
  33. package/dist/config/Configuration.mjs.map +1 -1
  34. package/dist/controllers/ControllerFactory.mjs +1 -1
  35. package/dist/controllers/ControllerFactory.mjs.map +1 -1
  36. package/dist/controllers/IController.d.ts +3 -27
  37. package/dist/controllers/IController.d.ts.map +1 -1
  38. package/dist/controllers/StandardController.d.ts +6 -25
  39. package/dist/controllers/StandardController.d.ts.map +1 -1
  40. package/dist/controllers/StandardController.mjs +28 -52
  41. package/dist/controllers/StandardController.mjs.map +1 -1
  42. package/dist/crypto/BrowserCrypto.d.ts.map +1 -1
  43. package/dist/crypto/BrowserCrypto.mjs +4 -3
  44. package/dist/crypto/BrowserCrypto.mjs.map +1 -1
  45. package/dist/crypto/CryptoOps.d.ts +0 -3
  46. package/dist/crypto/CryptoOps.d.ts.map +1 -1
  47. package/dist/crypto/CryptoOps.mjs +14 -17
  48. package/dist/crypto/CryptoOps.mjs.map +1 -1
  49. package/dist/crypto/ModernBrowserCrypto.mjs +1 -1
  50. package/dist/crypto/ModernBrowserCrypto.mjs.map +1 -1
  51. package/dist/crypto/PkceGenerator.d.ts +0 -1
  52. package/dist/crypto/PkceGenerator.d.ts.map +1 -1
  53. package/dist/crypto/PkceGenerator.mjs +8 -8
  54. package/dist/crypto/PkceGenerator.mjs.map +1 -1
  55. package/dist/crypto/SignedHttpRequest.mjs +1 -1
  56. package/dist/crypto/SignedHttpRequest.mjs.map +1 -1
  57. package/dist/encode/Base64Decode.d.ts +6 -19
  58. package/dist/encode/Base64Decode.d.ts.map +1 -1
  59. package/dist/encode/Base64Decode.mjs +17 -70
  60. package/dist/encode/Base64Decode.mjs.map +1 -1
  61. package/dist/encode/Base64Encode.d.ts +15 -27
  62. package/dist/encode/Base64Encode.d.ts.map +1 -1
  63. package/dist/encode/Base64Encode.mjs +36 -75
  64. package/dist/encode/Base64Encode.mjs.map +1 -1
  65. package/dist/error/BrowserAuthError.d.ts +54 -195
  66. package/dist/error/BrowserAuthError.d.ts.map +1 -1
  67. package/dist/error/BrowserAuthError.mjs +150 -381
  68. package/dist/error/BrowserAuthError.mjs.map +1 -1
  69. package/dist/error/BrowserAuthErrorCodes.d.ts +45 -0
  70. package/dist/error/BrowserAuthErrorCodes.d.ts.map +1 -0
  71. package/dist/error/BrowserAuthErrorCodes.mjs +53 -0
  72. package/dist/error/BrowserAuthErrorCodes.mjs.map +1 -0
  73. package/dist/error/BrowserConfigurationAuthError.mjs +1 -1
  74. package/dist/error/BrowserConfigurationAuthError.mjs.map +1 -1
  75. package/dist/error/NativeAuthError.d.ts.map +1 -1
  76. package/dist/error/NativeAuthError.mjs +5 -4
  77. package/dist/error/NativeAuthError.mjs.map +1 -1
  78. package/dist/event/EventHandler.mjs +1 -1
  79. package/dist/event/EventHandler.mjs.map +1 -1
  80. package/dist/event/EventMessage.mjs +1 -1
  81. package/dist/event/EventMessage.mjs.map +1 -1
  82. package/dist/event/EventType.mjs +1 -1
  83. package/dist/event/EventType.mjs.map +1 -1
  84. package/dist/index.d.ts +5 -5
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.mjs +5 -3
  87. package/dist/index.mjs.map +1 -1
  88. package/dist/interaction_client/BaseInteractionClient.d.ts +2 -1
  89. package/dist/interaction_client/BaseInteractionClient.d.ts.map +1 -1
  90. package/dist/interaction_client/BaseInteractionClient.mjs +1 -1
  91. package/dist/interaction_client/BaseInteractionClient.mjs.map +1 -1
  92. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs +1 -1
  93. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs.map +1 -1
  94. package/dist/interaction_client/NativeInteractionClient.d.ts +4 -10
  95. package/dist/interaction_client/NativeInteractionClient.d.ts.map +1 -1
  96. package/dist/interaction_client/NativeInteractionClient.mjs +22 -30
  97. package/dist/interaction_client/NativeInteractionClient.mjs.map +1 -1
  98. package/dist/interaction_client/PopupClient.d.ts.map +1 -1
  99. package/dist/interaction_client/PopupClient.mjs +16 -15
  100. package/dist/interaction_client/PopupClient.mjs.map +1 -1
  101. package/dist/interaction_client/RedirectClient.d.ts.map +1 -1
  102. package/dist/interaction_client/RedirectClient.mjs +7 -6
  103. package/dist/interaction_client/RedirectClient.mjs.map +1 -1
  104. package/dist/interaction_client/SilentAuthCodeClient.d.ts.map +1 -1
  105. package/dist/interaction_client/SilentAuthCodeClient.mjs +5 -4
  106. package/dist/interaction_client/SilentAuthCodeClient.mjs.map +1 -1
  107. package/dist/interaction_client/SilentCacheClient.d.ts +4 -2
  108. package/dist/interaction_client/SilentCacheClient.d.ts.map +1 -1
  109. package/dist/interaction_client/SilentCacheClient.mjs +10 -8
  110. package/dist/interaction_client/SilentCacheClient.mjs.map +1 -1
  111. package/dist/interaction_client/SilentIframeClient.d.ts.map +1 -1
  112. package/dist/interaction_client/SilentIframeClient.mjs +20 -47
  113. package/dist/interaction_client/SilentIframeClient.mjs.map +1 -1
  114. package/dist/interaction_client/SilentRefreshClient.d.ts.map +1 -1
  115. package/dist/interaction_client/SilentRefreshClient.mjs +4 -3
  116. package/dist/interaction_client/SilentRefreshClient.mjs.map +1 -1
  117. package/dist/interaction_client/StandardInteractionClient.d.ts.map +1 -1
  118. package/dist/interaction_client/StandardInteractionClient.mjs +8 -7
  119. package/dist/interaction_client/StandardInteractionClient.mjs.map +1 -1
  120. package/dist/interaction_handler/InteractionHandler.d.ts.map +1 -1
  121. package/dist/interaction_handler/InteractionHandler.mjs +9 -9
  122. package/dist/interaction_handler/InteractionHandler.mjs.map +1 -1
  123. package/dist/interaction_handler/RedirectHandler.d.ts.map +1 -1
  124. package/dist/interaction_handler/RedirectHandler.mjs +11 -10
  125. package/dist/interaction_handler/RedirectHandler.mjs.map +1 -1
  126. package/dist/interaction_handler/SilentHandler.d.ts.map +1 -1
  127. package/dist/interaction_handler/SilentHandler.mjs +10 -9
  128. package/dist/interaction_handler/SilentHandler.mjs.map +1 -1
  129. package/dist/navigation/NavigationClient.mjs +1 -1
  130. package/dist/navigation/NavigationClient.mjs.map +1 -1
  131. package/dist/network/FetchClient.d.ts.map +1 -1
  132. package/dist/network/FetchClient.mjs +9 -8
  133. package/dist/network/FetchClient.mjs.map +1 -1
  134. package/dist/operatingcontext/BaseOperatingContext.mjs +1 -1
  135. package/dist/operatingcontext/BaseOperatingContext.mjs.map +1 -1
  136. package/dist/operatingcontext/StandardOperatingContext.mjs +1 -1
  137. package/dist/operatingcontext/StandardOperatingContext.mjs.map +1 -1
  138. package/dist/operatingcontext/TeamsAppOperatingContext.mjs +1 -1
  139. package/dist/operatingcontext/TeamsAppOperatingContext.mjs.map +1 -1
  140. package/dist/packageMetadata.d.ts +1 -1
  141. package/dist/packageMetadata.mjs +2 -2
  142. package/dist/packageMetadata.mjs.map +1 -1
  143. package/dist/request/ClearCacheRequest.d.ts +11 -0
  144. package/dist/request/ClearCacheRequest.d.ts.map +1 -0
  145. package/dist/telemetry/BrowserPerformanceClient.d.ts +2 -4
  146. package/dist/telemetry/BrowserPerformanceClient.d.ts.map +1 -1
  147. package/dist/telemetry/BrowserPerformanceClient.mjs +2 -6
  148. package/dist/telemetry/BrowserPerformanceClient.mjs.map +1 -1
  149. package/dist/telemetry/BrowserPerformanceMeasurement.mjs +1 -1
  150. package/dist/telemetry/BrowserPerformanceMeasurement.mjs.map +1 -1
  151. package/dist/utils/BrowserConstants.mjs +1 -1
  152. package/dist/utils/BrowserConstants.mjs.map +1 -1
  153. package/dist/utils/BrowserProtocolUtils.d.ts.map +1 -1
  154. package/dist/utils/BrowserProtocolUtils.mjs +3 -3
  155. package/dist/utils/BrowserProtocolUtils.mjs.map +1 -1
  156. package/dist/utils/BrowserStringUtils.mjs +1 -1
  157. package/dist/utils/BrowserStringUtils.mjs.map +1 -1
  158. package/dist/utils/BrowserUtils.d.ts +0 -9
  159. package/dist/utils/BrowserUtils.d.ts.map +1 -1
  160. package/dist/utils/BrowserUtils.mjs +8 -33
  161. package/dist/utils/BrowserUtils.mjs.map +1 -1
  162. package/lib/msal-browser.cjs +6579 -7102
  163. package/lib/msal-browser.cjs.map +1 -1
  164. package/lib/msal-browser.js +6579 -7102
  165. package/lib/msal-browser.js.map +1 -1
  166. package/lib/msal-browser.min.js +65 -62
  167. package/package.json +7 -5
  168. package/src/app/IPublicClientApplication.ts +199 -0
  169. package/src/app/PublicClientApplication.ts +405 -0
  170. package/src/broker/nativeBroker/NativeMessageHandler.ts +419 -0
  171. package/src/broker/nativeBroker/NativeRequest.ts +52 -0
  172. package/src/broker/nativeBroker/NativeResponse.ts +56 -0
  173. package/src/cache/AsyncMemoryStorage.ts +158 -0
  174. package/src/cache/BrowserCacheManager.ts +1994 -0
  175. package/src/cache/BrowserStorage.ts +54 -0
  176. package/src/cache/CryptoKeyStore.ts +63 -0
  177. package/src/cache/DatabaseStorage.ts +287 -0
  178. package/src/cache/IAsyncMemoryStorage.ts +36 -0
  179. package/src/cache/ITokenCache.ts +21 -0
  180. package/src/cache/IWindowStorage.ts +36 -0
  181. package/src/cache/MemoryStorage.ts +42 -0
  182. package/src/cache/TokenCache.ts +484 -0
  183. package/src/config/Configuration.ts +375 -0
  184. package/src/controllers/ControllerFactory.ts +55 -0
  185. package/src/controllers/IController.ts +131 -0
  186. package/src/controllers/StandardController.ts +2107 -0
  187. package/src/crypto/BrowserCrypto.ts +135 -0
  188. package/src/crypto/CryptoOps.ts +247 -0
  189. package/src/crypto/ISubtleCrypto.ts +30 -0
  190. package/src/crypto/ModernBrowserCrypto.ts +69 -0
  191. package/src/crypto/PkceGenerator.ts +76 -0
  192. package/src/crypto/SignedHttpRequest.ts +76 -0
  193. package/src/encode/Base64Decode.ts +26 -0
  194. package/src/encode/Base64Encode.ts +52 -0
  195. package/src/error/BrowserAuthError.ts +340 -0
  196. package/src/error/BrowserAuthErrorCodes.ts +56 -0
  197. package/src/error/BrowserConfigurationAuthError.ts +133 -0
  198. package/src/error/NativeAuthError.ts +141 -0
  199. package/src/event/EventHandler.ts +176 -0
  200. package/src/event/EventMessage.ts +125 -0
  201. package/src/event/EventType.ts +33 -0
  202. package/src/index.ts +152 -0
  203. package/src/interaction_client/BaseInteractionClient.ts +301 -0
  204. package/src/interaction_client/HybridSpaAuthorizationCodeClient.ts +16 -0
  205. package/src/interaction_client/NativeInteractionClient.ts +907 -0
  206. package/src/interaction_client/PopupClient.ts +926 -0
  207. package/src/interaction_client/RedirectClient.ts +616 -0
  208. package/src/interaction_client/SilentAuthCodeClient.ts +163 -0
  209. package/src/interaction_client/SilentCacheClient.ts +133 -0
  210. package/src/interaction_client/SilentIframeClient.ts +301 -0
  211. package/src/interaction_client/SilentRefreshClient.ts +120 -0
  212. package/src/interaction_client/StandardInteractionClient.ts +481 -0
  213. package/src/interaction_handler/InteractionHandler.ts +246 -0
  214. package/src/interaction_handler/RedirectHandler.ts +225 -0
  215. package/src/interaction_handler/SilentHandler.ts +266 -0
  216. package/src/navigation/INavigationClient.ts +23 -0
  217. package/src/navigation/NavigationClient.ts +55 -0
  218. package/src/navigation/NavigationOptions.ts +18 -0
  219. package/src/network/FetchClient.ts +130 -0
  220. package/src/operatingcontext/BaseOperatingContext.ts +82 -0
  221. package/src/operatingcontext/StandardOperatingContext.ts +49 -0
  222. package/src/operatingcontext/TeamsAppOperatingContext.ts +48 -0
  223. package/src/packageMetadata.ts +3 -0
  224. package/src/request/AuthorizationCodeRequest.ts +19 -0
  225. package/src/request/AuthorizationUrlRequest.ts +17 -0
  226. package/src/request/ClearCacheRequest.ts +16 -0
  227. package/src/request/EndSessionPopupRequest.ts +26 -0
  228. package/src/request/EndSessionRequest.ts +23 -0
  229. package/src/request/PopupRequest.ts +51 -0
  230. package/src/request/PopupWindowAttributes.ts +22 -0
  231. package/src/request/RedirectRequest.ts +51 -0
  232. package/src/request/SilentRequest.ts +49 -0
  233. package/src/request/SsoSilentRequest.ts +44 -0
  234. package/src/response/AuthenticationResult.ts +13 -0
  235. package/src/telemetry/BrowserPerformanceClient.ts +226 -0
  236. package/src/telemetry/BrowserPerformanceMeasurement.ts +144 -0
  237. package/src/utils/BrowserConstants.ts +241 -0
  238. package/src/utils/BrowserProtocolUtils.ts +57 -0
  239. package/src/utils/BrowserStringUtils.ts +143 -0
  240. package/src/utils/BrowserUtils.ts +156 -0
  241. package/dist/crypto/GuidGenerator.d.ts +0 -13
  242. package/dist/crypto/GuidGenerator.d.ts.map +0 -1
  243. package/dist/crypto/GuidGenerator.mjs +0 -104
  244. package/dist/crypto/GuidGenerator.mjs.map +0 -1
  245. package/dist/internals.d.ts +0 -23
  246. package/dist/internals.d.ts.map +0 -1
  247. package/dist/internals.mjs +0 -28
  248. package/dist/internals.mjs.map +0 -1
  249. package/dist/network/XhrClient.d.ts +0 -41
  250. package/dist/network/XhrClient.d.ts.map +0 -1
  251. package/dist/network/XhrClient.mjs +0 -125
  252. package/dist/network/XhrClient.mjs.map +0 -1
  253. package/dist/utils/MathUtils.d.ts +0 -12
  254. package/dist/utils/MathUtils.d.ts.map +0 -1
  255. package/dist/utils/MathUtils.mjs +0 -26
  256. package/dist/utils/MathUtils.mjs.map +0 -1
@@ -0,0 +1,616 @@
1
+ /*
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import {
7
+ CommonAuthorizationCodeRequest,
8
+ AuthorizationCodeClient,
9
+ UrlString,
10
+ AuthError,
11
+ ServerTelemetryManager,
12
+ Constants,
13
+ ProtocolUtils,
14
+ ServerAuthorizationCodeResponse,
15
+ ThrottlingUtils,
16
+ ICrypto,
17
+ Logger,
18
+ IPerformanceClient,
19
+ PerformanceEvents,
20
+ ProtocolMode,
21
+ } from "@azure/msal-common";
22
+ import { StandardInteractionClient } from "./StandardInteractionClient";
23
+ import {
24
+ ApiId,
25
+ InteractionType,
26
+ TemporaryCacheKeys,
27
+ } from "../utils/BrowserConstants";
28
+ import { RedirectHandler } from "../interaction_handler/RedirectHandler";
29
+ import { BrowserUtils } from "../utils/BrowserUtils";
30
+ import { EndSessionRequest } from "../request/EndSessionRequest";
31
+ import { EventType } from "../event/EventType";
32
+ import { NavigationOptions } from "../navigation/NavigationOptions";
33
+ import {
34
+ createBrowserAuthError,
35
+ BrowserAuthErrorCodes,
36
+ } from "../error/BrowserAuthError";
37
+ import { RedirectRequest } from "../request/RedirectRequest";
38
+ import { NativeInteractionClient } from "./NativeInteractionClient";
39
+ import { NativeMessageHandler } from "../broker/nativeBroker/NativeMessageHandler";
40
+ import { BrowserConfiguration } from "../config/Configuration";
41
+ import { BrowserCacheManager } from "../cache/BrowserCacheManager";
42
+ import { EventHandler } from "../event/EventHandler";
43
+ import { INavigationClient } from "../navigation/INavigationClient";
44
+ import { EventError } from "../event/EventMessage";
45
+ import { AuthenticationResult } from "../response/AuthenticationResult";
46
+
47
+ export class RedirectClient extends StandardInteractionClient {
48
+ protected nativeStorage: BrowserCacheManager;
49
+
50
+ constructor(
51
+ config: BrowserConfiguration,
52
+ storageImpl: BrowserCacheManager,
53
+ browserCrypto: ICrypto,
54
+ logger: Logger,
55
+ eventHandler: EventHandler,
56
+ navigationClient: INavigationClient,
57
+ performanceClient: IPerformanceClient,
58
+ nativeStorageImpl: BrowserCacheManager,
59
+ nativeMessageHandler?: NativeMessageHandler,
60
+ correlationId?: string
61
+ ) {
62
+ super(
63
+ config,
64
+ storageImpl,
65
+ browserCrypto,
66
+ logger,
67
+ eventHandler,
68
+ navigationClient,
69
+ performanceClient,
70
+ nativeMessageHandler,
71
+ correlationId
72
+ );
73
+ this.nativeStorage = nativeStorageImpl;
74
+ }
75
+
76
+ /**
77
+ * Redirects the page to the /authorize endpoint of the IDP
78
+ * @param request
79
+ */
80
+ async acquireToken(request: RedirectRequest): Promise<void> {
81
+ this.performanceClient.setPreQueueTime(
82
+ PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest,
83
+ request.correlationId
84
+ );
85
+ const validRequest = await this.initializeAuthorizationRequest(
86
+ request,
87
+ InteractionType.Redirect
88
+ );
89
+ this.browserStorage.updateCacheEntries(
90
+ validRequest.state,
91
+ validRequest.nonce,
92
+ validRequest.authority,
93
+ validRequest.loginHint || Constants.EMPTY_STRING,
94
+ validRequest.account || null
95
+ );
96
+ const serverTelemetryManager = this.initializeServerTelemetryManager(
97
+ ApiId.acquireTokenRedirect
98
+ );
99
+
100
+ const handleBackButton = (event: PageTransitionEvent) => {
101
+ // Clear temporary cache if the back button is clicked during the redirect flow.
102
+ if (event.persisted) {
103
+ this.logger.verbose(
104
+ "Page was restored from back/forward cache. Clearing temporary cache."
105
+ );
106
+ this.browserStorage.cleanRequestByState(validRequest.state);
107
+ this.eventHandler.emitEvent(
108
+ EventType.RESTORE_FROM_BFCACHE,
109
+ InteractionType.Redirect
110
+ );
111
+ }
112
+ };
113
+
114
+ try {
115
+ // Create auth code request and generate PKCE params
116
+ this.performanceClient.setPreQueueTime(
117
+ PerformanceEvents.StandardInteractionClientInitializeAuthorizationCodeRequest,
118
+ request.correlationId
119
+ );
120
+ const authCodeRequest: CommonAuthorizationCodeRequest =
121
+ await this.initializeAuthorizationCodeRequest(validRequest);
122
+
123
+ // Initialize the client
124
+ this.performanceClient.setPreQueueTime(
125
+ PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,
126
+ request.correlationId
127
+ );
128
+ const authClient: AuthorizationCodeClient =
129
+ await this.createAuthCodeClient(
130
+ serverTelemetryManager,
131
+ validRequest.authority,
132
+ validRequest.azureCloudOptions
133
+ );
134
+ this.logger.verbose("Auth code client created");
135
+
136
+ // Create redirect interaction handler.
137
+ const interactionHandler = new RedirectHandler(
138
+ authClient,
139
+ this.browserStorage,
140
+ authCodeRequest,
141
+ this.logger,
142
+ this.browserCrypto,
143
+ this.performanceClient
144
+ );
145
+
146
+ // Create acquire token url.
147
+ const navigateUrl = await authClient.getAuthCodeUrl({
148
+ ...validRequest,
149
+ nativeBroker: NativeMessageHandler.isNativeAvailable(
150
+ this.config,
151
+ this.logger,
152
+ this.nativeMessageHandler,
153
+ request.authenticationScheme
154
+ ),
155
+ });
156
+
157
+ const redirectStartPage = this.getRedirectStartPage(
158
+ request.redirectStartPage
159
+ );
160
+ this.logger.verbosePii(`Redirect start page: ${redirectStartPage}`);
161
+
162
+ // Clear temporary cache if the back button is clicked during the redirect flow.
163
+ window.addEventListener("pageshow", handleBackButton);
164
+
165
+ // Show the UI once the url has been created. Response will come back in the hash, which will be handled in the handleRedirectCallback function.
166
+ return await interactionHandler.initiateAuthRequest(navigateUrl, {
167
+ navigationClient: this.navigationClient,
168
+ redirectTimeout: this.config.system.redirectNavigationTimeout,
169
+ redirectStartPage: redirectStartPage,
170
+ onRedirectNavigate: request.onRedirectNavigate,
171
+ });
172
+ } catch (e) {
173
+ if (e instanceof AuthError) {
174
+ e.setCorrelationId(this.correlationId);
175
+ serverTelemetryManager.cacheFailedRequest(e);
176
+ }
177
+ window.removeEventListener("pageshow", handleBackButton);
178
+ this.browserStorage.cleanRequestByState(validRequest.state);
179
+ throw e;
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Checks if navigateToLoginRequestUrl is set, and:
185
+ * - if true, performs logic to cache and navigate
186
+ * - if false, handles hash string and parses response
187
+ * @param hash
188
+ */
189
+ async handleRedirectPromise(
190
+ hash?: string
191
+ ): Promise<AuthenticationResult | null> {
192
+ const serverTelemetryManager = this.initializeServerTelemetryManager(
193
+ ApiId.handleRedirectPromise
194
+ );
195
+ try {
196
+ if (!this.browserStorage.isInteractionInProgress(true)) {
197
+ this.logger.info(
198
+ "handleRedirectPromise called but there is no interaction in progress, returning null."
199
+ );
200
+ return null;
201
+ }
202
+ const responseHash = this.getRedirectResponseHash(
203
+ hash || window.location.hash
204
+ );
205
+ if (!responseHash) {
206
+ // Not a recognized server response hash or hash not associated with a redirect request
207
+ this.logger.info(
208
+ "handleRedirectPromise did not detect a response hash as a result of a redirect. Cleaning temporary cache."
209
+ );
210
+ this.browserStorage.cleanRequestByInteractionType(
211
+ InteractionType.Redirect
212
+ );
213
+ return null;
214
+ }
215
+
216
+ let state: string;
217
+ try {
218
+ // Deserialize hash fragment response parameters.
219
+ const serverParams: ServerAuthorizationCodeResponse =
220
+ UrlString.getDeserializedHash(responseHash);
221
+ state = this.validateAndExtractStateFromHash(
222
+ serverParams,
223
+ InteractionType.Redirect
224
+ );
225
+ this.logger.verbose("State extracted from hash");
226
+ } catch (e) {
227
+ this.logger.info(
228
+ `handleRedirectPromise was unable to extract state due to: ${e}`
229
+ );
230
+ this.browserStorage.cleanRequestByInteractionType(
231
+ InteractionType.Redirect
232
+ );
233
+ return null;
234
+ }
235
+
236
+ // If navigateToLoginRequestUrl is true, get the url where the redirect request was initiated
237
+ const loginRequestUrl =
238
+ this.browserStorage.getTemporaryCache(
239
+ TemporaryCacheKeys.ORIGIN_URI,
240
+ true
241
+ ) || Constants.EMPTY_STRING;
242
+ const loginRequestUrlNormalized =
243
+ UrlString.removeHashFromUrl(loginRequestUrl);
244
+ const currentUrlNormalized = UrlString.removeHashFromUrl(
245
+ window.location.href
246
+ );
247
+
248
+ if (
249
+ loginRequestUrlNormalized === currentUrlNormalized &&
250
+ this.config.auth.navigateToLoginRequestUrl
251
+ ) {
252
+ // We are on the page we need to navigate to - handle hash
253
+ this.logger.verbose(
254
+ "Current page is loginRequestUrl, handling hash"
255
+ );
256
+ const handleHashResult = await this.handleHash(
257
+ responseHash,
258
+ state,
259
+ serverTelemetryManager
260
+ );
261
+
262
+ if (loginRequestUrl.indexOf("#") > -1) {
263
+ // Replace current hash with non-msal hash, if present
264
+ BrowserUtils.replaceHash(loginRequestUrl);
265
+ }
266
+
267
+ return handleHashResult;
268
+ } else if (!this.config.auth.navigateToLoginRequestUrl) {
269
+ this.logger.verbose(
270
+ "NavigateToLoginRequestUrl set to false, handling hash"
271
+ );
272
+ return this.handleHash(
273
+ responseHash,
274
+ state,
275
+ serverTelemetryManager
276
+ );
277
+ } else if (
278
+ !BrowserUtils.isInIframe() ||
279
+ this.config.system.allowRedirectInIframe
280
+ ) {
281
+ /*
282
+ * Returned from authority using redirect - need to perform navigation before processing response
283
+ * Cache the hash to be retrieved after the next redirect
284
+ */
285
+ this.browserStorage.setTemporaryCache(
286
+ TemporaryCacheKeys.URL_HASH,
287
+ responseHash,
288
+ true
289
+ );
290
+ const navigationOptions: NavigationOptions = {
291
+ apiId: ApiId.handleRedirectPromise,
292
+ timeout: this.config.system.redirectNavigationTimeout,
293
+ noHistory: true,
294
+ };
295
+
296
+ /**
297
+ * Default behavior is to redirect to the start page and not process the hash now.
298
+ * The start page is expected to also call handleRedirectPromise which will process the hash in one of the checks above.
299
+ */
300
+ let processHashOnRedirect: boolean = true;
301
+ if (!loginRequestUrl || loginRequestUrl === "null") {
302
+ // Redirect to home page if login request url is null (real null or the string null)
303
+ const homepage = BrowserUtils.getHomepage();
304
+ // Cache the homepage under ORIGIN_URI to ensure cached hash is processed on homepage
305
+ this.browserStorage.setTemporaryCache(
306
+ TemporaryCacheKeys.ORIGIN_URI,
307
+ homepage,
308
+ true
309
+ );
310
+ this.logger.warning(
311
+ "Unable to get valid login request url from cache, redirecting to home page"
312
+ );
313
+ processHashOnRedirect =
314
+ await this.navigationClient.navigateInternal(
315
+ homepage,
316
+ navigationOptions
317
+ );
318
+ } else {
319
+ // Navigate to page that initiated the redirect request
320
+ this.logger.verbose(
321
+ `Navigating to loginRequestUrl: ${loginRequestUrl}`
322
+ );
323
+ processHashOnRedirect =
324
+ await this.navigationClient.navigateInternal(
325
+ loginRequestUrl,
326
+ navigationOptions
327
+ );
328
+ }
329
+
330
+ // If navigateInternal implementation returns false, handle the hash now
331
+ if (!processHashOnRedirect) {
332
+ return this.handleHash(
333
+ responseHash,
334
+ state,
335
+ serverTelemetryManager
336
+ );
337
+ }
338
+ }
339
+
340
+ return null;
341
+ } catch (e) {
342
+ if (e instanceof AuthError) {
343
+ (e as AuthError).setCorrelationId(this.correlationId);
344
+ serverTelemetryManager.cacheFailedRequest(e);
345
+ }
346
+ this.browserStorage.cleanRequestByInteractionType(
347
+ InteractionType.Redirect
348
+ );
349
+ throw e;
350
+ }
351
+ }
352
+
353
+ /**
354
+ * Gets the response hash for a redirect request
355
+ * Returns null if interactionType in the state value is not "redirect" or the hash does not contain known properties
356
+ * @param hash
357
+ */
358
+ protected getRedirectResponseHash(hash: string): string | null {
359
+ this.logger.verbose("getRedirectResponseHash called");
360
+ // Get current location hash from window or cache.
361
+ const isResponseHash: boolean =
362
+ UrlString.hashContainsKnownProperties(hash);
363
+
364
+ if (isResponseHash) {
365
+ BrowserUtils.clearHash(window);
366
+ this.logger.verbose(
367
+ "Hash contains known properties, returning response hash"
368
+ );
369
+ return hash;
370
+ }
371
+
372
+ const cachedHash = this.browserStorage.getTemporaryCache(
373
+ TemporaryCacheKeys.URL_HASH,
374
+ true
375
+ );
376
+ this.browserStorage.removeItem(
377
+ this.browserStorage.generateCacheKey(TemporaryCacheKeys.URL_HASH)
378
+ );
379
+
380
+ this.logger.verbose(
381
+ "Hash does not contain known properties, returning cached hash"
382
+ );
383
+ return cachedHash;
384
+ }
385
+
386
+ /**
387
+ * Checks if hash exists and handles in window.
388
+ * @param hash
389
+ * @param state
390
+ */
391
+ protected async handleHash(
392
+ hash: string,
393
+ state: string,
394
+ serverTelemetryManager: ServerTelemetryManager
395
+ ): Promise<AuthenticationResult> {
396
+ const cachedRequest = this.browserStorage.getCachedRequest(state);
397
+ this.logger.verbose("handleHash called, retrieved cached request");
398
+
399
+ const serverParams: ServerAuthorizationCodeResponse =
400
+ UrlString.getDeserializedHash(hash);
401
+
402
+ if (serverParams.accountId) {
403
+ this.logger.verbose(
404
+ "Account id found in hash, calling WAM for token"
405
+ );
406
+ if (!this.nativeMessageHandler) {
407
+ throw createBrowserAuthError(
408
+ BrowserAuthErrorCodes.nativeConnectionNotEstablished
409
+ );
410
+ }
411
+ const nativeInteractionClient = new NativeInteractionClient(
412
+ this.config,
413
+ this.browserStorage,
414
+ this.browserCrypto,
415
+ this.logger,
416
+ this.eventHandler,
417
+ this.navigationClient,
418
+ ApiId.acquireTokenPopup,
419
+ this.performanceClient,
420
+ this.nativeMessageHandler,
421
+ serverParams.accountId,
422
+ this.nativeStorage,
423
+ cachedRequest.correlationId
424
+ );
425
+ const { userRequestState } = ProtocolUtils.parseRequestState(
426
+ this.browserCrypto,
427
+ state
428
+ );
429
+ return nativeInteractionClient
430
+ .acquireToken({
431
+ ...cachedRequest,
432
+ state: userRequestState,
433
+ prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently
434
+ })
435
+ .finally(() => {
436
+ this.browserStorage.cleanRequestByState(state);
437
+ });
438
+ }
439
+
440
+ // Hash contains known properties - handle and return in callback
441
+ const currentAuthority = this.browserStorage.getCachedAuthority(state);
442
+ if (!currentAuthority) {
443
+ throw createBrowserAuthError(
444
+ BrowserAuthErrorCodes.noCachedAuthorityError
445
+ );
446
+ }
447
+ this.performanceClient.setPreQueueTime(
448
+ PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,
449
+ cachedRequest.correlationId
450
+ );
451
+ const authClient = await this.createAuthCodeClient(
452
+ serverTelemetryManager,
453
+ currentAuthority
454
+ );
455
+ this.logger.verbose("Auth code client created");
456
+ ThrottlingUtils.removeThrottle(
457
+ this.browserStorage,
458
+ this.config.auth.clientId,
459
+ cachedRequest
460
+ );
461
+ const interactionHandler = new RedirectHandler(
462
+ authClient,
463
+ this.browserStorage,
464
+ cachedRequest,
465
+ this.logger,
466
+ this.browserCrypto,
467
+ this.performanceClient
468
+ );
469
+ return await interactionHandler.handleCodeResponseFromHash(
470
+ hash,
471
+ state,
472
+ authClient.authority,
473
+ this.networkClient
474
+ );
475
+ }
476
+
477
+ /**
478
+ * Use to log out the current user, and redirect the user to the postLogoutRedirectUri.
479
+ * Default behaviour is to redirect the user to `window.location.href`.
480
+ * @param logoutRequest
481
+ */
482
+ async logout(logoutRequest?: EndSessionRequest): Promise<void> {
483
+ this.logger.verbose("logoutRedirect called");
484
+ const validLogoutRequest = this.initializeLogoutRequest(logoutRequest);
485
+ const serverTelemetryManager = this.initializeServerTelemetryManager(
486
+ ApiId.logout
487
+ );
488
+
489
+ try {
490
+ this.eventHandler.emitEvent(
491
+ EventType.LOGOUT_START,
492
+ InteractionType.Redirect,
493
+ logoutRequest
494
+ );
495
+
496
+ // Clear cache on logout
497
+ await this.clearCacheOnLogout(validLogoutRequest.account);
498
+
499
+ const navigationOptions: NavigationOptions = {
500
+ apiId: ApiId.logout,
501
+ timeout: this.config.system.redirectNavigationTimeout,
502
+ noHistory: false,
503
+ };
504
+ this.performanceClient.setPreQueueTime(
505
+ PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,
506
+ validLogoutRequest.correlationId
507
+ );
508
+ const authClient = await this.createAuthCodeClient(
509
+ serverTelemetryManager,
510
+ logoutRequest && logoutRequest.authority
511
+ );
512
+ this.logger.verbose("Auth code client created");
513
+
514
+ if (authClient.authority.protocolMode === ProtocolMode.OIDC) {
515
+ try {
516
+ authClient.authority.endSessionEndpoint;
517
+ } catch {
518
+ if (validLogoutRequest.account?.homeAccountId) {
519
+ void this.browserStorage.removeAccount(
520
+ validLogoutRequest.account?.homeAccountId
521
+ );
522
+
523
+ this.eventHandler.emitEvent(
524
+ EventType.LOGOUT_SUCCESS,
525
+ InteractionType.Redirect,
526
+ validLogoutRequest
527
+ );
528
+
529
+ return;
530
+ }
531
+ }
532
+ }
533
+
534
+ // Create logout string and navigate user window to logout.
535
+ const logoutUri: string =
536
+ authClient.getLogoutUri(validLogoutRequest);
537
+
538
+ this.eventHandler.emitEvent(
539
+ EventType.LOGOUT_SUCCESS,
540
+ InteractionType.Redirect,
541
+ validLogoutRequest
542
+ );
543
+ // Check if onRedirectNavigate is implemented, and invoke it if so
544
+ if (
545
+ logoutRequest &&
546
+ typeof logoutRequest.onRedirectNavigate === "function"
547
+ ) {
548
+ const navigate = logoutRequest.onRedirectNavigate(logoutUri);
549
+
550
+ if (navigate !== false) {
551
+ this.logger.verbose(
552
+ "Logout onRedirectNavigate did not return false, navigating"
553
+ );
554
+ // Ensure interaction is in progress
555
+ if (!this.browserStorage.getInteractionInProgress()) {
556
+ this.browserStorage.setInteractionInProgress(true);
557
+ }
558
+ await this.navigationClient.navigateExternal(
559
+ logoutUri,
560
+ navigationOptions
561
+ );
562
+ return;
563
+ } else {
564
+ // Ensure interaction is not in progress
565
+ this.browserStorage.setInteractionInProgress(false);
566
+ this.logger.verbose(
567
+ "Logout onRedirectNavigate returned false, stopping navigation"
568
+ );
569
+ }
570
+ } else {
571
+ // Ensure interaction is in progress
572
+ if (!this.browserStorage.getInteractionInProgress()) {
573
+ this.browserStorage.setInteractionInProgress(true);
574
+ }
575
+ await this.navigationClient.navigateExternal(
576
+ logoutUri,
577
+ navigationOptions
578
+ );
579
+ return;
580
+ }
581
+ } catch (e) {
582
+ if (e instanceof AuthError) {
583
+ (e as AuthError).setCorrelationId(this.correlationId);
584
+ serverTelemetryManager.cacheFailedRequest(e);
585
+ }
586
+ this.eventHandler.emitEvent(
587
+ EventType.LOGOUT_FAILURE,
588
+ InteractionType.Redirect,
589
+ null,
590
+ e as EventError
591
+ );
592
+ this.eventHandler.emitEvent(
593
+ EventType.LOGOUT_END,
594
+ InteractionType.Redirect
595
+ );
596
+ throw e;
597
+ }
598
+
599
+ this.eventHandler.emitEvent(
600
+ EventType.LOGOUT_END,
601
+ InteractionType.Redirect
602
+ );
603
+ }
604
+
605
+ /**
606
+ * Use to get the redirectStartPage either from request or use current window
607
+ * @param requestStartPage
608
+ */
609
+ protected getRedirectStartPage(requestStartPage?: string): string {
610
+ const redirectStartPage = requestStartPage || window.location.href;
611
+ return UrlString.getAbsoluteUrl(
612
+ redirectStartPage,
613
+ BrowserUtils.getCurrentUri()
614
+ );
615
+ }
616
+ }