Skip to content

Commit fabf962

Browse files
authored
New resetInProgressEvent method to reset event to None after handleRedirectPromise completes (#7682)
This PR fixes a bug in msal-angular where inProgress event does not get reset to None after handleRedirectPromise() completes.
1 parent 972b993 commit fabf962

11 files changed

+80
-11
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "added resetInProgressEvent function to reset event after handleRedirectPromise is called #7682",
4+
"packageName": "@azure/msal-angular",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

lib/msal-angular/karma.conf.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ module.exports = function (config) {
1818
jasmine: {
1919
failSpecWithNoExpectations: true
2020
},
21-
clearContext: false // leave Jasmine Spec Runner output visible in browser
21+
clearContext: false, // leave Jasmine Spec Runner output visible in browser
22+
captureConsole: true // turns on console logging for test debugging
2223
},
2324
coverageIstanbulReporter: {
2425
dir: require("path").join(__dirname, "./coverage"),

lib/msal-angular/src/msal.broadcast.service.spec.ts

+26
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ function initializeMsal(providers: any[] = []) {
4040
}),
4141
],
4242
providers: [MsalBroadcastService, ...providers],
43+
teardown: { destroyAfterEach: false },
4344
});
4445
broadcastService = TestBed.inject(MsalBroadcastService);
4546
}
@@ -442,4 +443,29 @@ describe("MsalBroadcastService", () => {
442443
InteractionType.Redirect
443444
);
444445
});
446+
447+
it("automatically sets inProgress to None when handleRedirectPromise returns without emitting an event", (done) => {
448+
const expectedInProgress = [
449+
InteractionStatus.Startup,
450+
InteractionStatus.None,
451+
];
452+
let index = 0;
453+
454+
subscription = broadcastService.inProgress$.subscribe((result) => {
455+
expect(result).toEqual(expectedInProgress[index]);
456+
if (index === expectedInProgress.length - 1) {
457+
done();
458+
} else if (expectedInProgress[index] === InteractionStatus.Startup) {
459+
index++;
460+
broadcastService.resetInProgressEvent();
461+
} else {
462+
index++;
463+
}
464+
});
465+
466+
eventHandler.emitEvent(
467+
EventType.INITIALIZE_START,
468+
InteractionType.Redirect
469+
);
470+
});
445471
});

lib/msal-angular/src/msal.broadcast.service.ts

+9
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,13 @@ export class MsalBroadcastService {
7171
}
7272
});
7373
}
74+
75+
/**
76+
* Resets inProgress state to None
77+
*/
78+
resetInProgressEvent(): void {
79+
if (this._inProgress.value === InteractionStatus.Startup) {
80+
this._inProgress.next(InteractionStatus.None);
81+
}
82+
}
7483
}

lib/msal-angular/src/msal.guard.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ function initializeMsal(providers: any[] = []) {
6868
RouterTestingModule.withRoutes([]),
6969
],
7070
providers: [MsalGuard, MsalService, MsalBroadcastService, ...providers],
71+
teardown: { destroyAfterEach: false },
7172
});
7273

7374
authService = TestBed.inject(MsalService);

lib/msal-angular/src/msal.interceptor.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ function initializeMsal() {
124124
},
125125
Location,
126126
],
127+
teardown: { destroyAfterEach: false },
127128
});
128129

129130
interceptor = TestBed.inject(MsalInterceptor);

lib/msal-angular/src/msal.navigation.client.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ describe("MsalCustomNaviationClient", () => {
4444
MsalService,
4545
MsalGuard,
4646
],
47+
teardown: { destroyAfterEach: false },
4748
});
4849
authService = TestBed.inject(MsalService);
4950
navigationClient = TestBed.inject(MsalCustomNavigationClient);

lib/msal-angular/src/msal.redirect.component.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ function initializeMsal() {
2727
declarations: [MsalRedirectComponent],
2828
imports: [MsalModule.forRoot(MSALInstanceFactory(), null, null)],
2929
providers: [],
30+
teardown: { destroyAfterEach: false },
3031
});
3132

3233
authService = TestBed.inject(MsalService);

lib/msal-angular/src/msal.service.spec.ts

+21-5
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ import { TestBed } from "@angular/core/testing";
22
import {
33
AuthenticationResult,
44
AuthError,
5+
InteractionStatus,
56
InteractionType,
67
Logger,
78
PublicClientApplication,
89
SilentRequest,
910
} from "@azure/msal-browser";
1011
import { MsalModule, MsalBroadcastService, MsalService } from "./public-api";
12+
import { takeLast } from "rxjs/operators";
1113

1214
let authService: MsalService;
1315
let broadcastService: MsalBroadcastService;
@@ -30,6 +32,7 @@ function initializeMsal() {
3032
}),
3133
],
3234
providers: [MsalService, MsalBroadcastService],
35+
teardown: { destroyAfterEach: false },
3336
});
3437

3538
authService = TestBed.inject(MsalService);
@@ -198,7 +201,7 @@ describe("MsalService", () => {
198201

199202
authService.ssoSilent(request).subscribe({
200203
error: (error: AuthError) => {
201-
expect(error.message).toBe(sampleError.message);
204+
expect(error.errorMessage).toBe(sampleError.errorMessage);
202205
expect(
203206
PublicClientApplication.prototype.ssoSilent
204207
).toHaveBeenCalledWith(request);
@@ -259,7 +262,7 @@ describe("MsalService", () => {
259262

260263
authService.acquireTokenSilent(request).subscribe({
261264
error: (error: AuthError) => {
262-
expect(error.message).toBe(sampleError.message);
265+
expect(error.errorMessage).toBe(sampleError.errorMessage);
263266
expect(
264267
PublicClientApplication.prototype.acquireTokenSilent
265268
).toHaveBeenCalledWith(request);
@@ -339,7 +342,7 @@ describe("MsalService", () => {
339342

340343
authService.acquireTokenPopup(request).subscribe({
341344
error: (error: AuthError) => {
342-
expect(error.message).toBe(sampleError.message);
345+
expect(error.errorMessage).toBe(sampleError.errorMessage);
343346
expect(
344347
PublicClientApplication.prototype.acquireTokenPopup
345348
).toHaveBeenCalledWith(request);
@@ -350,11 +353,14 @@ describe("MsalService", () => {
350353
});
351354

352355
describe("handleRedirectObservable", () => {
353-
it("success", (done) => {
356+
it("success and resets inProgress event to none", (done) => {
354357
const sampleAccessToken = {
355358
accessToken: "123abc",
356359
};
357360

361+
//@ts-ignore
362+
broadcastService._inProgress.next(InteractionStatus.Startup);
363+
358364
spyOn(PublicClientApplication.prototype, "initialize").and.returnValue(
359365
Promise.resolve()
360366
);
@@ -379,13 +385,19 @@ describe("MsalService", () => {
379385
expect(
380386
PublicClientApplication.prototype.handleRedirectPromise
381387
).toHaveBeenCalled();
388+
broadcastService.inProgress$.subscribe((result) => {
389+
expect(result).toBe(InteractionStatus.None);
390+
});
382391
done();
383392
});
384393
});
385394

386-
it("failure", (done) => {
395+
it("failure and also resets inProgress event to none", (done) => {
387396
const sampleError = new AuthError("123", "message");
388397

398+
//@ts-ignore
399+
broadcastService._inProgress.next(InteractionStatus.Startup);
400+
389401
spyOn(PublicClientApplication.prototype, "initialize").and.returnValue(
390402
Promise.resolve()
391403
);
@@ -408,6 +420,10 @@ describe("MsalService", () => {
408420
expect(
409421
PublicClientApplication.prototype.handleRedirectPromise
410422
).toHaveBeenCalled();
423+
broadcastService.inProgress$.pipe(takeLast(1)).subscribe((result) => {
424+
console.log("failure result", result);
425+
expect(result).toBe(InteractionStatus.None);
426+
});
411427
done();
412428
},
413429
});

lib/msal-angular/src/msal.service.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License.
44
*/
55

6-
import { Inject, Injectable } from "@angular/core";
6+
import { Inject, Injectable, Injector } from "@angular/core";
77
import { Location } from "@angular/common";
88
import {
99
IPublicClientApplication,
@@ -21,6 +21,7 @@ import { Observable, from } from "rxjs";
2121
import { IMsalService } from "./IMsalService";
2222
import { name, version } from "./packageMetadata";
2323
import { MSAL_INSTANCE } from "./constants";
24+
import { MsalBroadcastService } from "./msal.broadcast.service";
2425

2526
@Injectable()
2627
export class MsalService implements IMsalService {
@@ -29,7 +30,8 @@ export class MsalService implements IMsalService {
2930

3031
constructor(
3132
@Inject(MSAL_INSTANCE) public instance: IPublicClientApplication,
32-
private location: Location
33+
private location: Location,
34+
private injector: Injector
3335
) {
3436
const hash = this.location.path(true).split("#").pop();
3537
if (hash) {
@@ -59,6 +61,10 @@ export class MsalService implements IMsalService {
5961
.then(() =>
6062
this.instance.handleRedirectPromise(hash || this.redirectHash)
6163
)
64+
.finally(() => {
65+
// update inProgress state to none
66+
this.injector.get(MsalBroadcastService).resetInProgressEvent();
67+
})
6268
);
6369
}
6470
loginPopup(request?: PopupRequest): Observable<AuthenticationResult> {

package-lock.json

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)