@azure/msal-angular 3.0.0-beta.0 → 3.0.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 (87) hide show
  1. package/.beachballrc +3 -0
  2. package/.editorconfig +16 -0
  3. package/CHANGELOG.json +1418 -0
  4. package/CHANGELOG.md +520 -0
  5. package/FAQ.md +175 -0
  6. package/LICENSE +20 -20
  7. package/README.md +157 -157
  8. package/angular.json +51 -0
  9. package/docs/angular-universal.md +60 -0
  10. package/docs/configuration.md +525 -0
  11. package/docs/errors.md +89 -0
  12. package/docs/events.md +262 -0
  13. package/docs/initialization.md +206 -0
  14. package/docs/known-issues.md +19 -0
  15. package/docs/logging.md +47 -0
  16. package/docs/msal-guard.md +208 -0
  17. package/docs/msal-interceptor.md +160 -0
  18. package/docs/multi-tenant.md +90 -0
  19. package/docs/performance.md +50 -0
  20. package/docs/public-apis.md +29 -0
  21. package/docs/redirects.md +214 -0
  22. package/docs/security.md +4 -0
  23. package/docs/ssosilent.md +84 -0
  24. package/docs/v0-v1-upgrade-guide.md +61 -0
  25. package/docs/v1-v2-upgrade-guide.md +70 -0
  26. package/docs/v2-v3-upgrade-guide.md +41 -0
  27. package/karma.conf.js +43 -0
  28. package/ng-package.json +7 -0
  29. package/package.json +55 -31
  30. package/src/IMsalService.ts +31 -0
  31. package/src/constants.ts +20 -0
  32. package/src/msal.broadcast.config.ts +8 -0
  33. package/src/msal.broadcast.service.spec.ts +456 -0
  34. package/src/msal.broadcast.service.ts +74 -0
  35. package/src/msal.guard.config.ts +27 -0
  36. package/src/msal.guard.spec.ts +525 -0
  37. package/src/msal.guard.ts +290 -0
  38. package/src/msal.interceptor.config.ts +44 -0
  39. package/src/msal.interceptor.spec.ts +1125 -0
  40. package/src/msal.interceptor.ts +390 -0
  41. package/src/msal.module.ts +51 -0
  42. package/src/msal.navigation.client.spec.ts +95 -0
  43. package/src/msal.navigation.client.ts +57 -0
  44. package/src/msal.redirect.component.spec.ts +63 -0
  45. package/src/msal.redirect.component.ts +26 -0
  46. package/src/msal.service.spec.ts +452 -0
  47. package/src/msal.service.ts +97 -0
  48. package/src/packageMetadata.ts +3 -0
  49. package/{public-api.d.ts → src/public-api.ts} +35 -17
  50. package/src/test.ts +19 -0
  51. package/tsconfig.json +25 -0
  52. package/tsconfig.lib.json +27 -0
  53. package/tsconfig.lib.prod.json +10 -0
  54. package/tsconfig.spec.json +17 -0
  55. package/IMsalService.d.ts +0 -15
  56. package/constants.d.ts +0 -5
  57. package/esm2020/IMsalService.mjs +0 -6
  58. package/esm2020/azure-msal-angular.mjs +0 -5
  59. package/esm2020/constants.mjs +0 -10
  60. package/esm2020/msal.broadcast.config.mjs +0 -6
  61. package/esm2020/msal.broadcast.service.mjs +0 -57
  62. package/esm2020/msal.guard.config.mjs +0 -6
  63. package/esm2020/msal.guard.mjs +0 -218
  64. package/esm2020/msal.interceptor.config.mjs +0 -6
  65. package/esm2020/msal.interceptor.mjs +0 -270
  66. package/esm2020/msal.module.mjs +0 -46
  67. package/esm2020/msal.navigation.client.mjs +0 -51
  68. package/esm2020/msal.redirect.component.mjs +0 -31
  69. package/esm2020/msal.service.mjs +0 -81
  70. package/esm2020/packageMetadata.mjs +0 -4
  71. package/esm2020/public-api.mjs +0 -18
  72. package/fesm2015/azure-msal-angular.mjs +0 -736
  73. package/fesm2015/azure-msal-angular.mjs.map +0 -1
  74. package/fesm2020/azure-msal-angular.mjs +0 -732
  75. package/fesm2020/azure-msal-angular.mjs.map +0 -1
  76. package/index.d.ts +0 -5
  77. package/msal.broadcast.config.d.ts +0 -3
  78. package/msal.broadcast.service.d.ts +0 -17
  79. package/msal.guard.config.d.ts +0 -9
  80. package/msal.guard.d.ts +0 -43
  81. package/msal.interceptor.config.d.ts +0 -17
  82. package/msal.interceptor.d.ts +0 -63
  83. package/msal.module.d.ts +0 -13
  84. package/msal.navigation.client.d.ts +0 -19
  85. package/msal.redirect.component.d.ts +0 -15
  86. package/msal.service.d.ts +0 -31
  87. package/packageMetadata.d.ts +0 -2
@@ -0,0 +1,31 @@
1
+ /*
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import {
7
+ EndSessionRequest,
8
+ AuthorizationUrlRequest,
9
+ AuthenticationResult,
10
+ PopupRequest,
11
+ RedirectRequest,
12
+ SilentRequest,
13
+ Logger,
14
+ } from '@azure/msal-browser';
15
+ import { Observable } from 'rxjs';
16
+
17
+ export interface IMsalService {
18
+ initialize(): Observable<void>;
19
+ acquireTokenPopup(request: PopupRequest): Observable<AuthenticationResult>;
20
+ acquireTokenRedirect(request: RedirectRequest): Observable<void>;
21
+ acquireTokenSilent(
22
+ silentRequest: SilentRequest
23
+ ): Observable<AuthenticationResult>;
24
+ handleRedirectObservable(): Observable<AuthenticationResult | null>;
25
+ loginPopup(request?: PopupRequest): Observable<AuthenticationResult>;
26
+ loginRedirect(request?: RedirectRequest): Observable<void>;
27
+ logout(logoutRequest?: EndSessionRequest): Observable<void>;
28
+ ssoSilent(request: AuthorizationUrlRequest): Observable<AuthenticationResult>;
29
+ getLogger(): Logger;
30
+ setLogger(logger: Logger): void;
31
+ }
@@ -0,0 +1,20 @@
1
+ /*
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { InjectionToken } from '@angular/core';
7
+
8
+ export const MSAL_INSTANCE = new InjectionToken<string>('MSAL_INSTANCE');
9
+
10
+ export const MSAL_GUARD_CONFIG = new InjectionToken<string>(
11
+ 'MSAL_GUARD_CONFIG'
12
+ );
13
+
14
+ export const MSAL_INTERCEPTOR_CONFIG = new InjectionToken<string>(
15
+ 'MSAL_INTERCEPTOR_CONFIG'
16
+ );
17
+
18
+ export const MSAL_BROADCAST_CONFIG = new InjectionToken<string>(
19
+ 'MSAL_BROADCAST_CONFIG'
20
+ );
@@ -0,0 +1,8 @@
1
+ /*
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ export type MsalBroadcastConfiguration = {
7
+ eventsToReplay: number;
8
+ };
@@ -0,0 +1,456 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+ import {
3
+ EventType,
4
+ InteractionStatus,
5
+ InteractionType,
6
+ PublicClientApplication,
7
+ } from '@azure/msal-browser';
8
+ import { Subscription } from 'rxjs';
9
+ import { MsalModule, MSAL_BROADCAST_CONFIG } from './public-api';
10
+ import { MsalBroadcastService } from './msal.broadcast.service';
11
+
12
+ let broadcastService: MsalBroadcastService;
13
+ let subscription: Subscription;
14
+
15
+ const msalInstance = new PublicClientApplication({
16
+ auth: {
17
+ clientId: '6226576d-37e9-49eb-b201-ec1eeb0029b6',
18
+ redirectUri: 'http://localhost:4200',
19
+ },
20
+ });
21
+
22
+ function initializeMsal(providers: any[] = []) {
23
+ TestBed.resetTestingModule();
24
+
25
+ TestBed.configureTestingModule({
26
+ imports: [
27
+ MsalModule.forRoot(msalInstance, null, {
28
+ interactionType: InteractionType.Popup,
29
+ protectedResourceMap: new Map(),
30
+ }),
31
+ ],
32
+ providers: [MsalBroadcastService, ...providers],
33
+ });
34
+ broadcastService = TestBed.inject(MsalBroadcastService);
35
+ }
36
+
37
+ describe('MsalBroadcastService', () => {
38
+ beforeEach(() => {
39
+ initializeMsal();
40
+ });
41
+
42
+ afterEach(() => {
43
+ subscription.unsubscribe();
44
+ });
45
+
46
+ it('broadcasts event from PublicClientApplication', (done) => {
47
+ const sub = broadcastService.msalSubject$.subscribe((result) => {
48
+ expect(result.eventType).toEqual(EventType.LOGIN_START);
49
+ expect(result.interactionType).toEqual(InteractionType.Popup);
50
+ expect(result.payload).toEqual(null);
51
+ expect(result.error).toEqual(null);
52
+ expect(result.timestamp).toBeInstanceOf(Number);
53
+ sub.unsubscribe();
54
+ });
55
+
56
+ const expectedInProgress = [
57
+ InteractionStatus.Startup,
58
+ InteractionStatus.Login,
59
+ ];
60
+ let index = 0;
61
+
62
+ subscription = broadcastService.inProgress$.subscribe((result) => {
63
+ expect(result).toEqual(expectedInProgress[index]);
64
+ if (index === expectedInProgress.length - 1) {
65
+ done();
66
+ } else {
67
+ index++;
68
+ }
69
+ });
70
+
71
+ // @ts-ignore
72
+ msalInstance.controller
73
+ .getEventHandler()
74
+ .emitEvent(EventType.LOGIN_START, InteractionType.Popup);
75
+ });
76
+
77
+ it('broadcasts previous events if MsalBroadcastConfig set and eventsToReplay is greater than 0', (done) => {
78
+ initializeMsal([
79
+ {
80
+ provide: MSAL_BROADCAST_CONFIG,
81
+ useValue: {
82
+ eventsToReplay: 3,
83
+ },
84
+ },
85
+ ]);
86
+
87
+ const expectedMsalSubjectFirstSubscription = [
88
+ {
89
+ eventType: EventType.LOGIN_START,
90
+ interactionType: InteractionType.Redirect,
91
+ payload: null,
92
+ error: null,
93
+ },
94
+ ];
95
+ let firstIndex = 0;
96
+
97
+ subscription = broadcastService.msalSubject$.subscribe((result) => {
98
+ expect(result.eventType).toEqual(
99
+ expectedMsalSubjectFirstSubscription[firstIndex].eventType
100
+ );
101
+ expect(result.interactionType).toEqual(
102
+ expectedMsalSubjectFirstSubscription[firstIndex].interactionType
103
+ );
104
+ expect(result.payload).toEqual(
105
+ expectedMsalSubjectFirstSubscription[firstIndex].payload
106
+ );
107
+ expect(result.error).toEqual(
108
+ expectedMsalSubjectFirstSubscription[firstIndex].error
109
+ );
110
+ expect(result.timestamp).toBeInstanceOf(Number);
111
+ if (firstIndex === expectedMsalSubjectFirstSubscription.length - 1) {
112
+ return;
113
+ } else {
114
+ firstIndex++;
115
+ }
116
+ });
117
+
118
+ // @ts-ignore
119
+ msalInstance.controller
120
+ .getEventHandler()
121
+ .emitEvent(EventType.LOGIN_START, InteractionType.Redirect);
122
+
123
+ subscription.unsubscribe();
124
+
125
+ let index = 0;
126
+ const expectedMsalSubject = [
127
+ {
128
+ eventType: EventType.LOGIN_START,
129
+ interactionType: InteractionType.Redirect,
130
+ payload: null,
131
+ error: null,
132
+ },
133
+ {
134
+ eventType: EventType.HANDLE_REDIRECT_START,
135
+ interactionType: InteractionType.Redirect,
136
+ payload: null,
137
+ error: null,
138
+ },
139
+ {
140
+ eventType: EventType.HANDLE_REDIRECT_END,
141
+ interactionType: InteractionType.Redirect,
142
+ payload: null,
143
+ error: null,
144
+ },
145
+ ];
146
+
147
+ const newSubscription = broadcastService.msalSubject$.subscribe(
148
+ (result) => {
149
+ expect(result.eventType).toEqual(expectedMsalSubject[index].eventType);
150
+ expect(result.interactionType).toEqual(
151
+ expectedMsalSubject[index].interactionType
152
+ );
153
+ expect(result.payload).toEqual(expectedMsalSubject[index].payload);
154
+ expect(result.error).toEqual(expectedMsalSubject[index].error);
155
+ expect(result.timestamp).toBeInstanceOf(Number);
156
+ if (index === expectedMsalSubject.length - 1) {
157
+ done();
158
+ } else {
159
+ index++;
160
+ }
161
+ }
162
+ );
163
+
164
+ // @ts-ignore
165
+ msalInstance.controller
166
+ .getEventHandler()
167
+ .emitEvent(EventType.HANDLE_REDIRECT_START, InteractionType.Redirect);
168
+ // @ts-ignore
169
+ msalInstance.controller
170
+ .getEventHandler()
171
+ .emitEvent(EventType.HANDLE_REDIRECT_END, InteractionType.Redirect);
172
+
173
+ newSubscription.unsubscribe();
174
+ });
175
+
176
+ it('broadcasts the set number of past events if MsalBroadcastConfig and eventsToReplay is set', (done) => {
177
+ initializeMsal([
178
+ {
179
+ provide: MSAL_BROADCAST_CONFIG,
180
+ useValue: {
181
+ eventsToReplay: 1,
182
+ },
183
+ },
184
+ ]);
185
+
186
+ const expectedMsalSubjectFirstSubscription = [
187
+ {
188
+ eventType: EventType.INITIALIZE_START,
189
+ interactionType: InteractionType.Redirect,
190
+ payload: null,
191
+ error: null,
192
+ },
193
+ {
194
+ eventType: EventType.LOGIN_START,
195
+ interactionType: InteractionType.Redirect,
196
+ payload: null,
197
+ error: null,
198
+ },
199
+ ];
200
+ let firstIndex = 0;
201
+
202
+ subscription = broadcastService.msalSubject$.subscribe((result) => {
203
+ expect(result.eventType).toEqual(
204
+ expectedMsalSubjectFirstSubscription[firstIndex].eventType
205
+ );
206
+ expect(result.interactionType).toEqual(
207
+ expectedMsalSubjectFirstSubscription[firstIndex].interactionType
208
+ );
209
+ expect(result.payload).toEqual(
210
+ expectedMsalSubjectFirstSubscription[firstIndex].payload
211
+ );
212
+ expect(result.error).toEqual(
213
+ expectedMsalSubjectFirstSubscription[firstIndex].error
214
+ );
215
+ expect(result.timestamp).toBeInstanceOf(Number);
216
+ if (firstIndex === expectedMsalSubjectFirstSubscription.length - 1) {
217
+ return;
218
+ } else {
219
+ firstIndex++;
220
+ }
221
+ });
222
+
223
+ // @ts-ignore
224
+ msalInstance.controller
225
+ .getEventHandler()
226
+ .emitEvent(EventType.INITIALIZE_START, InteractionType.Redirect);
227
+ // @ts-ignore
228
+ msalInstance.controller
229
+ .getEventHandler()
230
+ .emitEvent(EventType.LOGIN_START, InteractionType.Redirect);
231
+
232
+ subscription.unsubscribe();
233
+
234
+ let index = 0;
235
+ const expectedMsalSubject = [
236
+ {
237
+ eventType: EventType.LOGIN_START,
238
+ interactionType: InteractionType.Redirect,
239
+ payload: null,
240
+ error: null,
241
+ },
242
+ {
243
+ eventType: EventType.HANDLE_REDIRECT_START,
244
+ interactionType: InteractionType.Redirect,
245
+ payload: null,
246
+ error: null,
247
+ },
248
+ {
249
+ eventType: EventType.HANDLE_REDIRECT_END,
250
+ interactionType: InteractionType.Redirect,
251
+ payload: null,
252
+ error: null,
253
+ },
254
+ ];
255
+
256
+ const newSubscription = broadcastService.msalSubject$.subscribe(
257
+ (result) => {
258
+ expect(result.eventType).toEqual(expectedMsalSubject[index].eventType);
259
+ expect(result.interactionType).toEqual(
260
+ expectedMsalSubject[index].interactionType
261
+ );
262
+ expect(result.payload).toEqual(expectedMsalSubject[index].payload);
263
+ expect(result.error).toEqual(expectedMsalSubject[index].error);
264
+ expect(result.timestamp).toBeInstanceOf(Number);
265
+ if (index === expectedMsalSubject.length - 1) {
266
+ done();
267
+ } else {
268
+ index++;
269
+ }
270
+ }
271
+ );
272
+
273
+ // @ts-ignore
274
+ msalInstance.controller
275
+ .getEventHandler()
276
+ .emitEvent(EventType.HANDLE_REDIRECT_START, InteractionType.Redirect);
277
+ // @ts-ignore
278
+ msalInstance.controller
279
+ .getEventHandler()
280
+ .emitEvent(EventType.HANDLE_REDIRECT_END, InteractionType.Redirect);
281
+
282
+ newSubscription.unsubscribe();
283
+ });
284
+
285
+ it('does not broadcasts previous events if MsalBroadcastConfig is not set', (done) => {
286
+ const expectedMsalSubjectFirstSubscription = [
287
+ {
288
+ eventType: EventType.LOGIN_START,
289
+ interactionType: InteractionType.Redirect,
290
+ payload: null,
291
+ error: null,
292
+ },
293
+ ];
294
+ let firstIndex = 0;
295
+
296
+ subscription = broadcastService.msalSubject$.subscribe((result) => {
297
+ expect(result.eventType).toEqual(
298
+ expectedMsalSubjectFirstSubscription[firstIndex].eventType
299
+ );
300
+ expect(result.interactionType).toEqual(
301
+ expectedMsalSubjectFirstSubscription[firstIndex].interactionType
302
+ );
303
+ expect(result.payload).toEqual(
304
+ expectedMsalSubjectFirstSubscription[firstIndex].payload
305
+ );
306
+ expect(result.error).toEqual(
307
+ expectedMsalSubjectFirstSubscription[firstIndex].error
308
+ );
309
+ expect(result.timestamp).toBeInstanceOf(Number);
310
+ if (firstIndex === expectedMsalSubjectFirstSubscription.length - 1) {
311
+ return;
312
+ } else {
313
+ firstIndex++;
314
+ }
315
+ });
316
+
317
+ // @ts-ignore
318
+ msalInstance.controller
319
+ .getEventHandler()
320
+ .emitEvent(EventType.LOGIN_START, InteractionType.Redirect);
321
+
322
+ subscription.unsubscribe();
323
+
324
+ let index = 0;
325
+ const expectedMsalSubject = [
326
+ {
327
+ eventType: EventType.HANDLE_REDIRECT_START,
328
+ interactionType: InteractionType.Redirect,
329
+ payload: null,
330
+ error: null,
331
+ },
332
+ {
333
+ eventType: EventType.HANDLE_REDIRECT_END,
334
+ interactionType: InteractionType.Redirect,
335
+ payload: null,
336
+ error: null,
337
+ },
338
+ ];
339
+
340
+ const newSubscription = broadcastService.msalSubject$.subscribe(
341
+ (result) => {
342
+ expect(result.eventType).toEqual(expectedMsalSubject[index].eventType);
343
+ expect(result.interactionType).toEqual(
344
+ expectedMsalSubject[index].interactionType
345
+ );
346
+ expect(result.payload).toEqual(expectedMsalSubject[index].payload);
347
+ expect(result.error).toEqual(expectedMsalSubject[index].error);
348
+ expect(result.timestamp).toBeInstanceOf(Number);
349
+ if (index === expectedMsalSubject.length - 1) {
350
+ done();
351
+ } else {
352
+ index++;
353
+ }
354
+ }
355
+ );
356
+
357
+ // @ts-ignore
358
+ msalInstance.controller
359
+ .getEventHandler()
360
+ .emitEvent(EventType.HANDLE_REDIRECT_START, InteractionType.Redirect);
361
+ // @ts-ignore
362
+ msalInstance.controller
363
+ .getEventHandler()
364
+ .emitEvent(EventType.HANDLE_REDIRECT_END, InteractionType.Redirect);
365
+
366
+ newSubscription.unsubscribe();
367
+ });
368
+
369
+ it('LOGIN_SUCCESS event does not set inProgress to None if handleRedirect is still in progress', (done) => {
370
+ const expectedInProgress = [
371
+ InteractionStatus.Startup,
372
+ InteractionStatus.HandleRedirect,
373
+ ];
374
+ let index = 0;
375
+
376
+ subscription = broadcastService.inProgress$.subscribe((result) => {
377
+ expect(result).toEqual(expectedInProgress[index]);
378
+ if (index === expectedInProgress.length - 1) {
379
+ done();
380
+ } else {
381
+ index++;
382
+ }
383
+ });
384
+
385
+ // @ts-ignore
386
+ msalInstance.controller
387
+ .getEventHandler()
388
+ .emitEvent(EventType.HANDLE_REDIRECT_START, InteractionType.Redirect);
389
+ // @ts-ignore
390
+ msalInstance.controller
391
+ .getEventHandler()
392
+ .emitEvent(EventType.LOGIN_SUCCESS, InteractionType.Redirect);
393
+ });
394
+
395
+ it('HANDLE_REDIRECT_END event sets inProgress to None if handleRedirect is in progress', (done) => {
396
+ const expectedInProgress = [
397
+ InteractionStatus.Startup,
398
+ InteractionStatus.HandleRedirect,
399
+ InteractionStatus.None,
400
+ ];
401
+ let index = 0;
402
+
403
+ subscription = broadcastService.inProgress$.subscribe((result) => {
404
+ expect(result).toEqual(expectedInProgress[index]);
405
+ if (index === expectedInProgress.length - 1) {
406
+ done();
407
+ } else {
408
+ index++;
409
+ }
410
+ });
411
+
412
+ // @ts-ignore
413
+ msalInstance.controller
414
+ .getEventHandler()
415
+ .emitEvent(EventType.HANDLE_REDIRECT_START, InteractionType.Redirect);
416
+ // @ts-ignore
417
+ msalInstance.controller
418
+ .getEventHandler()
419
+ .emitEvent(EventType.LOGIN_SUCCESS, InteractionType.Redirect);
420
+ // @ts-ignore
421
+ msalInstance.controller
422
+ .getEventHandler()
423
+ .emitEvent(EventType.HANDLE_REDIRECT_END, InteractionType.Redirect);
424
+ });
425
+
426
+ it('HANDLE_REDIRECT_END event does not set inProgress to None if login is in progress', (done) => {
427
+ const expectedInProgress = [
428
+ InteractionStatus.Startup,
429
+ InteractionStatus.HandleRedirect,
430
+ InteractionStatus.Login,
431
+ ];
432
+ let index = 0;
433
+
434
+ subscription = broadcastService.inProgress$.subscribe((result) => {
435
+ expect(result).toEqual(expectedInProgress[index]);
436
+ if (index === expectedInProgress.length - 1) {
437
+ done();
438
+ } else {
439
+ index++;
440
+ }
441
+ });
442
+
443
+ // @ts-ignore
444
+ msalInstance.controller
445
+ .getEventHandler()
446
+ .emitEvent(EventType.HANDLE_REDIRECT_START, InteractionType.Redirect);
447
+ // @ts-ignore
448
+ msalInstance.controller
449
+ .getEventHandler()
450
+ .emitEvent(EventType.LOGIN_START, InteractionType.Redirect);
451
+ // @ts-ignore
452
+ msalInstance.controller
453
+ .getEventHandler()
454
+ .emitEvent(EventType.HANDLE_REDIRECT_END, InteractionType.Redirect);
455
+ });
456
+ });
@@ -0,0 +1,74 @@
1
+ /*
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { Inject, Injectable, Optional } from '@angular/core';
7
+ import {
8
+ EventMessage,
9
+ EventMessageUtils,
10
+ IPublicClientApplication,
11
+ InteractionStatus,
12
+ } from '@azure/msal-browser';
13
+ import { BehaviorSubject, Observable, ReplaySubject, Subject } from 'rxjs';
14
+ import { MsalService } from './msal.service';
15
+ import { MsalBroadcastConfiguration } from './msal.broadcast.config';
16
+ import { MSAL_BROADCAST_CONFIG, MSAL_INSTANCE } from './constants';
17
+
18
+ @Injectable()
19
+ export class MsalBroadcastService {
20
+ private _msalSubject: Subject<EventMessage>;
21
+ public msalSubject$: Observable<EventMessage>;
22
+ private _inProgress: BehaviorSubject<InteractionStatus>;
23
+ public inProgress$: Observable<InteractionStatus>;
24
+
25
+ constructor(
26
+ @Inject(MSAL_INSTANCE) private msalInstance: IPublicClientApplication,
27
+ private authService: MsalService,
28
+ @Optional()
29
+ @Inject(MSAL_BROADCAST_CONFIG)
30
+ private msalBroadcastConfig?: MsalBroadcastConfiguration
31
+ ) {
32
+ // Make _msalSubject a ReplaySubject if configured to replay past events
33
+ if (
34
+ this.msalBroadcastConfig &&
35
+ this.msalBroadcastConfig.eventsToReplay > 0
36
+ ) {
37
+ this.authService
38
+ .getLogger()
39
+ .verbose(
40
+ `BroadcastService - eventsToReplay set on BroadcastConfig, replaying the last ${this.msalBroadcastConfig.eventsToReplay} events`
41
+ );
42
+ this._msalSubject = new ReplaySubject<EventMessage>(
43
+ this.msalBroadcastConfig.eventsToReplay
44
+ );
45
+ } else {
46
+ // Defaults to _msalSubject being a Subject
47
+ this._msalSubject = new Subject<EventMessage>();
48
+ }
49
+
50
+ this.msalSubject$ = this._msalSubject.asObservable();
51
+
52
+ // InProgress as BehaviorSubject so most recent inProgress state will be available upon subscription
53
+ this._inProgress = new BehaviorSubject<InteractionStatus>(
54
+ InteractionStatus.Startup
55
+ );
56
+ this.inProgress$ = this._inProgress.asObservable();
57
+
58
+ this.msalInstance.addEventCallback((message: EventMessage) => {
59
+ this._msalSubject.next(message);
60
+ const status = EventMessageUtils.getInteractionStatusFromEvent(
61
+ message,
62
+ this._inProgress.value
63
+ );
64
+ if (status !== null) {
65
+ this.authService
66
+ .getLogger()
67
+ .verbose(
68
+ `BroadcastService - ${message.eventType} results in setting inProgress from ${this._inProgress.value} to ${status}`
69
+ );
70
+ this._inProgress.next(status);
71
+ }
72
+ });
73
+ }
74
+ }
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { RouterStateSnapshot } from '@angular/router';
7
+ import {
8
+ PopupRequest,
9
+ RedirectRequest,
10
+ InteractionType,
11
+ } from '@azure/msal-browser';
12
+ import { MsalService } from './msal.service';
13
+
14
+ export declare type MsalGuardAuthRequest =
15
+ | Partial<PopupRequest>
16
+ | Partial<Omit<RedirectRequest, 'redirectStartPage'>>;
17
+
18
+ export type MsalGuardConfiguration = {
19
+ interactionType: InteractionType.Popup | InteractionType.Redirect;
20
+ authRequest?:
21
+ | MsalGuardAuthRequest
22
+ | ((
23
+ authService: MsalService,
24
+ state: RouterStateSnapshot
25
+ ) => MsalGuardAuthRequest);
26
+ loginFailedRoute?: string;
27
+ };