Angular Universal is minimally supported in @azure/msal-angular
. As @azure/msal-angular
is a wrapper library for @azure/msal-browser
, which uses browser-only global objects such as window
and location
objects, not all of @azure/msal-angular
's features are available when using Angular Universal. While login and token acquisition is not supported server-side, Angular Universal can be used with @azure/msal-angular
without breaking your app.
Please see instructions from the Angular docs on how to install Angular Universal with an existing application, and for more information on browser-only global objects.
Note: MSAL Angular does not officially support server-side and prerendering capabilities. Using SSR with MSAL Angular may break your app.
To use @azure/msal-angular
with Angular Universal, make the following adjustments:
-
Remove references to browser-only objects. Our Angular Modules Sample has comments next to relevant lines that should be removed to render server-side. Removing these lines will not affect the sample app if using Angular Universal.
this.isIframe = window !== window.parent && !window.opener; // Remove this line to use Angular Universal
-
Alternatively, checks could be added before any lines that use browser-only global objects.
if (typeof window !== "undefined") { this.isIframe = window !== window.parent && !window.opener; }
-
The same check should be added to any HTTP calls made by your app, as the
MsalInterceptor
currently uses browser-only objects. This will be addressed in a future fix. See the example below in the profile.component.ts from our older MSAL Angular v2 Angular 11 sample app:export class ProfileComponent implements OnInit { profile!: ProfileType; constructor( private http: HttpClient ) { } ngOnInit() { // This check is added to ensure HTTP calls are made client-side if (typeof window !== "undefined") { this.getProfile(); } } getProfile() { this.http.get(GRAPH_ENDPOINT) .subscribe(profile => { this.profile = profile; }); } }
-
Ensure that your app is not using hash routing. The default routing strategy for the older MSAL Angular v2 Angular 11 sample app is hash routing, so ensure
useHash
is set tofalse
in the app-routing.module.ts:@NgModule({ imports: [RouterModule.forRoot(routes, { useHash: false, initialNavigation: 'enabled' })], exports: [RouterModule] }) export class AppRoutingModule { }