From 58d8f7e6e87cbe79ca41e2174902d21009a6bf93 Mon Sep 17 00:00:00 2001 From: Brad Kovach Date: Thu, 20 Mar 2025 10:29:41 -0600 Subject: [PATCH 1/7] Isolate inject() type changes to be merged into msal-v5 --- ...-46ce52bc-2e6e-40e0-acc8-1bccfd4ed63b.json | 7 +++++++ lib/msal-angular/src/constants.ts | 20 +++++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 change/@azure-msal-angular-46ce52bc-2e6e-40e0-acc8-1bccfd4ed63b.json diff --git a/change/@azure-msal-angular-46ce52bc-2e6e-40e0-acc8-1bccfd4ed63b.json b/change/@azure-msal-angular-46ce52bc-2e6e-40e0-acc8-1bccfd4ed63b.json new file mode 100644 index 0000000000..95e01e6b52 --- /dev/null +++ b/change/@azure-msal-angular-46ce52bc-2e6e-40e0-acc8-1bccfd4ed63b.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "Adjust InjectionToken usage so that properly-typed tokens can be used with new `inject(TOKEN)` syntax.", + "packageName": "@azure/msal-angular", + "email": "bradkovach@gmail.com", + "dependentChangeType": "major" +} diff --git a/lib/msal-angular/src/constants.ts b/lib/msal-angular/src/constants.ts index dbb44746a5..57fea5f227 100644 --- a/lib/msal-angular/src/constants.ts +++ b/lib/msal-angular/src/constants.ts @@ -4,17 +4,21 @@ */ import { InjectionToken } from "@angular/core"; +import { type IPublicClientApplication } from "@azure/msal-browser"; +import { type MsalBroadcastConfiguration } from "./msal.broadcast.config"; +import { type MsalGuardConfiguration } from "./msal.guard.config"; +import { type MsalInterceptorConfiguration } from "./msal.interceptor.config"; -export const MSAL_INSTANCE = new InjectionToken("MSAL_INSTANCE"); +export const MSAL_INSTANCE = new InjectionToken( + "MSAL_INSTANCE" +); -export const MSAL_GUARD_CONFIG = new InjectionToken( +export const MSAL_GUARD_CONFIG = new InjectionToken( "MSAL_GUARD_CONFIG" ); -export const MSAL_INTERCEPTOR_CONFIG = new InjectionToken( - "MSAL_INTERCEPTOR_CONFIG" -); +export const MSAL_INTERCEPTOR_CONFIG = + new InjectionToken("MSAL_INTERCEPTOR_CONFIG"); -export const MSAL_BROADCAST_CONFIG = new InjectionToken( - "MSAL_BROADCAST_CONFIG" -); +export const MSAL_BROADCAST_CONFIG = + new InjectionToken("MSAL_BROADCAST_CONFIG"); From d5d032e06154861860a9f61b8e9f1b2565d4c3a9 Mon Sep 17 00:00:00 2001 From: Brad Kovach Date: Wed, 23 Apr 2025 20:24:46 -0600 Subject: [PATCH 2/7] formatting: separate imports in msal-angular/constants.ts --- lib/msal-angular/src/constants.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/msal-angular/src/constants.ts b/lib/msal-angular/src/constants.ts index 57fea5f227..5d79d6f0e1 100644 --- a/lib/msal-angular/src/constants.ts +++ b/lib/msal-angular/src/constants.ts @@ -4,6 +4,7 @@ */ import { InjectionToken } from "@angular/core"; + import { type IPublicClientApplication } from "@azure/msal-browser"; import { type MsalBroadcastConfiguration } from "./msal.broadcast.config"; import { type MsalGuardConfiguration } from "./msal.guard.config"; From dc17de570e28b987aec7300a920024e1307d368d Mon Sep 17 00:00:00 2001 From: Brad Kovach Date: Wed, 23 Apr 2025 20:25:14 -0600 Subject: [PATCH 3/7] Change files --- ...-msal-angular-810b2704-1c5f-4480-86cc-0a97a42596dc.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@azure-msal-angular-810b2704-1c5f-4480-86cc-0a97a42596dc.json diff --git a/change/@azure-msal-angular-810b2704-1c5f-4480-86cc-0a97a42596dc.json b/change/@azure-msal-angular-810b2704-1c5f-4480-86cc-0a97a42596dc.json new file mode 100644 index 0000000000..9c1492fefa --- /dev/null +++ b/change/@azure-msal-angular-810b2704-1c5f-4480-86cc-0a97a42596dc.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "formatting: separate imports in msal-angular/constants.ts", + "packageName": "@azure/msal-angular", + "email": "bradkovach@gmail.com", + "dependentChangeType": "patch" +} From 3ad2442e3a94eb14ea9ca995b30bb327a8cc3a29 Mon Sep 17 00:00:00 2001 From: Brad Kovach Date: Thu, 24 Apr 2025 14:18:48 -0600 Subject: [PATCH 4/7] remove change files --- ...-msal-angular-46ce52bc-2e6e-40e0-acc8-1bccfd4ed63b.json | 7 ------- ...-msal-angular-810b2704-1c5f-4480-86cc-0a97a42596dc.json | 7 ------- 2 files changed, 14 deletions(-) delete mode 100644 change/@azure-msal-angular-46ce52bc-2e6e-40e0-acc8-1bccfd4ed63b.json delete mode 100644 change/@azure-msal-angular-810b2704-1c5f-4480-86cc-0a97a42596dc.json diff --git a/change/@azure-msal-angular-46ce52bc-2e6e-40e0-acc8-1bccfd4ed63b.json b/change/@azure-msal-angular-46ce52bc-2e6e-40e0-acc8-1bccfd4ed63b.json deleted file mode 100644 index 95e01e6b52..0000000000 --- a/change/@azure-msal-angular-46ce52bc-2e6e-40e0-acc8-1bccfd4ed63b.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "minor", - "comment": "Adjust InjectionToken usage so that properly-typed tokens can be used with new `inject(TOKEN)` syntax.", - "packageName": "@azure/msal-angular", - "email": "bradkovach@gmail.com", - "dependentChangeType": "major" -} diff --git a/change/@azure-msal-angular-810b2704-1c5f-4480-86cc-0a97a42596dc.json b/change/@azure-msal-angular-810b2704-1c5f-4480-86cc-0a97a42596dc.json deleted file mode 100644 index 9c1492fefa..0000000000 --- a/change/@azure-msal-angular-810b2704-1c5f-4480-86cc-0a97a42596dc.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "minor", - "comment": "formatting: separate imports in msal-angular/constants.ts", - "packageName": "@azure/msal-angular", - "email": "bradkovach@gmail.com", - "dependentChangeType": "patch" -} From 73b288391201e421249895b0e24dc630ff6f790d Mon Sep 17 00:00:00 2001 From: Brad Kovach Date: Thu, 24 Apr 2025 14:19:15 -0600 Subject: [PATCH 5/7] add type checking unit tests to verify inject(TOKEN) typing. --- lib/msal-angular/src/constants.spec.ts | 50 ++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 lib/msal-angular/src/constants.spec.ts diff --git a/lib/msal-angular/src/constants.spec.ts b/lib/msal-angular/src/constants.spec.ts new file mode 100644 index 0000000000..181e6452db --- /dev/null +++ b/lib/msal-angular/src/constants.spec.ts @@ -0,0 +1,50 @@ +import { Component, inject } from "@angular/core"; +import { TestBed } from "@angular/core/testing"; +import { + MSAL_BROADCAST_CONFIG, + MSAL_GUARD_CONFIG, + MSAL_INSTANCE, + MSAL_INTERCEPTOR_CONFIG, +} from "./constants"; + +describe("Injection Tokens", () => { + it("should produce helpful type errors on mismatch", async () => { + // These are all cases where a type error is expected. + // While Jest cannot verify the type errors, we can use TypeScript's + // type checking to verify that the errors are present. + @Component({ + selector: "app-strongly-typed-functional-injection", + template: "", + }) + class MistypedFunctionalInjection { + // @ts-expect-error MSAL_INSTANCE is not a string. + msalInstance: string = inject(MSAL_INSTANCE); + // @ts-expect-error MSAL_GUARD_CONFIG is not a string. + guardConfig: string = inject(MSAL_GUARD_CONFIG); + // @ts-expect-error MSAL_INTERCEPTOR_CONFIG is not a string. + interceptorConfig: string = inject(MSAL_INTERCEPTOR_CONFIG); + // @ts-expect-error MSAL_BROADCAST_CONFIG is not a string. + broadcastConfig: string = inject(MSAL_BROADCAST_CONFIG); + } + + await TestBed.configureTestingModule({ + providers: [ + MSAL_INSTANCE, + MSAL_GUARD_CONFIG, + MSAL_INTERCEPTOR_CONFIG, + MSAL_BROADCAST_CONFIG, + ].map((provide, useValue) => ({ + provide, + useValue, + })), + }).compileComponents(); + + const fixture = TestBed.createComponent(MistypedFunctionalInjection); + const instance = fixture.componentInstance; + + expect(instance.msalInstance).toBeDefined(); + expect(instance.guardConfig).toBeDefined(); + expect(instance.interceptorConfig).toBeDefined(); + expect(instance.broadcastConfig).toBeDefined(); + }); +}); From 06b8c08b0a49ea32f014f1cce6a0342c4b5f31c5 Mon Sep 17 00:00:00 2001 From: Brad Kovach Date: Thu, 24 Apr 2025 14:23:02 -0600 Subject: [PATCH 6/7] Change files --- ...-msal-angular-f9e43c58-0c6f-4239-9cae-ddd37a47e893.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@azure-msal-angular-f9e43c58-0c6f-4239-9cae-ddd37a47e893.json diff --git a/change/@azure-msal-angular-f9e43c58-0c6f-4239-9cae-ddd37a47e893.json b/change/@azure-msal-angular-f9e43c58-0c6f-4239-9cae-ddd37a47e893.json new file mode 100644 index 0000000000..d53f4e8b50 --- /dev/null +++ b/change/@azure-msal-angular-f9e43c58-0c6f-4239-9cae-ddd37a47e893.json @@ -0,0 +1,7 @@ +{ + "type": "major", + "comment": "dx: Fix InjectionToken types to allow new Angular 14+ inject(TOKEN) syntax.", + "packageName": "@azure/msal-angular", + "email": "bradkovach@gmail.com", + "dependentChangeType": "patch" +} From 1d61de8b6b249271713d5b04e6d6c77921f9e90e Mon Sep 17 00:00:00 2001 From: Eugene Date: Wed, 2 Jul 2025 01:32:48 +0200 Subject: [PATCH 7/7] Angular standalone sample updates (#7547) This PR: - Removes unused `CommonModule` - Uses `styleUrl` instead of `styleUrls` - Uses `inject` for DI - Uses `takeUntilDestroyed` instead of `Subject/OnDestroy` approach - Fixes indents There is a typing issue, which is now solved by a generic in the following line: ```ts private msalGuardConfig = inject(MSAL_GUARD_CONFIG); ``` I found a fix in the next PR: https://github.com/AzureAD/microsoft-authentication-library-for-js/pull/7484 After its merge, the generic can be removed: ```ts private msalGuardConfig = inject(MSAL_GUARD_CONFIG); ``` --- .../src/app/app.component.ts | 53 ++++++++----------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/samples/msal-angular-samples/angular-standalone-sample/src/app/app.component.ts b/samples/msal-angular-samples/angular-standalone-sample/src/app/app.component.ts index fe09468787..7160888440 100644 --- a/samples/msal-angular-samples/angular-standalone-sample/src/app/app.component.ts +++ b/samples/msal-angular-samples/angular-standalone-sample/src/app/app.component.ts @@ -1,5 +1,5 @@ -import { Component, OnInit, Inject, OnDestroy } from '@angular/core'; -import { CommonModule } from '@angular/common'; +import { Component, DestroyRef, inject, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatMenuModule } from '@angular/material/menu'; import { MatButtonModule } from '@angular/material/button'; import { MatToolbarModule } from '@angular/material/toolbar'; @@ -19,38 +19,34 @@ import { EventMessage, EventType, } from '@azure/msal-browser'; -import { Subject } from 'rxjs'; -import { filter, takeUntil } from 'rxjs/operators'; +import { filter } from 'rxjs/operators'; @Component({ - selector: 'app-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.css'], - imports: [ - CommonModule, - MsalModule, - RouterOutlet, - RouterLink, - MatToolbarModule, - MatButtonModule, - MatMenuModule, - ] + selector: 'app-root', + templateUrl: './app.component.html', + styleUrl: './app.component.css', + imports: [ + MsalModule, + RouterOutlet, + RouterLink, + MatToolbarModule, + MatButtonModule, + MatMenuModule, + ] }) -export class AppComponent implements OnInit, OnDestroy { +export class AppComponent implements OnInit { + private destroyRef = inject(DestroyRef); + private msalGuardConfig = inject(MSAL_GUARD_CONFIG); + private authService = inject(MsalService); + private msalBroadcastService = inject(MsalBroadcastService); + title = 'Angular Standalone Sample - MSAL Angular'; isIframe = false; loginDisplay = false; - private readonly _destroying$ = new Subject(); - - constructor( - @Inject(MSAL_GUARD_CONFIG) private msalGuardConfig: MsalGuardConfiguration, - private authService: MsalService, - private msalBroadcastService: MsalBroadcastService - ) {} ngOnInit(): void { this.authService.handleRedirectObservable().subscribe(); - + this.isIframe = window !== window.parent && !window.opener; // Remove this line to use Angular Universal this.msalBroadcastService.msalSubject$ @@ -74,7 +70,7 @@ export class AppComponent implements OnInit, OnDestroy { filter( (status: InteractionStatus) => status === InteractionStatus.None ), - takeUntil(this._destroying$) + takeUntilDestroyed(this.destroyRef) ) .subscribe(() => { this.setLoginDisplay(); @@ -138,9 +134,4 @@ export class AppComponent implements OnInit, OnDestroy { this.authService.logoutRedirect(); } } - - ngOnDestroy(): void { - this._destroying$.next(undefined); - this._destroying$.complete(); - } }