@azure/msal-browser 3.0.0-alpha.1 → 3.0.0-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 (178) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +213 -213
  3. package/dist/app/IPublicClientApplication.d.ts +45 -45
  4. package/dist/app/IPublicClientApplication.js +96 -96
  5. package/dist/app/PublicClientApplication.d.ts +244 -244
  6. package/dist/app/PublicClientApplication.js +307 -307
  7. package/dist/broker/nativeBroker/NativeMessageHandler.d.ts +63 -63
  8. package/dist/broker/nativeBroker/NativeMessageHandler.js +255 -255
  9. package/dist/broker/nativeBroker/NativeRequest.d.ts +43 -43
  10. package/dist/broker/nativeBroker/NativeResponse.d.ts +48 -48
  11. package/dist/cache/AsyncMemoryStorage.d.ts +51 -51
  12. package/dist/cache/AsyncMemoryStorage.js +132 -132
  13. package/dist/cache/BrowserCacheManager.d.ts +376 -377
  14. package/dist/cache/BrowserCacheManager.d.ts.map +1 -1
  15. package/dist/cache/BrowserCacheManager.js +1275 -1276
  16. package/dist/cache/BrowserCacheManager.js.map +1 -1
  17. package/dist/cache/BrowserStorage.d.ts +11 -11
  18. package/dist/cache/BrowserStorage.js +35 -35
  19. package/dist/cache/CryptoKeyStore.d.ts +18 -17
  20. package/dist/cache/CryptoKeyStore.d.ts.map +1 -1
  21. package/dist/cache/CryptoKeyStore.js +40 -41
  22. package/dist/cache/CryptoKeyStore.js.map +1 -1
  23. package/dist/cache/DatabaseStorage.d.ts +56 -56
  24. package/dist/cache/DatabaseStorage.js +190 -190
  25. package/dist/cache/IAsyncMemoryStorage.d.ts +27 -27
  26. package/dist/cache/ITokenCache.d.ts +10 -10
  27. package/dist/cache/IWindowStorage.d.ts +27 -27
  28. package/dist/cache/MemoryStorage.d.ts +11 -11
  29. package/dist/cache/MemoryStorage.js +31 -31
  30. package/dist/cache/TokenCache.d.ts +76 -76
  31. package/dist/cache/TokenCache.js +225 -225
  32. package/dist/config/Configuration.d.ts +187 -203
  33. package/dist/config/Configuration.d.ts.map +1 -1
  34. package/dist/config/Configuration.js +97 -101
  35. package/dist/config/Configuration.js.map +1 -1
  36. package/dist/controllers/ControllerFactory.d.ts +9 -9
  37. package/dist/controllers/ControllerFactory.js +37 -37
  38. package/dist/controllers/IController.d.ts +66 -66
  39. package/dist/controllers/IController.d.ts.map +1 -1
  40. package/dist/controllers/StandardController.d.ts +413 -413
  41. package/dist/controllers/StandardController.d.ts.map +1 -1
  42. package/dist/controllers/StandardController.js +1277 -1272
  43. package/dist/controllers/StandardController.js.map +1 -1
  44. package/dist/crypto/BrowserCrypto.d.ts +49 -61
  45. package/dist/crypto/BrowserCrypto.d.ts.map +1 -1
  46. package/dist/crypto/BrowserCrypto.js +93 -134
  47. package/dist/crypto/BrowserCrypto.js.map +1 -1
  48. package/dist/crypto/CryptoOps.d.ts +72 -73
  49. package/dist/crypto/CryptoOps.d.ts.map +1 -1
  50. package/dist/crypto/CryptoOps.js +150 -150
  51. package/dist/crypto/CryptoOps.js.map +1 -1
  52. package/dist/crypto/GuidGenerator.d.ts +12 -12
  53. package/dist/crypto/GuidGenerator.js +96 -96
  54. package/dist/crypto/ISubtleCrypto.d.ts +9 -9
  55. package/dist/crypto/ModernBrowserCrypto.d.ts +9 -9
  56. package/dist/crypto/ModernBrowserCrypto.js +24 -24
  57. package/dist/crypto/PkceGenerator.d.ts +24 -24
  58. package/dist/crypto/PkceGenerator.js +58 -58
  59. package/dist/crypto/SignedHttpRequest.d.ts +30 -30
  60. package/dist/crypto/SignedHttpRequest.js +39 -39
  61. package/dist/encode/Base64Decode.d.ts +22 -22
  62. package/dist/encode/Base64Decode.js +73 -73
  63. package/dist/encode/Base64Encode.d.ts +31 -31
  64. package/dist/encode/Base64Encode.js +79 -79
  65. package/dist/error/BrowserAuthError.d.ts +382 -382
  66. package/dist/error/BrowserAuthError.js +483 -483
  67. package/dist/error/BrowserConfigurationAuthError.d.ts +70 -70
  68. package/dist/error/BrowserConfigurationAuthError.js +96 -96
  69. package/dist/error/NativeAuthError.d.ts +57 -56
  70. package/dist/error/NativeAuthError.d.ts.map +1 -1
  71. package/dist/error/NativeAuthError.js +93 -88
  72. package/dist/error/NativeAuthError.js.map +1 -1
  73. package/dist/event/EventHandler.d.ts +41 -41
  74. package/dist/event/EventHandler.js +119 -119
  75. package/dist/event/EventMessage.d.ts +25 -25
  76. package/dist/event/EventMessage.d.ts.map +1 -1
  77. package/dist/event/EventMessage.js +68 -67
  78. package/dist/event/EventMessage.js.map +1 -1
  79. package/dist/event/EventType.d.ts +28 -26
  80. package/dist/event/EventType.d.ts.map +1 -1
  81. package/dist/event/EventType.js +32 -32
  82. package/dist/event/EventType.js.map +1 -1
  83. package/dist/index.d.ts +35 -35
  84. package/dist/index.js +1 -1
  85. package/dist/interaction_client/BaseInteractionClient.d.ts +53 -52
  86. package/dist/interaction_client/BaseInteractionClient.d.ts.map +1 -1
  87. package/dist/interaction_client/BaseInteractionClient.js +151 -138
  88. package/dist/interaction_client/BaseInteractionClient.js.map +1 -1
  89. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.d.ts +4 -4
  90. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.js +10 -10
  91. package/dist/interaction_client/NativeInteractionClient.d.ts +148 -148
  92. package/dist/interaction_client/NativeInteractionClient.d.ts.map +1 -1
  93. package/dist/interaction_client/NativeInteractionClient.js +521 -517
  94. package/dist/interaction_client/NativeInteractionClient.js.map +1 -1
  95. package/dist/interaction_client/PopupClient.d.ts +111 -111
  96. package/dist/interaction_client/PopupClient.js +476 -476
  97. package/dist/interaction_client/RedirectClient.d.ts +48 -48
  98. package/dist/interaction_client/RedirectClient.d.ts.map +1 -1
  99. package/dist/interaction_client/RedirectClient.js +291 -290
  100. package/dist/interaction_client/RedirectClient.js.map +1 -1
  101. package/dist/interaction_client/SilentAuthCodeClient.d.ts +22 -22
  102. package/dist/interaction_client/SilentAuthCodeClient.js +62 -62
  103. package/dist/interaction_client/SilentCacheClient.d.ts +21 -21
  104. package/dist/interaction_client/SilentCacheClient.js +67 -67
  105. package/dist/interaction_client/SilentCacheClient.js.map +1 -1
  106. package/dist/interaction_client/SilentIframeClient.d.ts +31 -31
  107. package/dist/interaction_client/SilentIframeClient.js +127 -127
  108. package/dist/interaction_client/SilentRefreshClient.d.ts +19 -19
  109. package/dist/interaction_client/SilentRefreshClient.js +62 -62
  110. package/dist/interaction_client/SilentRefreshClient.js.map +1 -1
  111. package/dist/interaction_client/StandardInteractionClient.d.ts +59 -59
  112. package/dist/interaction_client/StandardInteractionClient.js +259 -259
  113. package/dist/interaction_handler/InteractionHandler.d.ts +39 -39
  114. package/dist/interaction_handler/InteractionHandler.js +127 -127
  115. package/dist/interaction_handler/RedirectHandler.d.ts +24 -24
  116. package/dist/interaction_handler/RedirectHandler.js +118 -118
  117. package/dist/interaction_handler/SilentHandler.d.ts +47 -47
  118. package/dist/interaction_handler/SilentHandler.js +162 -162
  119. package/dist/internals.d.ts +23 -23
  120. package/dist/internals.js +4 -4
  121. package/dist/navigation/INavigationClient.d.ts +16 -16
  122. package/dist/navigation/NavigationClient.d.ts +22 -22
  123. package/dist/navigation/NavigationClient.js +40 -40
  124. package/dist/navigation/NavigationOptions.d.ts +12 -12
  125. package/dist/network/FetchClient.d.ts +26 -26
  126. package/dist/network/FetchClient.js +99 -99
  127. package/dist/network/XhrClient.d.ts +40 -40
  128. package/dist/network/XhrClient.js +117 -117
  129. package/dist/operatingcontext/BaseOperatingContext.d.ts +40 -40
  130. package/dist/operatingcontext/BaseOperatingContext.js +44 -44
  131. package/dist/operatingcontext/StandardOperatingContext.d.ts +25 -25
  132. package/dist/operatingcontext/StandardOperatingContext.js +43 -43
  133. package/dist/operatingcontext/TeamsAppOperatingContext.d.ts +25 -25
  134. package/dist/operatingcontext/TeamsAppOperatingContext.js +42 -42
  135. package/dist/packageMetadata.d.ts +2 -2
  136. package/dist/packageMetadata.d.ts.map +1 -1
  137. package/dist/packageMetadata.js +4 -4
  138. package/dist/request/AuthorizationCodeRequest.d.ts +8 -8
  139. package/dist/request/AuthorizationUrlRequest.d.ts +8 -8
  140. package/dist/request/EndSessionPopupRequest.d.ts +18 -18
  141. package/dist/request/EndSessionRequest.d.ts +15 -15
  142. package/dist/request/PopupRequest.d.ts +32 -32
  143. package/dist/request/PopupWindowAttributes.d.ts +15 -15
  144. package/dist/request/RedirectRequest.d.ts +33 -33
  145. package/dist/request/SilentRequest.d.ts +30 -30
  146. package/dist/request/SsoSilentRequest.d.ts +26 -26
  147. package/dist/telemetry/BrowserPerformanceClient.d.ts +37 -38
  148. package/dist/telemetry/BrowserPerformanceClient.d.ts.map +1 -1
  149. package/dist/telemetry/BrowserPerformanceClient.js +124 -124
  150. package/dist/telemetry/BrowserPerformanceClient.js.map +1 -1
  151. package/dist/telemetry/BrowserPerformanceMeasurement.d.ts +21 -21
  152. package/dist/telemetry/BrowserPerformanceMeasurement.js +92 -92
  153. package/dist/utils/BrowserConstants.d.ts +176 -166
  154. package/dist/utils/BrowserConstants.d.ts.map +1 -1
  155. package/dist/utils/BrowserConstants.js +205 -215
  156. package/dist/utils/BrowserConstants.js.map +1 -1
  157. package/dist/utils/BrowserProtocolUtils.d.ts +18 -18
  158. package/dist/utils/BrowserProtocolUtils.js +34 -34
  159. package/dist/utils/BrowserStringUtils.d.ts +26 -26
  160. package/dist/utils/BrowserStringUtils.js +149 -149
  161. package/dist/utils/BrowserUtils.d.ts +65 -65
  162. package/dist/utils/BrowserUtils.js +138 -138
  163. package/dist/utils/MathUtils.d.ts +11 -11
  164. package/dist/utils/MathUtils.js +21 -21
  165. package/lib/msal-browser.cjs.js +18227 -0
  166. package/lib/msal-browser.cjs.js.map +1 -0
  167. package/lib/msal-browser.js +18233 -0
  168. package/lib/msal-browser.js.map +1 -0
  169. package/lib/msal-browser.min.js +63 -0
  170. package/package.json +101 -95
  171. package/dist/crypto/MsBrowserCrypto.d.ts +0 -10
  172. package/dist/crypto/MsBrowserCrypto.d.ts.map +0 -1
  173. package/dist/crypto/MsBrowserCrypto.js +0 -88
  174. package/dist/crypto/MsBrowserCrypto.js.map +0 -1
  175. package/dist/crypto/MsrBrowserCrypto.d.ts +0 -18
  176. package/dist/crypto/MsrBrowserCrypto.d.ts.map +0 -1
  177. package/dist/crypto/MsrBrowserCrypto.js +0 -35
  178. package/dist/crypto/MsrBrowserCrypto.js.map +0 -1
@@ -1,64 +1,64 @@
1
- import { Logger, AuthenticationScheme, IPerformanceClient, ICrypto } from "@azure/msal-common";
2
- import { NativeExtensionRequestBody } from "./NativeRequest";
3
- import { BrowserConfiguration } from "../../config/Configuration";
4
- export declare class NativeMessageHandler {
5
- private extensionId;
6
- private extensionVersion;
7
- private logger;
8
- private crypto;
9
- private readonly handshakeTimeoutMs;
10
- private timeoutId;
11
- private resolvers;
12
- private handshakeResolvers;
13
- private messageChannel;
14
- private readonly windowListener;
15
- private readonly performanceClient;
16
- private readonly handshakeEvent;
17
- constructor(logger: Logger, handshakeTimeoutMs: number, performanceClient: IPerformanceClient, crypto: ICrypto, extensionId?: string);
18
- /**
19
- * Sends a given message to the extension and resolves with the extension response
20
- * @param body
21
- */
22
- sendMessage(body: NativeExtensionRequestBody): Promise<object>;
23
- /**
24
- * Returns an instance of the MessageHandler that has successfully established a connection with an extension
25
- * @param {Logger} logger
26
- * @param {number} handshakeTimeoutMs
27
- * @param {IPerformanceClient} performanceClient
28
- * @param {ICrypto} crypto
29
- */
30
- static createProvider(logger: Logger, handshakeTimeoutMs: number, performanceClient: IPerformanceClient, crypto: ICrypto): Promise<NativeMessageHandler>;
31
- /**
32
- * Send handshake request helper.
33
- */
34
- private sendHandshakeRequest;
35
- /**
36
- * Invoked when a message is posted to the window. If a handshake request is received it means the extension is not installed.
37
- * @param event
38
- */
39
- private onWindowMessage;
40
- /**
41
- * Invoked when a message is received from the extension on the MessageChannel port
42
- * @param event
43
- */
44
- private onChannelMessage;
45
- /**
46
- * Returns the Id for the browser extension this handler is communicating with
47
- * @returns
48
- */
49
- getExtensionId(): string | undefined;
50
- /**
51
- * Returns the version for the browser extension this handler is communicating with
52
- * @returns
53
- */
54
- getExtensionVersion(): string | undefined;
55
- /**
56
- * Returns boolean indicating whether or not the request should attempt to use native broker
57
- * @param logger
58
- * @param config
59
- * @param nativeExtensionProvider
60
- * @param authenticationScheme
61
- */
62
- static isNativeAvailable(config: BrowserConfiguration, logger: Logger, nativeExtensionProvider?: NativeMessageHandler, authenticationScheme?: AuthenticationScheme): boolean;
63
- }
1
+ import { Logger, AuthenticationScheme, IPerformanceClient, ICrypto } from "@azure/msal-common";
2
+ import { NativeExtensionRequestBody } from "./NativeRequest";
3
+ import { BrowserConfiguration } from "../../config/Configuration";
4
+ export declare class NativeMessageHandler {
5
+ private extensionId;
6
+ private extensionVersion;
7
+ private logger;
8
+ private crypto;
9
+ private readonly handshakeTimeoutMs;
10
+ private timeoutId;
11
+ private resolvers;
12
+ private handshakeResolvers;
13
+ private messageChannel;
14
+ private readonly windowListener;
15
+ private readonly performanceClient;
16
+ private readonly handshakeEvent;
17
+ constructor(logger: Logger, handshakeTimeoutMs: number, performanceClient: IPerformanceClient, crypto: ICrypto, extensionId?: string);
18
+ /**
19
+ * Sends a given message to the extension and resolves with the extension response
20
+ * @param body
21
+ */
22
+ sendMessage(body: NativeExtensionRequestBody): Promise<object>;
23
+ /**
24
+ * Returns an instance of the MessageHandler that has successfully established a connection with an extension
25
+ * @param {Logger} logger
26
+ * @param {number} handshakeTimeoutMs
27
+ * @param {IPerformanceClient} performanceClient
28
+ * @param {ICrypto} crypto
29
+ */
30
+ static createProvider(logger: Logger, handshakeTimeoutMs: number, performanceClient: IPerformanceClient, crypto: ICrypto): Promise<NativeMessageHandler>;
31
+ /**
32
+ * Send handshake request helper.
33
+ */
34
+ private sendHandshakeRequest;
35
+ /**
36
+ * Invoked when a message is posted to the window. If a handshake request is received it means the extension is not installed.
37
+ * @param event
38
+ */
39
+ private onWindowMessage;
40
+ /**
41
+ * Invoked when a message is received from the extension on the MessageChannel port
42
+ * @param event
43
+ */
44
+ private onChannelMessage;
45
+ /**
46
+ * Returns the Id for the browser extension this handler is communicating with
47
+ * @returns
48
+ */
49
+ getExtensionId(): string | undefined;
50
+ /**
51
+ * Returns the version for the browser extension this handler is communicating with
52
+ * @returns
53
+ */
54
+ getExtensionVersion(): string | undefined;
55
+ /**
56
+ * Returns boolean indicating whether or not the request should attempt to use native broker
57
+ * @param logger
58
+ * @param config
59
+ * @param nativeExtensionProvider
60
+ * @param authenticationScheme
61
+ */
62
+ static isNativeAvailable(config: BrowserConfiguration, logger: Logger, nativeExtensionProvider?: NativeMessageHandler, authenticationScheme?: AuthenticationScheme): boolean;
63
+ }
64
64
  //# sourceMappingURL=NativeMessageHandler.d.ts.map
@@ -1,264 +1,264 @@
1
- /*! @azure/msal-browser v3.0.0-alpha.1 2023-05-08 */
1
+ /*! @azure/msal-browser v3.0.0-beta.0 2023-06-19 */
2
2
  'use strict';
3
3
  import { NativeConstants, NativeExtensionMethod } from '../../utils/BrowserConstants.js';
4
4
  import { PerformanceEvents, AuthError, AuthenticationScheme } from '@azure/msal-common';
5
5
  import { NativeAuthError } from '../../error/NativeAuthError.js';
6
6
  import { BrowserAuthError } from '../../error/BrowserAuthError.js';
7
7
 
8
- /*
9
- * Copyright (c) Microsoft Corporation. All rights reserved.
10
- * Licensed under the MIT License.
11
- */
12
- class NativeMessageHandler {
13
- constructor(logger, handshakeTimeoutMs, performanceClient, crypto, extensionId) {
14
- this.logger = logger;
15
- this.handshakeTimeoutMs = handshakeTimeoutMs;
16
- this.extensionId = extensionId;
17
- this.resolvers = new Map(); // Used for non-handshake messages
18
- this.handshakeResolvers = new Map(); // Used for handshake messages
19
- this.messageChannel = new MessageChannel();
20
- this.windowListener = this.onWindowMessage.bind(this); // Window event callback doesn't have access to 'this' unless it's bound
21
- this.performanceClient = performanceClient;
22
- this.handshakeEvent = performanceClient.startMeasurement(PerformanceEvents.NativeMessageHandlerHandshake);
23
- this.crypto = crypto;
24
- }
25
- /**
26
- * Sends a given message to the extension and resolves with the extension response
27
- * @param body
28
- */
29
- async sendMessage(body) {
30
- this.logger.trace("NativeMessageHandler - sendMessage called.");
31
- const req = {
32
- channel: NativeConstants.CHANNEL_ID,
33
- extensionId: this.extensionId,
34
- responseId: this.crypto.createNewGuid(),
35
- body: body,
36
- };
37
- this.logger.trace("NativeMessageHandler - Sending request to browser extension");
38
- this.logger.tracePii(`NativeMessageHandler - Sending request to browser extension: ${JSON.stringify(req)}`);
39
- this.messageChannel.port1.postMessage(req);
40
- return new Promise((resolve, reject) => {
41
- this.resolvers.set(req.responseId, { resolve, reject });
42
- });
43
- }
44
- /**
45
- * Returns an instance of the MessageHandler that has successfully established a connection with an extension
46
- * @param {Logger} logger
47
- * @param {number} handshakeTimeoutMs
48
- * @param {IPerformanceClient} performanceClient
49
- * @param {ICrypto} crypto
50
- */
51
- static async createProvider(logger, handshakeTimeoutMs, performanceClient, crypto) {
52
- logger.trace("NativeMessageHandler - createProvider called.");
53
- try {
54
- const preferredProvider = new NativeMessageHandler(logger, handshakeTimeoutMs, performanceClient, crypto, NativeConstants.PREFERRED_EXTENSION_ID);
55
- await preferredProvider.sendHandshakeRequest();
56
- return preferredProvider;
57
- }
58
- catch (e) {
59
- // If preferred extension fails for whatever reason, fallback to using any installed extension
60
- const backupProvider = new NativeMessageHandler(logger, handshakeTimeoutMs, performanceClient, crypto);
61
- await backupProvider.sendHandshakeRequest();
62
- return backupProvider;
63
- }
64
- }
65
- /**
66
- * Send handshake request helper.
67
- */
68
- async sendHandshakeRequest() {
69
- this.logger.trace("NativeMessageHandler - sendHandshakeRequest called.");
70
- // Register this event listener before sending handshake
71
- window.addEventListener("message", this.windowListener, false); // false is important, because content script message processing should work first
72
- const req = {
73
- channel: NativeConstants.CHANNEL_ID,
74
- extensionId: this.extensionId,
75
- responseId: this.crypto.createNewGuid(),
76
- body: {
77
- method: NativeExtensionMethod.HandshakeRequest,
78
- },
79
- };
80
- this.handshakeEvent.addStaticFields({
81
- extensionId: this.extensionId,
82
- extensionHandshakeTimeoutMs: this.handshakeTimeoutMs,
83
- });
84
- this.messageChannel.port1.onmessage = (event) => {
85
- this.onChannelMessage(event);
86
- };
87
- window.postMessage(req, window.origin, [this.messageChannel.port2]);
88
- return new Promise((resolve, reject) => {
89
- this.handshakeResolvers.set(req.responseId, { resolve, reject });
90
- this.timeoutId = window.setTimeout(() => {
91
- /*
92
- * Throw an error if neither HandshakeResponse nor original Handshake request are received in a reasonable timeframe.
93
- * This typically suggests an event handler stopped propagation of the Handshake request but did not respond to it on the MessageChannel port
94
- */
95
- window.removeEventListener("message", this.windowListener, false);
96
- this.messageChannel.port1.close();
97
- this.messageChannel.port2.close();
98
- this.handshakeEvent.endMeasurement({
99
- extensionHandshakeTimedOut: true,
100
- success: false,
101
- });
102
- reject(BrowserAuthError.createNativeHandshakeTimeoutError());
103
- this.handshakeResolvers.delete(req.responseId);
104
- }, this.handshakeTimeoutMs); // Use a reasonable timeout in milliseconds here
105
- });
106
- }
107
- /**
108
- * Invoked when a message is posted to the window. If a handshake request is received it means the extension is not installed.
109
- * @param event
110
- */
111
- onWindowMessage(event) {
112
- this.logger.trace("NativeMessageHandler - onWindowMessage called");
113
- // We only accept messages from ourselves
114
- if (event.source !== window) {
115
- return;
116
- }
117
- const request = event.data;
118
- if (!request.channel ||
119
- request.channel !== NativeConstants.CHANNEL_ID) {
120
- return;
121
- }
122
- if (request.extensionId && request.extensionId !== this.extensionId) {
123
- return;
124
- }
125
- if (request.body.method === NativeExtensionMethod.HandshakeRequest) {
126
- const handshakeResolver = this.handshakeResolvers.get(request.responseId);
127
- /*
128
- * Filter out responses with no matched resolvers sooner to keep channel ports open while waiting for
129
- * the proper response.
130
- */
131
- if (!handshakeResolver) {
132
- this.logger.trace(`NativeMessageHandler.onWindowMessage - resolver can't be found for request ${request.responseId}`);
133
- return;
134
- }
135
- // If we receive this message back it means no extension intercepted the request, meaning no extension supporting handshake protocol is installed
136
- this.logger.verbose(request.extensionId
137
- ? `Extension with id: ${request.extensionId} not installed`
138
- : "No extension installed");
139
- clearTimeout(this.timeoutId);
140
- this.messageChannel.port1.close();
141
- this.messageChannel.port2.close();
142
- window.removeEventListener("message", this.windowListener, false);
143
- this.handshakeEvent.endMeasurement({
144
- success: false,
145
- extensionInstalled: false,
146
- });
147
- handshakeResolver.reject(BrowserAuthError.createNativeExtensionNotInstalledError());
148
- }
149
- }
150
- /**
151
- * Invoked when a message is received from the extension on the MessageChannel port
152
- * @param event
153
- */
154
- onChannelMessage(event) {
155
- this.logger.trace("NativeMessageHandler - onChannelMessage called.");
156
- const request = event.data;
157
- const resolver = this.resolvers.get(request.responseId);
158
- const handshakeResolver = this.handshakeResolvers.get(request.responseId);
159
- try {
160
- const method = request.body.method;
161
- if (method === NativeExtensionMethod.Response) {
162
- if (!resolver) {
163
- return;
164
- }
165
- const response = request.body.response;
166
- this.logger.trace("NativeMessageHandler - Received response from browser extension");
167
- this.logger.tracePii(`NativeMessageHandler - Received response from browser extension: ${JSON.stringify(response)}`);
168
- if (response.status !== "Success") {
169
- resolver.reject(NativeAuthError.createError(response.code, response.description, response.ext));
170
- }
171
- else if (response.result) {
172
- if (response.result["code"] &&
173
- response.result["description"]) {
174
- resolver.reject(NativeAuthError.createError(response.result["code"], response.result["description"], response.result["ext"]));
175
- }
176
- else {
177
- resolver.resolve(response.result);
178
- }
179
- }
180
- else {
181
- throw AuthError.createUnexpectedError("Event does not contain result.");
182
- }
183
- this.resolvers.delete(request.responseId);
184
- }
185
- else if (method === NativeExtensionMethod.HandshakeResponse) {
186
- if (!handshakeResolver) {
187
- this.logger.trace(`NativeMessageHandler.onChannelMessage - resolver can't be found for request ${request.responseId}`);
188
- return;
189
- }
190
- clearTimeout(this.timeoutId); // Clear setTimeout
191
- window.removeEventListener("message", this.windowListener, false); // Remove 'No extension' listener
192
- this.extensionId = request.extensionId;
193
- this.extensionVersion = request.body.version;
194
- this.logger.verbose(`NativeMessageHandler - Received HandshakeResponse from extension: ${this.extensionId}`);
195
- this.handshakeEvent.endMeasurement({
196
- extensionInstalled: true,
197
- success: true,
198
- });
199
- handshakeResolver.resolve();
200
- this.handshakeResolvers.delete(request.responseId);
201
- }
202
- // Do nothing if method is not Response or HandshakeResponse
203
- }
204
- catch (err) {
205
- this.logger.error("Error parsing response from WAM Extension");
206
- this.logger.errorPii(`Error parsing response from WAM Extension: ${err}`);
207
- this.logger.errorPii(`Unable to parse ${event}`);
208
- if (resolver) {
209
- resolver.reject(err);
210
- }
211
- else if (handshakeResolver) {
212
- handshakeResolver.reject(err);
213
- }
214
- }
215
- }
216
- /**
217
- * Returns the Id for the browser extension this handler is communicating with
218
- * @returns
219
- */
220
- getExtensionId() {
221
- return this.extensionId;
222
- }
223
- /**
224
- * Returns the version for the browser extension this handler is communicating with
225
- * @returns
226
- */
227
- getExtensionVersion() {
228
- return this.extensionVersion;
229
- }
230
- /**
231
- * Returns boolean indicating whether or not the request should attempt to use native broker
232
- * @param logger
233
- * @param config
234
- * @param nativeExtensionProvider
235
- * @param authenticationScheme
236
- */
237
- static isNativeAvailable(config, logger, nativeExtensionProvider, authenticationScheme) {
238
- logger.trace("isNativeAvailable called");
239
- if (!config.system.allowNativeBroker) {
240
- logger.trace("isNativeAvailable: allowNativeBroker is not enabled, returning false");
241
- // Developer disabled WAM
242
- return false;
243
- }
244
- if (!nativeExtensionProvider) {
245
- logger.trace("isNativeAvailable: WAM extension provider is not initialized, returning false");
246
- // Extension is not available
247
- return false;
248
- }
249
- if (authenticationScheme) {
250
- switch (authenticationScheme) {
251
- case AuthenticationScheme.BEARER:
252
- case AuthenticationScheme.POP:
253
- logger.trace("isNativeAvailable: authenticationScheme is supported, returning true");
254
- return true;
255
- default:
256
- logger.trace("isNativeAvailable: authenticationScheme is not supported, returning false");
257
- return false;
258
- }
259
- }
260
- return true;
261
- }
8
+ /*
9
+ * Copyright (c) Microsoft Corporation. All rights reserved.
10
+ * Licensed under the MIT License.
11
+ */
12
+ class NativeMessageHandler {
13
+ constructor(logger, handshakeTimeoutMs, performanceClient, crypto, extensionId) {
14
+ this.logger = logger;
15
+ this.handshakeTimeoutMs = handshakeTimeoutMs;
16
+ this.extensionId = extensionId;
17
+ this.resolvers = new Map(); // Used for non-handshake messages
18
+ this.handshakeResolvers = new Map(); // Used for handshake messages
19
+ this.messageChannel = new MessageChannel();
20
+ this.windowListener = this.onWindowMessage.bind(this); // Window event callback doesn't have access to 'this' unless it's bound
21
+ this.performanceClient = performanceClient;
22
+ this.handshakeEvent = performanceClient.startMeasurement(PerformanceEvents.NativeMessageHandlerHandshake);
23
+ this.crypto = crypto;
24
+ }
25
+ /**
26
+ * Sends a given message to the extension and resolves with the extension response
27
+ * @param body
28
+ */
29
+ async sendMessage(body) {
30
+ this.logger.trace("NativeMessageHandler - sendMessage called.");
31
+ const req = {
32
+ channel: NativeConstants.CHANNEL_ID,
33
+ extensionId: this.extensionId,
34
+ responseId: this.crypto.createNewGuid(),
35
+ body: body,
36
+ };
37
+ this.logger.trace("NativeMessageHandler - Sending request to browser extension");
38
+ this.logger.tracePii(`NativeMessageHandler - Sending request to browser extension: ${JSON.stringify(req)}`);
39
+ this.messageChannel.port1.postMessage(req);
40
+ return new Promise((resolve, reject) => {
41
+ this.resolvers.set(req.responseId, { resolve, reject });
42
+ });
43
+ }
44
+ /**
45
+ * Returns an instance of the MessageHandler that has successfully established a connection with an extension
46
+ * @param {Logger} logger
47
+ * @param {number} handshakeTimeoutMs
48
+ * @param {IPerformanceClient} performanceClient
49
+ * @param {ICrypto} crypto
50
+ */
51
+ static async createProvider(logger, handshakeTimeoutMs, performanceClient, crypto) {
52
+ logger.trace("NativeMessageHandler - createProvider called.");
53
+ try {
54
+ const preferredProvider = new NativeMessageHandler(logger, handshakeTimeoutMs, performanceClient, crypto, NativeConstants.PREFERRED_EXTENSION_ID);
55
+ await preferredProvider.sendHandshakeRequest();
56
+ return preferredProvider;
57
+ }
58
+ catch (e) {
59
+ // If preferred extension fails for whatever reason, fallback to using any installed extension
60
+ const backupProvider = new NativeMessageHandler(logger, handshakeTimeoutMs, performanceClient, crypto);
61
+ await backupProvider.sendHandshakeRequest();
62
+ return backupProvider;
63
+ }
64
+ }
65
+ /**
66
+ * Send handshake request helper.
67
+ */
68
+ async sendHandshakeRequest() {
69
+ this.logger.trace("NativeMessageHandler - sendHandshakeRequest called.");
70
+ // Register this event listener before sending handshake
71
+ window.addEventListener("message", this.windowListener, false); // false is important, because content script message processing should work first
72
+ const req = {
73
+ channel: NativeConstants.CHANNEL_ID,
74
+ extensionId: this.extensionId,
75
+ responseId: this.crypto.createNewGuid(),
76
+ body: {
77
+ method: NativeExtensionMethod.HandshakeRequest,
78
+ },
79
+ };
80
+ this.handshakeEvent.addStaticFields({
81
+ extensionId: this.extensionId,
82
+ extensionHandshakeTimeoutMs: this.handshakeTimeoutMs,
83
+ });
84
+ this.messageChannel.port1.onmessage = (event) => {
85
+ this.onChannelMessage(event);
86
+ };
87
+ window.postMessage(req, window.origin, [this.messageChannel.port2]);
88
+ return new Promise((resolve, reject) => {
89
+ this.handshakeResolvers.set(req.responseId, { resolve, reject });
90
+ this.timeoutId = window.setTimeout(() => {
91
+ /*
92
+ * Throw an error if neither HandshakeResponse nor original Handshake request are received in a reasonable timeframe.
93
+ * This typically suggests an event handler stopped propagation of the Handshake request but did not respond to it on the MessageChannel port
94
+ */
95
+ window.removeEventListener("message", this.windowListener, false);
96
+ this.messageChannel.port1.close();
97
+ this.messageChannel.port2.close();
98
+ this.handshakeEvent.endMeasurement({
99
+ extensionHandshakeTimedOut: true,
100
+ success: false,
101
+ });
102
+ reject(BrowserAuthError.createNativeHandshakeTimeoutError());
103
+ this.handshakeResolvers.delete(req.responseId);
104
+ }, this.handshakeTimeoutMs); // Use a reasonable timeout in milliseconds here
105
+ });
106
+ }
107
+ /**
108
+ * Invoked when a message is posted to the window. If a handshake request is received it means the extension is not installed.
109
+ * @param event
110
+ */
111
+ onWindowMessage(event) {
112
+ this.logger.trace("NativeMessageHandler - onWindowMessage called");
113
+ // We only accept messages from ourselves
114
+ if (event.source !== window) {
115
+ return;
116
+ }
117
+ const request = event.data;
118
+ if (!request.channel ||
119
+ request.channel !== NativeConstants.CHANNEL_ID) {
120
+ return;
121
+ }
122
+ if (request.extensionId && request.extensionId !== this.extensionId) {
123
+ return;
124
+ }
125
+ if (request.body.method === NativeExtensionMethod.HandshakeRequest) {
126
+ const handshakeResolver = this.handshakeResolvers.get(request.responseId);
127
+ /*
128
+ * Filter out responses with no matched resolvers sooner to keep channel ports open while waiting for
129
+ * the proper response.
130
+ */
131
+ if (!handshakeResolver) {
132
+ this.logger.trace(`NativeMessageHandler.onWindowMessage - resolver can't be found for request ${request.responseId}`);
133
+ return;
134
+ }
135
+ // If we receive this message back it means no extension intercepted the request, meaning no extension supporting handshake protocol is installed
136
+ this.logger.verbose(request.extensionId
137
+ ? `Extension with id: ${request.extensionId} not installed`
138
+ : "No extension installed");
139
+ clearTimeout(this.timeoutId);
140
+ this.messageChannel.port1.close();
141
+ this.messageChannel.port2.close();
142
+ window.removeEventListener("message", this.windowListener, false);
143
+ this.handshakeEvent.endMeasurement({
144
+ success: false,
145
+ extensionInstalled: false,
146
+ });
147
+ handshakeResolver.reject(BrowserAuthError.createNativeExtensionNotInstalledError());
148
+ }
149
+ }
150
+ /**
151
+ * Invoked when a message is received from the extension on the MessageChannel port
152
+ * @param event
153
+ */
154
+ onChannelMessage(event) {
155
+ this.logger.trace("NativeMessageHandler - onChannelMessage called.");
156
+ const request = event.data;
157
+ const resolver = this.resolvers.get(request.responseId);
158
+ const handshakeResolver = this.handshakeResolvers.get(request.responseId);
159
+ try {
160
+ const method = request.body.method;
161
+ if (method === NativeExtensionMethod.Response) {
162
+ if (!resolver) {
163
+ return;
164
+ }
165
+ const response = request.body.response;
166
+ this.logger.trace("NativeMessageHandler - Received response from browser extension");
167
+ this.logger.tracePii(`NativeMessageHandler - Received response from browser extension: ${JSON.stringify(response)}`);
168
+ if (response.status !== "Success") {
169
+ resolver.reject(NativeAuthError.createError(response.code, response.description, response.ext));
170
+ }
171
+ else if (response.result) {
172
+ if (response.result["code"] &&
173
+ response.result["description"]) {
174
+ resolver.reject(NativeAuthError.createError(response.result["code"], response.result["description"], response.result["ext"]));
175
+ }
176
+ else {
177
+ resolver.resolve(response.result);
178
+ }
179
+ }
180
+ else {
181
+ throw AuthError.createUnexpectedError("Event does not contain result.");
182
+ }
183
+ this.resolvers.delete(request.responseId);
184
+ }
185
+ else if (method === NativeExtensionMethod.HandshakeResponse) {
186
+ if (!handshakeResolver) {
187
+ this.logger.trace(`NativeMessageHandler.onChannelMessage - resolver can't be found for request ${request.responseId}`);
188
+ return;
189
+ }
190
+ clearTimeout(this.timeoutId); // Clear setTimeout
191
+ window.removeEventListener("message", this.windowListener, false); // Remove 'No extension' listener
192
+ this.extensionId = request.extensionId;
193
+ this.extensionVersion = request.body.version;
194
+ this.logger.verbose(`NativeMessageHandler - Received HandshakeResponse from extension: ${this.extensionId}`);
195
+ this.handshakeEvent.endMeasurement({
196
+ extensionInstalled: true,
197
+ success: true,
198
+ });
199
+ handshakeResolver.resolve();
200
+ this.handshakeResolvers.delete(request.responseId);
201
+ }
202
+ // Do nothing if method is not Response or HandshakeResponse
203
+ }
204
+ catch (err) {
205
+ this.logger.error("Error parsing response from WAM Extension");
206
+ this.logger.errorPii(`Error parsing response from WAM Extension: ${err}`);
207
+ this.logger.errorPii(`Unable to parse ${event}`);
208
+ if (resolver) {
209
+ resolver.reject(err);
210
+ }
211
+ else if (handshakeResolver) {
212
+ handshakeResolver.reject(err);
213
+ }
214
+ }
215
+ }
216
+ /**
217
+ * Returns the Id for the browser extension this handler is communicating with
218
+ * @returns
219
+ */
220
+ getExtensionId() {
221
+ return this.extensionId;
222
+ }
223
+ /**
224
+ * Returns the version for the browser extension this handler is communicating with
225
+ * @returns
226
+ */
227
+ getExtensionVersion() {
228
+ return this.extensionVersion;
229
+ }
230
+ /**
231
+ * Returns boolean indicating whether or not the request should attempt to use native broker
232
+ * @param logger
233
+ * @param config
234
+ * @param nativeExtensionProvider
235
+ * @param authenticationScheme
236
+ */
237
+ static isNativeAvailable(config, logger, nativeExtensionProvider, authenticationScheme) {
238
+ logger.trace("isNativeAvailable called");
239
+ if (!config.system.allowNativeBroker) {
240
+ logger.trace("isNativeAvailable: allowNativeBroker is not enabled, returning false");
241
+ // Developer disabled WAM
242
+ return false;
243
+ }
244
+ if (!nativeExtensionProvider) {
245
+ logger.trace("isNativeAvailable: WAM extension provider is not initialized, returning false");
246
+ // Extension is not available
247
+ return false;
248
+ }
249
+ if (authenticationScheme) {
250
+ switch (authenticationScheme) {
251
+ case AuthenticationScheme.BEARER:
252
+ case AuthenticationScheme.POP:
253
+ logger.trace("isNativeAvailable: authenticationScheme is supported, returning true");
254
+ return true;
255
+ default:
256
+ logger.trace("isNativeAvailable: authenticationScheme is not supported, returning false");
257
+ return false;
258
+ }
259
+ }
260
+ return true;
261
+ }
262
262
  }
263
263
 
264
264
  export { NativeMessageHandler };