@azure/msal-angular 2.5.5 → 2.5.6

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 (40) hide show
  1. package/IMsalService.d.ts +15 -15
  2. package/LICENSE +20 -20
  3. package/README.md +151 -151
  4. package/azure-msal-angular.d.ts +4 -4
  5. package/azure-msal-angular.metadata.json +1 -1
  6. package/bundles/azure-msal-angular.umd.js +1025 -1025
  7. package/bundles/azure-msal-angular.umd.js.map +1 -1
  8. package/bundles/azure-msal-angular.umd.min.js +1 -1
  9. package/bundles/azure-msal-angular.umd.min.js.map +1 -1
  10. package/constants.d.ts +5 -5
  11. package/esm2015/IMsalService.js +6 -6
  12. package/esm2015/azure-msal-angular.js +4 -4
  13. package/esm2015/constants.js +10 -10
  14. package/esm2015/msal.broadcast.config.js +6 -6
  15. package/esm2015/msal.broadcast.service.js +46 -46
  16. package/esm2015/msal.guard.config.js +6 -6
  17. package/esm2015/msal.guard.js +189 -189
  18. package/esm2015/msal.interceptor.config.js +6 -6
  19. package/esm2015/msal.interceptor.js +230 -230
  20. package/esm2015/msal.module.js +46 -46
  21. package/esm2015/msal.navigation.client.js +53 -53
  22. package/esm2015/msal.redirect.component.js +33 -33
  23. package/esm2015/msal.service.js +77 -77
  24. package/esm2015/packageMetadata.js +4 -4
  25. package/esm2015/public-api.js +18 -18
  26. package/fesm2015/azure-msal-angular.js +626 -626
  27. package/fesm2015/azure-msal-angular.js.map +1 -1
  28. package/msal.broadcast.config.d.ts +3 -3
  29. package/msal.broadcast.service.d.ts +14 -14
  30. package/msal.guard.config.d.ts +9 -9
  31. package/msal.guard.d.ts +40 -40
  32. package/msal.interceptor.config.d.ts +17 -17
  33. package/msal.interceptor.d.ts +59 -59
  34. package/msal.module.d.ts +7 -7
  35. package/msal.navigation.client.d.ts +16 -16
  36. package/msal.redirect.component.d.ts +12 -12
  37. package/msal.service.d.ts +28 -28
  38. package/package.json +2 -2
  39. package/packageMetadata.d.ts +2 -2
  40. package/public-api.d.ts +17 -17
@@ -6,651 +6,651 @@ import { Router } from '@angular/router';
6
6
  import { map, concatMap, catchError, switchMap, take, filter } from 'rxjs/operators';
7
7
  import { __awaiter } from 'tslib';
8
8
 
9
- /*
10
- * Copyright (c) Microsoft Corporation. All rights reserved.
11
- * Licensed under the MIT License.
12
- */
13
- const MSAL_INSTANCE = new InjectionToken("MSAL_INSTANCE");
14
- const MSAL_GUARD_CONFIG = new InjectionToken("MSAL_GUARD_CONFIG");
15
- const MSAL_INTERCEPTOR_CONFIG = new InjectionToken("MSAL_INTERCEPTOR_CONFIG");
9
+ /*
10
+ * Copyright (c) Microsoft Corporation. All rights reserved.
11
+ * Licensed under the MIT License.
12
+ */
13
+ const MSAL_INSTANCE = new InjectionToken("MSAL_INSTANCE");
14
+ const MSAL_GUARD_CONFIG = new InjectionToken("MSAL_GUARD_CONFIG");
15
+ const MSAL_INTERCEPTOR_CONFIG = new InjectionToken("MSAL_INTERCEPTOR_CONFIG");
16
16
  const MSAL_BROADCAST_CONFIG = new InjectionToken("MSAL_BROADCAST_CONFIG");
17
17
 
18
- /* eslint-disable header/header */
19
- const name = "@azure/msal-angular";
20
- const version = "2.5.5";
18
+ /* eslint-disable header/header */
19
+ const name = "@azure/msal-angular";
20
+ const version = "2.5.6";
21
21
 
22
- /*
23
- * Copyright (c) Microsoft Corporation. All rights reserved.
24
- * Licensed under the MIT License.
25
- */
26
- class MsalService {
27
- constructor(instance, location) {
28
- this.instance = instance;
29
- this.location = location;
30
- const hash = this.location.path(true).split("#").pop();
31
- if (hash) {
32
- this.redirectHash = `#${hash}`;
33
- }
34
- this.instance.initializeWrapperLibrary(WrapperSKU.Angular, version);
35
- }
36
- initialize() {
37
- return from(this.instance.initialize());
38
- }
39
- acquireTokenPopup(request) {
40
- return from(this.instance.acquireTokenPopup(request));
41
- }
42
- acquireTokenRedirect(request) {
43
- return from(this.instance.acquireTokenRedirect(request));
44
- }
45
- acquireTokenSilent(silentRequest) {
46
- return from(this.instance.acquireTokenSilent(silentRequest));
47
- }
48
- handleRedirectObservable(hash) {
49
- return from(this.instance.handleRedirectPromise(hash || this.redirectHash));
50
- }
51
- loginPopup(request) {
52
- return from(this.instance.loginPopup(request));
53
- }
54
- loginRedirect(request) {
55
- return from(this.instance.loginRedirect(request));
56
- }
57
- logout(logoutRequest) {
58
- return from(this.instance.logout(logoutRequest));
59
- }
60
- logoutRedirect(logoutRequest) {
61
- return from(this.instance.logoutRedirect(logoutRequest));
62
- }
63
- logoutPopup(logoutRequest) {
64
- return from(this.instance.logoutPopup(logoutRequest));
65
- }
66
- ssoSilent(request) {
67
- return from(this.instance.ssoSilent(request));
68
- }
69
- /**
70
- * Gets logger for msal-angular.
71
- * If no logger set, returns logger instance created with same options as msal-browser
72
- */
73
- getLogger() {
74
- if (!this.logger) {
75
- this.logger = this.instance.getLogger().clone(name, version);
76
- }
77
- return this.logger;
78
- }
79
- // Create a logger instance for msal-angular with the same options as msal-browser
80
- setLogger(logger) {
81
- this.logger = logger.clone(name, version);
82
- this.instance.setLogger(logger);
83
- }
84
- }
85
- MsalService.decorators = [
86
- { type: Injectable }
87
- ];
88
- MsalService.ctorParameters = () => [
89
- { type: undefined, decorators: [{ type: Inject, args: [MSAL_INSTANCE,] }] },
90
- { type: Location }
22
+ /*
23
+ * Copyright (c) Microsoft Corporation. All rights reserved.
24
+ * Licensed under the MIT License.
25
+ */
26
+ class MsalService {
27
+ constructor(instance, location) {
28
+ this.instance = instance;
29
+ this.location = location;
30
+ const hash = this.location.path(true).split("#").pop();
31
+ if (hash) {
32
+ this.redirectHash = `#${hash}`;
33
+ }
34
+ this.instance.initializeWrapperLibrary(WrapperSKU.Angular, version);
35
+ }
36
+ initialize() {
37
+ return from(this.instance.initialize());
38
+ }
39
+ acquireTokenPopup(request) {
40
+ return from(this.instance.acquireTokenPopup(request));
41
+ }
42
+ acquireTokenRedirect(request) {
43
+ return from(this.instance.acquireTokenRedirect(request));
44
+ }
45
+ acquireTokenSilent(silentRequest) {
46
+ return from(this.instance.acquireTokenSilent(silentRequest));
47
+ }
48
+ handleRedirectObservable(hash) {
49
+ return from(this.instance.handleRedirectPromise(hash || this.redirectHash));
50
+ }
51
+ loginPopup(request) {
52
+ return from(this.instance.loginPopup(request));
53
+ }
54
+ loginRedirect(request) {
55
+ return from(this.instance.loginRedirect(request));
56
+ }
57
+ logout(logoutRequest) {
58
+ return from(this.instance.logout(logoutRequest));
59
+ }
60
+ logoutRedirect(logoutRequest) {
61
+ return from(this.instance.logoutRedirect(logoutRequest));
62
+ }
63
+ logoutPopup(logoutRequest) {
64
+ return from(this.instance.logoutPopup(logoutRequest));
65
+ }
66
+ ssoSilent(request) {
67
+ return from(this.instance.ssoSilent(request));
68
+ }
69
+ /**
70
+ * Gets logger for msal-angular.
71
+ * If no logger set, returns logger instance created with same options as msal-browser
72
+ */
73
+ getLogger() {
74
+ if (!this.logger) {
75
+ this.logger = this.instance.getLogger().clone(name, version);
76
+ }
77
+ return this.logger;
78
+ }
79
+ // Create a logger instance for msal-angular with the same options as msal-browser
80
+ setLogger(logger) {
81
+ this.logger = logger.clone(name, version);
82
+ this.instance.setLogger(logger);
83
+ }
84
+ }
85
+ MsalService.decorators = [
86
+ { type: Injectable }
87
+ ];
88
+ MsalService.ctorParameters = () => [
89
+ { type: undefined, decorators: [{ type: Inject, args: [MSAL_INSTANCE,] }] },
90
+ { type: Location }
91
91
  ];
92
92
 
93
- /*
94
- * Copyright (c) Microsoft Corporation. All rights reserved.
95
- * Licensed under the MIT License.
96
- */
97
- class MsalBroadcastService {
98
- constructor(msalInstance, authService, msalBroadcastConfig) {
99
- this.msalInstance = msalInstance;
100
- this.authService = authService;
101
- this.msalBroadcastConfig = msalBroadcastConfig;
102
- // Make _msalSubject a ReplaySubject if configured to replay past events
103
- if (this.msalBroadcastConfig && this.msalBroadcastConfig.eventsToReplay > 0) {
104
- this.authService.getLogger().verbose(`BroadcastService - replayPastEvents set on BroadcastConfig, replaying the last ${this.msalBroadcastConfig.eventsToReplay} events`);
105
- this._msalSubject = new ReplaySubject(this.msalBroadcastConfig.eventsToReplay);
106
- }
107
- else {
108
- // Defaults to _msalSubject being a Subject
109
- this._msalSubject = new Subject();
110
- }
111
- this.msalSubject$ = this._msalSubject.asObservable();
112
- // InProgress as BehaviorSubject so most recent inProgress state will be available upon subscription
113
- this._inProgress = new BehaviorSubject(InteractionStatus.Startup);
114
- this.inProgress$ = this._inProgress.asObservable();
115
- this.msalInstance.addEventCallback((message) => {
116
- this._msalSubject.next(message);
117
- const status = EventMessageUtils.getInteractionStatusFromEvent(message, this._inProgress.value);
118
- if (status !== null) {
119
- this.authService.getLogger().verbose(`BroadcastService - ${message.eventType} results in setting inProgress from ${this._inProgress.value} to ${status}`);
120
- this._inProgress.next(status);
121
- }
122
- });
123
- }
124
- }
125
- MsalBroadcastService.decorators = [
126
- { type: Injectable }
127
- ];
128
- MsalBroadcastService.ctorParameters = () => [
129
- { type: undefined, decorators: [{ type: Inject, args: [MSAL_INSTANCE,] }] },
130
- { type: MsalService },
131
- { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [MSAL_BROADCAST_CONFIG,] }] }
93
+ /*
94
+ * Copyright (c) Microsoft Corporation. All rights reserved.
95
+ * Licensed under the MIT License.
96
+ */
97
+ class MsalBroadcastService {
98
+ constructor(msalInstance, authService, msalBroadcastConfig) {
99
+ this.msalInstance = msalInstance;
100
+ this.authService = authService;
101
+ this.msalBroadcastConfig = msalBroadcastConfig;
102
+ // Make _msalSubject a ReplaySubject if configured to replay past events
103
+ if (this.msalBroadcastConfig && this.msalBroadcastConfig.eventsToReplay > 0) {
104
+ this.authService.getLogger().verbose(`BroadcastService - replayPastEvents set on BroadcastConfig, replaying the last ${this.msalBroadcastConfig.eventsToReplay} events`);
105
+ this._msalSubject = new ReplaySubject(this.msalBroadcastConfig.eventsToReplay);
106
+ }
107
+ else {
108
+ // Defaults to _msalSubject being a Subject
109
+ this._msalSubject = new Subject();
110
+ }
111
+ this.msalSubject$ = this._msalSubject.asObservable();
112
+ // InProgress as BehaviorSubject so most recent inProgress state will be available upon subscription
113
+ this._inProgress = new BehaviorSubject(InteractionStatus.Startup);
114
+ this.inProgress$ = this._inProgress.asObservable();
115
+ this.msalInstance.addEventCallback((message) => {
116
+ this._msalSubject.next(message);
117
+ const status = EventMessageUtils.getInteractionStatusFromEvent(message, this._inProgress.value);
118
+ if (status !== null) {
119
+ this.authService.getLogger().verbose(`BroadcastService - ${message.eventType} results in setting inProgress from ${this._inProgress.value} to ${status}`);
120
+ this._inProgress.next(status);
121
+ }
122
+ });
123
+ }
124
+ }
125
+ MsalBroadcastService.decorators = [
126
+ { type: Injectable }
127
+ ];
128
+ MsalBroadcastService.ctorParameters = () => [
129
+ { type: undefined, decorators: [{ type: Inject, args: [MSAL_INSTANCE,] }] },
130
+ { type: MsalService },
131
+ { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [MSAL_BROADCAST_CONFIG,] }] }
132
132
  ];
133
133
 
134
- /*
135
- * Copyright (c) Microsoft Corporation. All rights reserved.
136
- * Licensed under the MIT License.
137
- */
138
- class MsalGuard {
139
- constructor(msalGuardConfig, msalBroadcastService, authService, location, router) {
140
- this.msalGuardConfig = msalGuardConfig;
141
- this.msalBroadcastService = msalBroadcastService;
142
- this.authService = authService;
143
- this.location = location;
144
- this.router = router;
145
- // Subscribing so events in MsalGuard will set inProgress$ observable
146
- this.msalBroadcastService.inProgress$.subscribe();
147
- }
148
- /**
149
- * Parses url string to UrlTree
150
- * @param url
151
- */
152
- parseUrl(url) {
153
- return this.router.parseUrl(url);
154
- }
155
- /**
156
- * Builds the absolute url for the destination page
157
- * @param path Relative path of requested page
158
- * @returns Full destination url
159
- */
160
- getDestinationUrl(path) {
161
- this.authService.getLogger().verbose("Guard - getting destination url");
162
- // Absolute base url for the application (default to origin if base element not present)
163
- const baseElements = document.getElementsByTagName("base");
164
- const baseUrl = this.location.normalize(baseElements.length ? baseElements[0].href : window.location.origin);
165
- // Path of page (including hash, if using hash routing)
166
- const pathUrl = this.location.prepareExternalUrl(path);
167
- // Hash location strategy
168
- if (pathUrl.startsWith("#")) {
169
- this.authService.getLogger().verbose("Guard - destination by hash routing");
170
- return `${baseUrl}/${pathUrl}`;
171
- }
172
- /*
173
- * If using path location strategy, pathUrl will include the relative portion of the base path (e.g. /base/page).
174
- * Since baseUrl also includes /base, can just concatentate baseUrl + path
175
- */
176
- return `${baseUrl}${path}`;
177
- }
178
- /**
179
- * Interactively prompt the user to login
180
- * @param url Path of the requested page
181
- */
182
- loginInteractively(state) {
183
- const authRequest = typeof this.msalGuardConfig.authRequest === "function"
184
- ? this.msalGuardConfig.authRequest(this.authService, state)
185
- : Object.assign({}, this.msalGuardConfig.authRequest);
186
- if (this.msalGuardConfig.interactionType === InteractionType.Popup) {
187
- this.authService.getLogger().verbose("Guard - logging in by popup");
188
- return this.authService.loginPopup(authRequest)
189
- .pipe(map((response) => {
190
- this.authService.getLogger().verbose("Guard - login by popup successful, can activate, setting active account");
191
- this.authService.instance.setActiveAccount(response.account);
192
- return true;
193
- }));
194
- }
195
- this.authService.getLogger().verbose("Guard - logging in by redirect");
196
- const redirectStartPage = this.getDestinationUrl(state.url);
197
- return this.authService.loginRedirect(Object.assign({ redirectStartPage }, authRequest))
198
- .pipe(map(() => false));
199
- }
200
- /**
201
- * Helper which checks for the correct interaction type, prevents page with Guard to be set as reidrect, and calls handleRedirectObservable
202
- * @param state
203
- */
204
- activateHelper(state) {
205
- if (this.msalGuardConfig.interactionType !== InteractionType.Popup && this.msalGuardConfig.interactionType !== InteractionType.Redirect) {
206
- throw new BrowserConfigurationAuthError("invalid_interaction_type", "Invalid interaction type provided to MSAL Guard. InteractionType.Popup or InteractionType.Redirect must be provided in the MsalGuardConfiguration");
207
- }
208
- this.authService.getLogger().verbose("MSAL Guard activated");
209
- /*
210
- * If a page with MSAL Guard is set as the redirect for acquireTokenSilent,
211
- * short-circuit to prevent redirecting or popups.
212
- */
213
- if (typeof window !== "undefined") {
214
- if (UrlString.hashContainsKnownProperties(window.location.hash) && BrowserUtils.isInIframe() && !this.authService.instance.getConfiguration().system.allowRedirectInIframe) {
215
- this.authService.getLogger().warning("Guard - redirectUri set to page with MSAL Guard. It is recommended to not set redirectUri to a page that requires authentication.");
216
- return of(false);
217
- }
218
- }
219
- else {
220
- this.authService.getLogger().info("Guard - window is undefined, MSAL does not support server-side token acquisition");
221
- return of(true);
222
- }
223
- /**
224
- * If a loginFailedRoute is set in the config, set this as the loginFailedRoute
225
- */
226
- if (this.msalGuardConfig.loginFailedRoute) {
227
- this.loginFailedRoute = this.parseUrl(this.msalGuardConfig.loginFailedRoute);
228
- }
229
- // Capture current path before it gets changed by handleRedirectObservable
230
- const currentPath = this.location.path(true);
231
- return this.authService.handleRedirectObservable()
232
- .pipe(concatMap(() => {
233
- if (!this.authService.instance.getAllAccounts().length) {
234
- if (state) {
235
- this.authService.getLogger().verbose("Guard - no accounts retrieved, log in required to activate");
236
- return this.loginInteractively(state);
237
- }
238
- this.authService.getLogger().verbose("Guard - no accounts retrieved, no state, cannot load");
239
- return of(false);
240
- }
241
- this.authService.getLogger().verbose("Guard - at least 1 account exists, can activate or load");
242
- // Prevent navigating the app to /#code= or /code=
243
- if (state) {
244
- /*
245
- * Path routing:
246
- * state.url: /#code=...
247
- * state.root.fragment: code=...
248
- */
249
- /*
250
- * Hash routing:
251
- * state.url: /code
252
- * state.root.fragment: null
253
- */
254
- const urlContainsCode = this.includesCode(state.url);
255
- const fragmentContainsCode = !!state.root && !!state.root.fragment && this.includesCode(`#${state.root.fragment}`);
256
- const hashRouting = this.location.prepareExternalUrl(state.url).indexOf("#") === 0;
257
- // Ensure code parameter is in fragment (and not in query parameter), or that hash hash routing is used
258
- if (urlContainsCode && (fragmentContainsCode || hashRouting)) {
259
- this.authService.getLogger().info("Guard - Hash contains known code response, stopping navigation.");
260
- // Path routing (navigate to current path without hash)
261
- if (currentPath.indexOf("#") > -1) {
262
- return of(this.parseUrl(this.location.path()));
263
- }
264
- // Hash routing (navigate to root path)
265
- return of(this.parseUrl(""));
266
- }
267
- }
268
- return of(true);
269
- }), catchError((error) => {
270
- this.authService.getLogger().error("Guard - error while logging in, unable to activate");
271
- this.authService.getLogger().errorPii(`Guard - error: ${error.message}`);
272
- /**
273
- * If a loginFailedRoute is set, checks to see if Angular 10+ is used and state is passed in before returning route
274
- * Apps using Angular 9 will receive of(false) in canLoad interface, as it does not support UrlTree return types
275
- */
276
- if (this.loginFailedRoute && parseInt(VERSION.major, 10) > 9 && state) {
277
- this.authService.getLogger().verbose("Guard - loginFailedRoute set, redirecting");
278
- return of(this.loginFailedRoute);
279
- }
280
- return of(false);
281
- }));
282
- }
283
- includesCode(path) {
284
- return (path.lastIndexOf("/code") > -1 &&
285
- path.lastIndexOf("/code") === path.length - "/code".length) || // path.endsWith("/code")
286
- path.indexOf("#code=") > -1 ||
287
- path.indexOf("&code=") > -1;
288
- }
289
- canActivate(route, state) {
290
- this.authService.getLogger().verbose("Guard - canActivate");
291
- return this.activateHelper(state);
292
- }
293
- canActivateChild(route, state) {
294
- this.authService.getLogger().verbose("Guard - canActivateChild");
295
- return this.activateHelper(state);
296
- }
297
- canLoad() {
298
- this.authService.getLogger().verbose("Guard - canLoad");
299
- // @ts-ignore
300
- return this.activateHelper();
301
- }
302
- }
303
- MsalGuard.decorators = [
304
- { type: Injectable }
305
- ];
306
- MsalGuard.ctorParameters = () => [
307
- { type: undefined, decorators: [{ type: Inject, args: [MSAL_GUARD_CONFIG,] }] },
308
- { type: MsalBroadcastService },
309
- { type: MsalService },
310
- { type: Location },
311
- { type: Router }
134
+ /*
135
+ * Copyright (c) Microsoft Corporation. All rights reserved.
136
+ * Licensed under the MIT License.
137
+ */
138
+ class MsalGuard {
139
+ constructor(msalGuardConfig, msalBroadcastService, authService, location, router) {
140
+ this.msalGuardConfig = msalGuardConfig;
141
+ this.msalBroadcastService = msalBroadcastService;
142
+ this.authService = authService;
143
+ this.location = location;
144
+ this.router = router;
145
+ // Subscribing so events in MsalGuard will set inProgress$ observable
146
+ this.msalBroadcastService.inProgress$.subscribe();
147
+ }
148
+ /**
149
+ * Parses url string to UrlTree
150
+ * @param url
151
+ */
152
+ parseUrl(url) {
153
+ return this.router.parseUrl(url);
154
+ }
155
+ /**
156
+ * Builds the absolute url for the destination page
157
+ * @param path Relative path of requested page
158
+ * @returns Full destination url
159
+ */
160
+ getDestinationUrl(path) {
161
+ this.authService.getLogger().verbose("Guard - getting destination url");
162
+ // Absolute base url for the application (default to origin if base element not present)
163
+ const baseElements = document.getElementsByTagName("base");
164
+ const baseUrl = this.location.normalize(baseElements.length ? baseElements[0].href : window.location.origin);
165
+ // Path of page (including hash, if using hash routing)
166
+ const pathUrl = this.location.prepareExternalUrl(path);
167
+ // Hash location strategy
168
+ if (pathUrl.startsWith("#")) {
169
+ this.authService.getLogger().verbose("Guard - destination by hash routing");
170
+ return `${baseUrl}/${pathUrl}`;
171
+ }
172
+ /*
173
+ * If using path location strategy, pathUrl will include the relative portion of the base path (e.g. /base/page).
174
+ * Since baseUrl also includes /base, can just concatentate baseUrl + path
175
+ */
176
+ return `${baseUrl}${path}`;
177
+ }
178
+ /**
179
+ * Interactively prompt the user to login
180
+ * @param url Path of the requested page
181
+ */
182
+ loginInteractively(state) {
183
+ const authRequest = typeof this.msalGuardConfig.authRequest === "function"
184
+ ? this.msalGuardConfig.authRequest(this.authService, state)
185
+ : Object.assign({}, this.msalGuardConfig.authRequest);
186
+ if (this.msalGuardConfig.interactionType === InteractionType.Popup) {
187
+ this.authService.getLogger().verbose("Guard - logging in by popup");
188
+ return this.authService.loginPopup(authRequest)
189
+ .pipe(map((response) => {
190
+ this.authService.getLogger().verbose("Guard - login by popup successful, can activate, setting active account");
191
+ this.authService.instance.setActiveAccount(response.account);
192
+ return true;
193
+ }));
194
+ }
195
+ this.authService.getLogger().verbose("Guard - logging in by redirect");
196
+ const redirectStartPage = this.getDestinationUrl(state.url);
197
+ return this.authService.loginRedirect(Object.assign({ redirectStartPage }, authRequest))
198
+ .pipe(map(() => false));
199
+ }
200
+ /**
201
+ * Helper which checks for the correct interaction type, prevents page with Guard to be set as reidrect, and calls handleRedirectObservable
202
+ * @param state
203
+ */
204
+ activateHelper(state) {
205
+ if (this.msalGuardConfig.interactionType !== InteractionType.Popup && this.msalGuardConfig.interactionType !== InteractionType.Redirect) {
206
+ throw new BrowserConfigurationAuthError("invalid_interaction_type", "Invalid interaction type provided to MSAL Guard. InteractionType.Popup or InteractionType.Redirect must be provided in the MsalGuardConfiguration");
207
+ }
208
+ this.authService.getLogger().verbose("MSAL Guard activated");
209
+ /*
210
+ * If a page with MSAL Guard is set as the redirect for acquireTokenSilent,
211
+ * short-circuit to prevent redirecting or popups.
212
+ */
213
+ if (typeof window !== "undefined") {
214
+ if (UrlString.hashContainsKnownProperties(window.location.hash) && BrowserUtils.isInIframe() && !this.authService.instance.getConfiguration().system.allowRedirectInIframe) {
215
+ this.authService.getLogger().warning("Guard - redirectUri set to page with MSAL Guard. It is recommended to not set redirectUri to a page that requires authentication.");
216
+ return of(false);
217
+ }
218
+ }
219
+ else {
220
+ this.authService.getLogger().info("Guard - window is undefined, MSAL does not support server-side token acquisition");
221
+ return of(true);
222
+ }
223
+ /**
224
+ * If a loginFailedRoute is set in the config, set this as the loginFailedRoute
225
+ */
226
+ if (this.msalGuardConfig.loginFailedRoute) {
227
+ this.loginFailedRoute = this.parseUrl(this.msalGuardConfig.loginFailedRoute);
228
+ }
229
+ // Capture current path before it gets changed by handleRedirectObservable
230
+ const currentPath = this.location.path(true);
231
+ return this.authService.handleRedirectObservable()
232
+ .pipe(concatMap(() => {
233
+ if (!this.authService.instance.getAllAccounts().length) {
234
+ if (state) {
235
+ this.authService.getLogger().verbose("Guard - no accounts retrieved, log in required to activate");
236
+ return this.loginInteractively(state);
237
+ }
238
+ this.authService.getLogger().verbose("Guard - no accounts retrieved, no state, cannot load");
239
+ return of(false);
240
+ }
241
+ this.authService.getLogger().verbose("Guard - at least 1 account exists, can activate or load");
242
+ // Prevent navigating the app to /#code= or /code=
243
+ if (state) {
244
+ /*
245
+ * Path routing:
246
+ * state.url: /#code=...
247
+ * state.root.fragment: code=...
248
+ */
249
+ /*
250
+ * Hash routing:
251
+ * state.url: /code
252
+ * state.root.fragment: null
253
+ */
254
+ const urlContainsCode = this.includesCode(state.url);
255
+ const fragmentContainsCode = !!state.root && !!state.root.fragment && this.includesCode(`#${state.root.fragment}`);
256
+ const hashRouting = this.location.prepareExternalUrl(state.url).indexOf("#") === 0;
257
+ // Ensure code parameter is in fragment (and not in query parameter), or that hash hash routing is used
258
+ if (urlContainsCode && (fragmentContainsCode || hashRouting)) {
259
+ this.authService.getLogger().info("Guard - Hash contains known code response, stopping navigation.");
260
+ // Path routing (navigate to current path without hash)
261
+ if (currentPath.indexOf("#") > -1) {
262
+ return of(this.parseUrl(this.location.path()));
263
+ }
264
+ // Hash routing (navigate to root path)
265
+ return of(this.parseUrl(""));
266
+ }
267
+ }
268
+ return of(true);
269
+ }), catchError((error) => {
270
+ this.authService.getLogger().error("Guard - error while logging in, unable to activate");
271
+ this.authService.getLogger().errorPii(`Guard - error: ${error.message}`);
272
+ /**
273
+ * If a loginFailedRoute is set, checks to see if Angular 10+ is used and state is passed in before returning route
274
+ * Apps using Angular 9 will receive of(false) in canLoad interface, as it does not support UrlTree return types
275
+ */
276
+ if (this.loginFailedRoute && parseInt(VERSION.major, 10) > 9 && state) {
277
+ this.authService.getLogger().verbose("Guard - loginFailedRoute set, redirecting");
278
+ return of(this.loginFailedRoute);
279
+ }
280
+ return of(false);
281
+ }));
282
+ }
283
+ includesCode(path) {
284
+ return (path.lastIndexOf("/code") > -1 &&
285
+ path.lastIndexOf("/code") === path.length - "/code".length) || // path.endsWith("/code")
286
+ path.indexOf("#code=") > -1 ||
287
+ path.indexOf("&code=") > -1;
288
+ }
289
+ canActivate(route, state) {
290
+ this.authService.getLogger().verbose("Guard - canActivate");
291
+ return this.activateHelper(state);
292
+ }
293
+ canActivateChild(route, state) {
294
+ this.authService.getLogger().verbose("Guard - canActivateChild");
295
+ return this.activateHelper(state);
296
+ }
297
+ canLoad() {
298
+ this.authService.getLogger().verbose("Guard - canLoad");
299
+ // @ts-ignore
300
+ return this.activateHelper();
301
+ }
302
+ }
303
+ MsalGuard.decorators = [
304
+ { type: Injectable }
305
+ ];
306
+ MsalGuard.ctorParameters = () => [
307
+ { type: undefined, decorators: [{ type: Inject, args: [MSAL_GUARD_CONFIG,] }] },
308
+ { type: MsalBroadcastService },
309
+ { type: MsalService },
310
+ { type: Location },
311
+ { type: Router }
312
312
  ];
313
313
 
314
- /*
315
- * Copyright (c) Microsoft Corporation. All rights reserved.
316
- * Licensed under the MIT License.
317
- */
318
- class MsalInterceptor {
319
- constructor(msalInterceptorConfig, authService, location, msalBroadcastService,
320
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
321
- document) {
322
- this.msalInterceptorConfig = msalInterceptorConfig;
323
- this.authService = authService;
324
- this.location = location;
325
- this.msalBroadcastService = msalBroadcastService;
326
- this._document = document;
327
- }
328
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
329
- intercept(req, next) {
330
- if (this.msalInterceptorConfig.interactionType !== InteractionType.Popup && this.msalInterceptorConfig.interactionType !== InteractionType.Redirect) {
331
- throw new BrowserConfigurationAuthError("invalid_interaction_type", "Invalid interaction type provided to MSAL Interceptor. InteractionType.Popup, InteractionType.Redirect must be provided in the msalInterceptorConfiguration");
332
- }
333
- this.authService.getLogger().verbose("MSAL Interceptor activated");
334
- const scopes = this.getScopesForEndpoint(req.url, req.method);
335
- // If no scopes for endpoint, does not acquire token
336
- if (!scopes || scopes.length === 0) {
337
- this.authService.getLogger().verbose("Interceptor - no scopes for endpoint");
338
- return next.handle(req);
339
- }
340
- // Sets account as active account or first account
341
- let account;
342
- if (!!this.authService.instance.getActiveAccount()) {
343
- this.authService.getLogger().verbose("Interceptor - active account selected");
344
- account = this.authService.instance.getActiveAccount();
345
- }
346
- else {
347
- this.authService.getLogger().verbose("Interceptor - no active account, fallback to first account");
348
- account = this.authService.instance.getAllAccounts()[0];
349
- }
350
- const authRequest = typeof this.msalInterceptorConfig.authRequest === "function"
351
- ? this.msalInterceptorConfig.authRequest(this.authService, req, { account: account })
352
- : Object.assign(Object.assign({}, this.msalInterceptorConfig.authRequest), { account });
353
- this.authService.getLogger().info(`Interceptor - ${scopes.length} scopes found for endpoint`);
354
- this.authService.getLogger().infoPii(`Interceptor - [${scopes}] scopes found for ${req.url}`);
355
- return this.acquireToken(authRequest, scopes, account)
356
- .pipe(switchMap((result) => {
357
- this.authService.getLogger().verbose("Interceptor - setting authorization headers");
358
- const headers = req.headers
359
- .set("Authorization", `Bearer ${result.accessToken}`);
360
- const requestClone = req.clone({ headers });
361
- return next.handle(requestClone);
362
- }));
363
- }
364
- /**
365
- * Try to acquire token silently. Invoke interaction if acquireTokenSilent rejected with error or resolved with null access token
366
- * @param authRequest Request
367
- * @param scopes Array of scopes for the request
368
- * @param account Account
369
- * @returns Authentication result
370
- */
371
- acquireToken(authRequest, scopes, account) {
372
- // Note: For MSA accounts, include openid scope when calling acquireTokenSilent to return idToken
373
- return this.authService.acquireTokenSilent(Object.assign(Object.assign({}, authRequest), { scopes, account }))
374
- .pipe(catchError(() => {
375
- this.authService.getLogger().error("Interceptor - acquireTokenSilent rejected with error. Invoking interaction to resolve.");
376
- return this.msalBroadcastService.inProgress$
377
- .pipe(take(1), switchMap((status) => {
378
- if (status === InteractionStatus.None) {
379
- return this.acquireTokenInteractively(authRequest, scopes);
380
- }
381
- return this.msalBroadcastService.inProgress$
382
- .pipe(filter((status) => status === InteractionStatus.None), take(1), switchMap(() => this.acquireToken(authRequest, scopes, account)));
383
- }));
384
- }), switchMap((result) => {
385
- if (!result.accessToken) {
386
- this.authService.getLogger().error("Interceptor - acquireTokenSilent resolved with null access token. Known issue with B2C tenants, invoking interaction to resolve.");
387
- return this.msalBroadcastService.inProgress$
388
- .pipe(filter((status) => status === InteractionStatus.None), take(1), switchMap(() => this.acquireTokenInteractively(authRequest, scopes)));
389
- }
390
- return of(result);
391
- }));
392
- }
393
- /**
394
- * Invoke interaction for the given set of scopes
395
- * @param authRequest Request
396
- * @param scopes Array of scopes for the request
397
- * @returns Result from the interactive request
398
- */
399
- acquireTokenInteractively(authRequest, scopes) {
400
- if (this.msalInterceptorConfig.interactionType === InteractionType.Popup) {
401
- this.authService.getLogger().verbose("Interceptor - error acquiring token silently, acquiring by popup");
402
- return this.authService.acquireTokenPopup(Object.assign(Object.assign({}, authRequest), { scopes }));
403
- }
404
- this.authService.getLogger().verbose("Interceptor - error acquiring token silently, acquiring by redirect");
405
- const redirectStartPage = window.location.href;
406
- this.authService.acquireTokenRedirect(Object.assign(Object.assign({}, authRequest), { scopes, redirectStartPage }));
407
- return EMPTY;
408
- }
409
- /**
410
- * Looks up the scopes for the given endpoint from the protectedResourceMap
411
- * @param endpoint Url of the request
412
- * @param httpMethod Http method of the request
413
- * @returns Array of scopes, or null if not found
414
- *
415
- */
416
- getScopesForEndpoint(endpoint, httpMethod) {
417
- this.authService.getLogger().verbose("Interceptor - getting scopes for endpoint");
418
- // Ensures endpoints and protected resources compared are normalized
419
- const normalizedEndpoint = this.location.normalize(endpoint);
420
- const protectedResourcesArray = Array.from(this.msalInterceptorConfig.protectedResourceMap.keys());
421
- const matchingProtectedResources = this.matchResourcesToEndpoint(protectedResourcesArray, normalizedEndpoint);
422
- // Check absolute urls of resources first before checking relative to prevent incorrect matching where multiple resources have similar relative urls
423
- if (matchingProtectedResources.absoluteResources.length > 0) {
424
- return this.matchScopesToEndpoint(this.msalInterceptorConfig.protectedResourceMap, matchingProtectedResources.absoluteResources, httpMethod);
425
- }
426
- else if (matchingProtectedResources.relativeResources.length > 0) {
427
- return this.matchScopesToEndpoint(this.msalInterceptorConfig.protectedResourceMap, matchingProtectedResources.relativeResources, httpMethod);
428
- }
429
- return null;
430
- }
431
- /**
432
- * Finds resource endpoints that match request endpoint
433
- * @param protectedResourcesEndpoints
434
- * @param endpoint
435
- * @returns
436
- */
437
- matchResourcesToEndpoint(protectedResourcesEndpoints, endpoint) {
438
- const matchingResources = { absoluteResources: [], relativeResources: [] };
439
- protectedResourcesEndpoints.forEach(key => {
440
- // Normalizes and adds resource to matchingResources.absoluteResources if key matches endpoint. StringUtils.matchPattern accounts for wildcards
441
- const normalizedKey = this.location.normalize(key);
442
- if (StringUtils.matchPattern(normalizedKey, endpoint)) {
443
- matchingResources.absoluteResources.push(key);
444
- }
445
- // Get url components for relative urls
446
- const absoluteKey = this.getAbsoluteUrl(key);
447
- const keyComponents = new UrlString(absoluteKey).getUrlComponents();
448
- const absoluteEndpoint = this.getAbsoluteUrl(endpoint);
449
- const endpointComponents = new UrlString(absoluteEndpoint).getUrlComponents();
450
- // Normalized key should include query strings if applicable
451
- const relativeNormalizedKey = keyComponents.QueryString ? `${keyComponents.AbsolutePath}?${keyComponents.QueryString}` : this.location.normalize(keyComponents.AbsolutePath);
452
- // Add resource to matchingResources.relativeResources if same origin, relativeKey matches endpoint, and is not empty
453
- if (keyComponents.HostNameAndPort === endpointComponents.HostNameAndPort && StringUtils.matchPattern(relativeNormalizedKey, absoluteEndpoint) && relativeNormalizedKey !== "" && relativeNormalizedKey !== "/*") {
454
- matchingResources.relativeResources.push(key);
455
- }
456
- });
457
- return matchingResources;
458
- }
459
- /**
460
- * Transforms relative urls to absolute urls
461
- * @param url
462
- * @returns
463
- */
464
- getAbsoluteUrl(url) {
465
- const link = this._document.createElement("a");
466
- link.href = url;
467
- return link.href;
468
- }
469
- /**
470
- * Finds scopes from first matching endpoint with HTTP method that matches request
471
- * @param protectedResourceMap Protected resource map
472
- * @param endpointArray Array of resources that match request endpoint
473
- * @param httpMethod Http method of the request
474
- * @returns
475
- */
476
- matchScopesToEndpoint(protectedResourceMap, endpointArray, httpMethod) {
477
- const allMatchedScopes = [];
478
- // Check each matched endpoint for matching HttpMethod and scopes
479
- endpointArray.forEach(matchedEndpoint => {
480
- const scopesForEndpoint = [];
481
- const methodAndScopesArray = protectedResourceMap.get(matchedEndpoint);
482
- // Return if resource is unprotected
483
- if (methodAndScopesArray === null) {
484
- allMatchedScopes.push(null);
485
- return;
486
- }
487
- methodAndScopesArray.forEach(entry => {
488
- // Entry is either array of scopes or ProtectedResourceScopes object
489
- if (typeof entry === "string") {
490
- scopesForEndpoint.push(entry);
491
- }
492
- else {
493
- // Ensure methods being compared are normalized
494
- const normalizedRequestMethod = httpMethod.toLowerCase();
495
- const normalizedResourceMethod = entry.httpMethod.toLowerCase();
496
- // Method in protectedResourceMap matches request http method
497
- if (normalizedResourceMethod === normalizedRequestMethod) {
498
- // Validate if scopes comes null to unprotect the resource in a certain http method
499
- if (entry.scopes === null) {
500
- allMatchedScopes.push(null);
501
- }
502
- else {
503
- entry.scopes.forEach((scope) => {
504
- scopesForEndpoint.push(scope);
505
- });
506
- }
507
- }
508
- }
509
- });
510
- // Only add to all scopes if scopes for endpoint and method is found
511
- if (scopesForEndpoint.length > 0) {
512
- allMatchedScopes.push(scopesForEndpoint);
513
- }
514
- });
515
- if (allMatchedScopes.length > 0) {
516
- if (allMatchedScopes.length > 1) {
517
- this.authService.getLogger().warning("Interceptor - More than 1 matching scopes for endpoint found.");
518
- }
519
- // Returns scopes for first matching endpoint
520
- return allMatchedScopes[0];
521
- }
522
- return null;
523
- }
524
- }
525
- MsalInterceptor.decorators = [
526
- { type: Injectable }
527
- ];
528
- MsalInterceptor.ctorParameters = () => [
529
- { type: undefined, decorators: [{ type: Inject, args: [MSAL_INTERCEPTOR_CONFIG,] }] },
530
- { type: MsalService },
531
- { type: Location },
532
- { type: MsalBroadcastService },
533
- { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
314
+ /*
315
+ * Copyright (c) Microsoft Corporation. All rights reserved.
316
+ * Licensed under the MIT License.
317
+ */
318
+ class MsalInterceptor {
319
+ constructor(msalInterceptorConfig, authService, location, msalBroadcastService,
320
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
321
+ document) {
322
+ this.msalInterceptorConfig = msalInterceptorConfig;
323
+ this.authService = authService;
324
+ this.location = location;
325
+ this.msalBroadcastService = msalBroadcastService;
326
+ this._document = document;
327
+ }
328
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
329
+ intercept(req, next) {
330
+ if (this.msalInterceptorConfig.interactionType !== InteractionType.Popup && this.msalInterceptorConfig.interactionType !== InteractionType.Redirect) {
331
+ throw new BrowserConfigurationAuthError("invalid_interaction_type", "Invalid interaction type provided to MSAL Interceptor. InteractionType.Popup, InteractionType.Redirect must be provided in the msalInterceptorConfiguration");
332
+ }
333
+ this.authService.getLogger().verbose("MSAL Interceptor activated");
334
+ const scopes = this.getScopesForEndpoint(req.url, req.method);
335
+ // If no scopes for endpoint, does not acquire token
336
+ if (!scopes || scopes.length === 0) {
337
+ this.authService.getLogger().verbose("Interceptor - no scopes for endpoint");
338
+ return next.handle(req);
339
+ }
340
+ // Sets account as active account or first account
341
+ let account;
342
+ if (!!this.authService.instance.getActiveAccount()) {
343
+ this.authService.getLogger().verbose("Interceptor - active account selected");
344
+ account = this.authService.instance.getActiveAccount();
345
+ }
346
+ else {
347
+ this.authService.getLogger().verbose("Interceptor - no active account, fallback to first account");
348
+ account = this.authService.instance.getAllAccounts()[0];
349
+ }
350
+ const authRequest = typeof this.msalInterceptorConfig.authRequest === "function"
351
+ ? this.msalInterceptorConfig.authRequest(this.authService, req, { account: account })
352
+ : Object.assign(Object.assign({}, this.msalInterceptorConfig.authRequest), { account });
353
+ this.authService.getLogger().info(`Interceptor - ${scopes.length} scopes found for endpoint`);
354
+ this.authService.getLogger().infoPii(`Interceptor - [${scopes}] scopes found for ${req.url}`);
355
+ return this.acquireToken(authRequest, scopes, account)
356
+ .pipe(switchMap((result) => {
357
+ this.authService.getLogger().verbose("Interceptor - setting authorization headers");
358
+ const headers = req.headers
359
+ .set("Authorization", `Bearer ${result.accessToken}`);
360
+ const requestClone = req.clone({ headers });
361
+ return next.handle(requestClone);
362
+ }));
363
+ }
364
+ /**
365
+ * Try to acquire token silently. Invoke interaction if acquireTokenSilent rejected with error or resolved with null access token
366
+ * @param authRequest Request
367
+ * @param scopes Array of scopes for the request
368
+ * @param account Account
369
+ * @returns Authentication result
370
+ */
371
+ acquireToken(authRequest, scopes, account) {
372
+ // Note: For MSA accounts, include openid scope when calling acquireTokenSilent to return idToken
373
+ return this.authService.acquireTokenSilent(Object.assign(Object.assign({}, authRequest), { scopes, account }))
374
+ .pipe(catchError(() => {
375
+ this.authService.getLogger().error("Interceptor - acquireTokenSilent rejected with error. Invoking interaction to resolve.");
376
+ return this.msalBroadcastService.inProgress$
377
+ .pipe(take(1), switchMap((status) => {
378
+ if (status === InteractionStatus.None) {
379
+ return this.acquireTokenInteractively(authRequest, scopes);
380
+ }
381
+ return this.msalBroadcastService.inProgress$
382
+ .pipe(filter((status) => status === InteractionStatus.None), take(1), switchMap(() => this.acquireToken(authRequest, scopes, account)));
383
+ }));
384
+ }), switchMap((result) => {
385
+ if (!result.accessToken) {
386
+ this.authService.getLogger().error("Interceptor - acquireTokenSilent resolved with null access token. Known issue with B2C tenants, invoking interaction to resolve.");
387
+ return this.msalBroadcastService.inProgress$
388
+ .pipe(filter((status) => status === InteractionStatus.None), take(1), switchMap(() => this.acquireTokenInteractively(authRequest, scopes)));
389
+ }
390
+ return of(result);
391
+ }));
392
+ }
393
+ /**
394
+ * Invoke interaction for the given set of scopes
395
+ * @param authRequest Request
396
+ * @param scopes Array of scopes for the request
397
+ * @returns Result from the interactive request
398
+ */
399
+ acquireTokenInteractively(authRequest, scopes) {
400
+ if (this.msalInterceptorConfig.interactionType === InteractionType.Popup) {
401
+ this.authService.getLogger().verbose("Interceptor - error acquiring token silently, acquiring by popup");
402
+ return this.authService.acquireTokenPopup(Object.assign(Object.assign({}, authRequest), { scopes }));
403
+ }
404
+ this.authService.getLogger().verbose("Interceptor - error acquiring token silently, acquiring by redirect");
405
+ const redirectStartPage = window.location.href;
406
+ this.authService.acquireTokenRedirect(Object.assign(Object.assign({}, authRequest), { scopes, redirectStartPage }));
407
+ return EMPTY;
408
+ }
409
+ /**
410
+ * Looks up the scopes for the given endpoint from the protectedResourceMap
411
+ * @param endpoint Url of the request
412
+ * @param httpMethod Http method of the request
413
+ * @returns Array of scopes, or null if not found
414
+ *
415
+ */
416
+ getScopesForEndpoint(endpoint, httpMethod) {
417
+ this.authService.getLogger().verbose("Interceptor - getting scopes for endpoint");
418
+ // Ensures endpoints and protected resources compared are normalized
419
+ const normalizedEndpoint = this.location.normalize(endpoint);
420
+ const protectedResourcesArray = Array.from(this.msalInterceptorConfig.protectedResourceMap.keys());
421
+ const matchingProtectedResources = this.matchResourcesToEndpoint(protectedResourcesArray, normalizedEndpoint);
422
+ // Check absolute urls of resources first before checking relative to prevent incorrect matching where multiple resources have similar relative urls
423
+ if (matchingProtectedResources.absoluteResources.length > 0) {
424
+ return this.matchScopesToEndpoint(this.msalInterceptorConfig.protectedResourceMap, matchingProtectedResources.absoluteResources, httpMethod);
425
+ }
426
+ else if (matchingProtectedResources.relativeResources.length > 0) {
427
+ return this.matchScopesToEndpoint(this.msalInterceptorConfig.protectedResourceMap, matchingProtectedResources.relativeResources, httpMethod);
428
+ }
429
+ return null;
430
+ }
431
+ /**
432
+ * Finds resource endpoints that match request endpoint
433
+ * @param protectedResourcesEndpoints
434
+ * @param endpoint
435
+ * @returns
436
+ */
437
+ matchResourcesToEndpoint(protectedResourcesEndpoints, endpoint) {
438
+ const matchingResources = { absoluteResources: [], relativeResources: [] };
439
+ protectedResourcesEndpoints.forEach(key => {
440
+ // Normalizes and adds resource to matchingResources.absoluteResources if key matches endpoint. StringUtils.matchPattern accounts for wildcards
441
+ const normalizedKey = this.location.normalize(key);
442
+ if (StringUtils.matchPattern(normalizedKey, endpoint)) {
443
+ matchingResources.absoluteResources.push(key);
444
+ }
445
+ // Get url components for relative urls
446
+ const absoluteKey = this.getAbsoluteUrl(key);
447
+ const keyComponents = new UrlString(absoluteKey).getUrlComponents();
448
+ const absoluteEndpoint = this.getAbsoluteUrl(endpoint);
449
+ const endpointComponents = new UrlString(absoluteEndpoint).getUrlComponents();
450
+ // Normalized key should include query strings if applicable
451
+ const relativeNormalizedKey = keyComponents.QueryString ? `${keyComponents.AbsolutePath}?${keyComponents.QueryString}` : this.location.normalize(keyComponents.AbsolutePath);
452
+ // Add resource to matchingResources.relativeResources if same origin, relativeKey matches endpoint, and is not empty
453
+ if (keyComponents.HostNameAndPort === endpointComponents.HostNameAndPort && StringUtils.matchPattern(relativeNormalizedKey, absoluteEndpoint) && relativeNormalizedKey !== "" && relativeNormalizedKey !== "/*") {
454
+ matchingResources.relativeResources.push(key);
455
+ }
456
+ });
457
+ return matchingResources;
458
+ }
459
+ /**
460
+ * Transforms relative urls to absolute urls
461
+ * @param url
462
+ * @returns
463
+ */
464
+ getAbsoluteUrl(url) {
465
+ const link = this._document.createElement("a");
466
+ link.href = url;
467
+ return link.href;
468
+ }
469
+ /**
470
+ * Finds scopes from first matching endpoint with HTTP method that matches request
471
+ * @param protectedResourceMap Protected resource map
472
+ * @param endpointArray Array of resources that match request endpoint
473
+ * @param httpMethod Http method of the request
474
+ * @returns
475
+ */
476
+ matchScopesToEndpoint(protectedResourceMap, endpointArray, httpMethod) {
477
+ const allMatchedScopes = [];
478
+ // Check each matched endpoint for matching HttpMethod and scopes
479
+ endpointArray.forEach(matchedEndpoint => {
480
+ const scopesForEndpoint = [];
481
+ const methodAndScopesArray = protectedResourceMap.get(matchedEndpoint);
482
+ // Return if resource is unprotected
483
+ if (methodAndScopesArray === null) {
484
+ allMatchedScopes.push(null);
485
+ return;
486
+ }
487
+ methodAndScopesArray.forEach(entry => {
488
+ // Entry is either array of scopes or ProtectedResourceScopes object
489
+ if (typeof entry === "string") {
490
+ scopesForEndpoint.push(entry);
491
+ }
492
+ else {
493
+ // Ensure methods being compared are normalized
494
+ const normalizedRequestMethod = httpMethod.toLowerCase();
495
+ const normalizedResourceMethod = entry.httpMethod.toLowerCase();
496
+ // Method in protectedResourceMap matches request http method
497
+ if (normalizedResourceMethod === normalizedRequestMethod) {
498
+ // Validate if scopes comes null to unprotect the resource in a certain http method
499
+ if (entry.scopes === null) {
500
+ allMatchedScopes.push(null);
501
+ }
502
+ else {
503
+ entry.scopes.forEach((scope) => {
504
+ scopesForEndpoint.push(scope);
505
+ });
506
+ }
507
+ }
508
+ }
509
+ });
510
+ // Only add to all scopes if scopes for endpoint and method is found
511
+ if (scopesForEndpoint.length > 0) {
512
+ allMatchedScopes.push(scopesForEndpoint);
513
+ }
514
+ });
515
+ if (allMatchedScopes.length > 0) {
516
+ if (allMatchedScopes.length > 1) {
517
+ this.authService.getLogger().warning("Interceptor - More than 1 matching scopes for endpoint found.");
518
+ }
519
+ // Returns scopes for first matching endpoint
520
+ return allMatchedScopes[0];
521
+ }
522
+ return null;
523
+ }
524
+ }
525
+ MsalInterceptor.decorators = [
526
+ { type: Injectable }
527
+ ];
528
+ MsalInterceptor.ctorParameters = () => [
529
+ { type: undefined, decorators: [{ type: Inject, args: [MSAL_INTERCEPTOR_CONFIG,] }] },
530
+ { type: MsalService },
531
+ { type: Location },
532
+ { type: MsalBroadcastService },
533
+ { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
534
534
  ];
535
535
 
536
- /*
537
- * Copyright (c) Microsoft Corporation. All rights reserved.
538
- * Licensed under the MIT License.
539
- */
540
- class MsalRedirectComponent {
541
- constructor(authService) {
542
- this.authService = authService;
543
- }
544
- ngOnInit() {
545
- this.authService.getLogger().verbose("MsalRedirectComponent activated");
546
- this.authService.initialize().pipe(concatMap(() => {
547
- return this.authService.handleRedirectObservable();
548
- })).subscribe();
549
- }
550
- }
551
- MsalRedirectComponent.decorators = [
552
- { type: Component, args: [{
553
- selector: "app-redirect",
554
- template: ""
555
- },] }
556
- ];
557
- MsalRedirectComponent.ctorParameters = () => [
558
- { type: MsalService }
536
+ /*
537
+ * Copyright (c) Microsoft Corporation. All rights reserved.
538
+ * Licensed under the MIT License.
539
+ */
540
+ class MsalRedirectComponent {
541
+ constructor(authService) {
542
+ this.authService = authService;
543
+ }
544
+ ngOnInit() {
545
+ this.authService.getLogger().verbose("MsalRedirectComponent activated");
546
+ this.authService.initialize().pipe(concatMap(() => {
547
+ return this.authService.handleRedirectObservable();
548
+ })).subscribe();
549
+ }
550
+ }
551
+ MsalRedirectComponent.decorators = [
552
+ { type: Component, args: [{
553
+ selector: "app-redirect",
554
+ template: ""
555
+ },] }
556
+ ];
557
+ MsalRedirectComponent.ctorParameters = () => [
558
+ { type: MsalService }
559
559
  ];
560
560
 
561
- /*
562
- * Copyright (c) Microsoft Corporation. All rights reserved.
563
- * Licensed under the MIT License.
564
- */
565
- class MsalModule {
566
- static forRoot(msalInstance, guardConfig, interceptorConfig) {
567
- return {
568
- ngModule: MsalModule,
569
- providers: [
570
- {
571
- provide: MSAL_INSTANCE,
572
- useValue: msalInstance
573
- },
574
- {
575
- provide: MSAL_GUARD_CONFIG,
576
- useValue: guardConfig
577
- },
578
- {
579
- provide: MSAL_INTERCEPTOR_CONFIG,
580
- useValue: interceptorConfig
581
- },
582
- MsalService
583
- ]
584
- };
585
- }
586
- }
587
- MsalModule.decorators = [
588
- { type: NgModule, args: [{
589
- declarations: [MsalRedirectComponent],
590
- imports: [
591
- CommonModule
592
- ],
593
- providers: [
594
- MsalGuard,
595
- MsalBroadcastService
596
- ]
597
- },] }
561
+ /*
562
+ * Copyright (c) Microsoft Corporation. All rights reserved.
563
+ * Licensed under the MIT License.
564
+ */
565
+ class MsalModule {
566
+ static forRoot(msalInstance, guardConfig, interceptorConfig) {
567
+ return {
568
+ ngModule: MsalModule,
569
+ providers: [
570
+ {
571
+ provide: MSAL_INSTANCE,
572
+ useValue: msalInstance
573
+ },
574
+ {
575
+ provide: MSAL_GUARD_CONFIG,
576
+ useValue: guardConfig
577
+ },
578
+ {
579
+ provide: MSAL_INTERCEPTOR_CONFIG,
580
+ useValue: interceptorConfig
581
+ },
582
+ MsalService
583
+ ]
584
+ };
585
+ }
586
+ }
587
+ MsalModule.decorators = [
588
+ { type: NgModule, args: [{
589
+ declarations: [MsalRedirectComponent],
590
+ imports: [
591
+ CommonModule
592
+ ],
593
+ providers: [
594
+ MsalGuard,
595
+ MsalBroadcastService
596
+ ]
597
+ },] }
598
598
  ];
599
599
 
600
- /*
601
- * Copyright (c) Microsoft Corporation. All rights reserved.
602
- * Licensed under the MIT License.
603
- */
604
- /**
605
- * Custom navigation used for Angular client-side navigation.
606
- * See performance doc for details:
607
- * https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/lib/msal-angular/docs/v2-docs/performance.md
608
- */
609
- class MsalCustomNavigationClient extends NavigationClient {
610
- constructor(authService, router, location) {
611
- super();
612
- this.authService = authService;
613
- this.router = router;
614
- this.location = location;
615
- }
616
- navigateInternal(url, options) {
617
- const _super = Object.create(null, {
618
- navigateInternal: { get: () => super.navigateInternal }
619
- });
620
- return __awaiter(this, void 0, void 0, function* () {
621
- this.authService.getLogger().trace("MsalCustomNavigationClient called");
622
- this.authService.getLogger().verbose("MsalCustomNavigationClient - navigating");
623
- this.authService.getLogger().verbosePii(`MsalCustomNavigationClient - navigating to url: ${url}`);
624
- // Prevent hash clearing from causing an issue with Client-side navigation after redirect is handled
625
- if (options.noHistory) {
626
- return _super.navigateInternal.call(this, url, options);
627
- }
628
- else {
629
- // Normalizing newUrl if no query string
630
- const urlComponents = new UrlString(url).getUrlComponents();
631
- const newUrl = urlComponents.QueryString ? `${urlComponents.AbsolutePath}?${urlComponents.QueryString}` : this.location.normalize(urlComponents.AbsolutePath);
632
- this.router.navigateByUrl(newUrl, { replaceUrl: options.noHistory });
633
- }
634
- return Promise.resolve(options.noHistory);
635
- });
636
- }
637
- }
638
- MsalCustomNavigationClient.decorators = [
639
- { type: Injectable }
640
- ];
641
- MsalCustomNavigationClient.ctorParameters = () => [
642
- { type: MsalService },
643
- { type: Router },
644
- { type: Location }
600
+ /*
601
+ * Copyright (c) Microsoft Corporation. All rights reserved.
602
+ * Licensed under the MIT License.
603
+ */
604
+ /**
605
+ * Custom navigation used for Angular client-side navigation.
606
+ * See performance doc for details:
607
+ * https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/lib/msal-angular/docs/v2-docs/performance.md
608
+ */
609
+ class MsalCustomNavigationClient extends NavigationClient {
610
+ constructor(authService, router, location) {
611
+ super();
612
+ this.authService = authService;
613
+ this.router = router;
614
+ this.location = location;
615
+ }
616
+ navigateInternal(url, options) {
617
+ const _super = Object.create(null, {
618
+ navigateInternal: { get: () => super.navigateInternal }
619
+ });
620
+ return __awaiter(this, void 0, void 0, function* () {
621
+ this.authService.getLogger().trace("MsalCustomNavigationClient called");
622
+ this.authService.getLogger().verbose("MsalCustomNavigationClient - navigating");
623
+ this.authService.getLogger().verbosePii(`MsalCustomNavigationClient - navigating to url: ${url}`);
624
+ // Prevent hash clearing from causing an issue with Client-side navigation after redirect is handled
625
+ if (options.noHistory) {
626
+ return _super.navigateInternal.call(this, url, options);
627
+ }
628
+ else {
629
+ // Normalizing newUrl if no query string
630
+ const urlComponents = new UrlString(url).getUrlComponents();
631
+ const newUrl = urlComponents.QueryString ? `${urlComponents.AbsolutePath}?${urlComponents.QueryString}` : this.location.normalize(urlComponents.AbsolutePath);
632
+ this.router.navigateByUrl(newUrl, { replaceUrl: options.noHistory });
633
+ }
634
+ return Promise.resolve(options.noHistory);
635
+ });
636
+ }
637
+ }
638
+ MsalCustomNavigationClient.decorators = [
639
+ { type: Injectable }
640
+ ];
641
+ MsalCustomNavigationClient.ctorParameters = () => [
642
+ { type: MsalService },
643
+ { type: Router },
644
+ { type: Location }
645
645
  ];
646
646
 
647
- /*
648
- * Copyright (c) Microsoft Corporation. All rights reserved.
649
- * Licensed under the MIT License.
647
+ /*
648
+ * Copyright (c) Microsoft Corporation. All rights reserved.
649
+ * Licensed under the MIT License.
650
650
  */
651
651
 
652
- /**
653
- * Generated bundle index. Do not edit.
652
+ /**
653
+ * Generated bundle index. Do not edit.
654
654
  */
655
655
 
656
656
  export { MSAL_BROADCAST_CONFIG, MSAL_GUARD_CONFIG, MSAL_INSTANCE, MSAL_INTERCEPTOR_CONFIG, MsalBroadcastService, MsalCustomNavigationClient, MsalGuard, MsalInterceptor, MsalModule, MsalRedirectComponent, MsalService, version };