[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Other... Please describe:
Library version: "@azure/msal-angular": "0.1.2"
Angular version: 8.1.1
Build fails with
ERROR in Attempted to get members of a non-class: "export class MsalConfig {
constructor() {
this.authority = "https://login.microsoftonline.com/common";
this.validateAuthority = true;
this.cacheLocation = "sessionStorage";
this.loadFrameTimeout = 6000;
this.navigateToLoginRequestUrl = true;
}
}"
No error
Follow the steps here https://angular.io/guide/ivy and run ng serve
I'm facing the exact same issue. Msal-Angular is the only dependency in my project preventing me from using Ivy.
This might see a bit more traffic in the next few weeks - Angular 9 uses Ivy as its default engine, and had an RC1 release last week.
We are working to upgrade @azure/msal-angular to be compatible with latest version of Angular, include Ivy. We'll update this issue when we have an preview version you can try. Thanks!
We are working to upgrade
@azure/msal-angularto be compatible with latest version of Angular, include Ivy. We'll update this issue when we have an preview version you can try. Thanks!
@jasonnutter any ETC for this library to support for angular 8?
@stevenruizhang We are committed to have this work completed by the end of the year.
@jasonnutter I'm seeing the progress on MSAL Angular 1.0 which is exciting, however, I'm about to start a new Angular project, so we want/need to use Angular 9, and we're going to need to auth with Azure AD.
I know that MSAL.js is the recommended approach going forward, do you have any idea on when this library will work with Angular 9 and Ivy?
@snebjorn @willyt150 I have put together a sample for Angular 9 using the new version of MSAL and MSAL Angular. Can you please try this and let me know if you have any feedback? https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev-angular-9-sample/samples/angular9-sample-app
@jasonnutter thank you for pointing me to this sample.
The auth worked, ran into a few items/issues. I'm also going to try this in setting up my own project and see how it goes. I was under the impression that with Ivy and AoT compilation doing something like MsalModule.forRoot() in the import isn't supposed to be allowed, did you do something to get around that, or am I confusing something?
First, that I'm not sure if it's a true error or not, is when I did npm ci a few errors scrolled into view related to gyp.
Took a screenshot of the first one, and I tried it multiple times with the same results.

2nd, for the sample, once I authenticate and give the application access to my account, when I click the profile button I see an error thrown in the console. (Not sure if it's expected for this to work yet in the sample or if it's still in progress) Uncaught (in promise): InteractionRequiredAuthError: AADSTS65001: The user or administrator has not consented to use the application with ID '6226576d-37e9-49eb-b201-ec1eeb0029b6' named 'msal-angular2'. Send an interactive authorization request for this user and resource.
3rd, during the ng serve compilation it gave a warning about the @azure/msal-angular package: WARNING in Entry point '@azure/msal-angular' contains deep imports into '{folderpath}/node_modules/msal/lib-commonjs/utils/UrlUtils', '{folderpath}/node_modules/msal/lib-commonjs/cache/AuthCache', '{folderpath}/node_modules/msal/lib-commonjs/UserAgentApplication'. This is probably not a problem, but may cause the compilation of entry points to be out of order. Note: the {folderpath} is me removing my full directory path and NOT what was actually written
@willyt150
forRoot: I did not do anything special in that regard. I'll do some more research.npm ci: fsevents is for Mac only I believe, so I would expect errors when installing on Windows. Does that error happen with a stock Angular 9 app (without MSAL)?AADSTS65001: Are you logging in with a work or personal account? Try either logging in with a personal account, or create your own client id in your tenant.ng serve: Those warnings are currently expected, and will be fixed in a future version.@jasonnutter
ng update failed on saying that those weren't allowed. I compared a net new angular.json and tsconfig.json created by the latest angular cli to the ones in your samples and the only differences were names.npm ci on a new stock Angular 9 app. It DOES have the exact same errors, sorry for thinking it was from you :)Speaking of future versions, I thought I saw a planned roadmap with dates somewhere but have been unable to find it. Do you happen to have the link to that? Just trying to figure out how close to the planned GA v1 of the angular wrapper we are.
@willyt150
GA: we're working to have it ready for the end of this month, unfortunately, things keep getting pushed back due in part to some dependencies outside our team. Sorry for the delay on that. I'll have the roadmap updated and we'll let you know when we have a solid date.
Hi!
Updating from Angular 8 to 9 i'm getting a error that seems to be related with Ivy load:
ERROR NullInjectorError: "R3InjectorError(AppModule)[MsalService -> MsalService -> MsalService]:
NullInjectorError: No provider for MsalService!"
We were loading the module like this, cause the configs depend on data from an Angular Service.
@NgModule({
declarations: [AppComponent],
imports: [..., MsalModule...],
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: MsalInterceptor, multi: true },
{ provide: MSAL_CONFIG, useFactory: MSALConfigFactory, deps: [ConfigService] },
{ provide: MSAL_CONFIG_ANGULAR, useFactory: MSALConfigAngularFactory, deps: [ConfigService] },
MsalService,
{ provide: WindowWrapper, useValue: window },
],
bootstrap: [AppComponent]
})
export class AppModule {}
I see in the Angular 9 sample you load the module with a .forRoot() but this way is mandatory to pass the MSAL_CONFIG on it, but for me it depends on a factory... how can I pass the config data in a dynamic way?
Hi!
Updating from Angular 8 to 9 i'm getting a error that seems to be related with Ivy load:ERROR NullInjectorError: "R3InjectorError(AppModule)[MsalService -> MsalService -> MsalService]: NullInjectorError: No provider for MsalService!"We were loading the module like this, cause the configs depend on data from an Angular Service.
@NgModule({ declarations: [AppComponent], imports: [..., MsalModule...], providers: [ { provide: HTTP_INTERCEPTORS, useClass: MsalInterceptor, multi: true }, { provide: MSAL_CONFIG, useFactory: MSALConfigFactory, deps: [ConfigService] }, { provide: MSAL_CONFIG_ANGULAR, useFactory: MSALConfigAngularFactory, deps: [ConfigService] }, MsalService, { provide: WindowWrapper, useValue: window }, ], bootstrap: [AppComponent] }) export class AppModule {}I see in the Angular 9 sample you load the module with a .forRoot() but this way is mandatory to pass the MSAL_CONFIG on it, but for me it depends on a factory... how can I pass the config data in a dynamic way?
I'm having exactly the same problem, we are also using a factory (because of different configuration in dev/staging/production).
NullInjectorError: No provider for MsalService! R3InjectorError(AppModule)[AuthenticationService -> MsalService -> MsalService -> MsalService]
And that's the only reason why I can't enable Ivy in our Project.
@asanchezfe @strabu Thanks, that is very helpful. I'll investigate and follow up.
@jasonnutter I also have the config injection issue.
I'm writing my own AuthGuard and I need to
@Inject(MSAL_CONFIG) private readonly msalConfig: Configuration,
@Inject(MSAL_CONFIG_ANGULAR) private readonly msalAngularConfig: MsalAngularConfiguration,
Also they are not exported in the base module. So we have to import them like this. It's not ideal.
// tslint:disable-next-line: no-submodule-imports
import { MSAL_CONFIG, MSAL_CONFIG_ANGULAR } from '@azure/msal-angular/dist/msal.service';
Also I don't think the MsalService usage is clear.
Looking at https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/84136a0fa3e1ea57fd0bf579b7840d7fc86ef3fc/lib/msal-angular/src/msal-guard.service.ts#L27
First of, the Guard broadcasts msal:loginSuccess/loginFailure. Shouldn't that be handled by the MsalService? Perhaps I'm missing something.
2nd, it's a bit weird/redundant that the config is required in most calls. I mean surely loginPopup() should be enough as the MsalService already have access to the config.
Current API
.loginPopup({
scopes: this.msalAngularConfig.consentScopes,
extraQueryParameters: this.msalAngularConfig.extraQueryParameters
})
Please simplify the usage by making the arguments optional and if omitted then use the injected config. Where ever possible.
Lastly, I found it unclear when the MsalService would do an Auth "round trip" and when it would use the cached token. This, to me, looks like it'll fetch a token every time.
if (!this.authService.getAccount()) {
if (this.msalAngularConfig.popUp) {
return this.authService.loginPopup(...);
}
this.authService.loginRedirect(...);
} else {
return this.authService.acquireTokenSilent(...);
}
In the previous guard there was stuff like this which could be used to not re-fetch unless needed.
this.authService.updateDataFromCache([this.config.clientID]);
const isAuthenticated = this.authService._oauthData.isAuthenticated;
if (this.isObjectEmpty(this.authService._oauthData.idToken) &&
!this.authService._renewActive &&
!this.authService.loginInProgress()) {...}
Looking forward to the release. Keep up the good work :)
@snebjorn
MSAL_CONFIG, MSAL_CONFIG_ANGULAR: I agree, and am planning to make them available from the main export of the library.MsalGuard broadcasts: The difference with the MsalGuard broadcast is that it is broadcasting login-related events, whereas the MsalService broadcasts token-related events. It does look like both would occur, which I agree is potentially confusing (both conceptually and functionally).Appreciate the feedback!
@jasonnutter So we're running into a very similar issue to what's mentioned above for trying to setup MSAL without doing the .forRoot call. Just like the others we had to do this so we can host the same compiled site on different environments, each with their own Azure AD Application and tenant.
The error we're getting is: R3InjectorError(AppModule)[MsalService -> InjectionToken MSAL_CONFIG -> InjectionToken MSAL_CONFIG -> InjectionToken MSAL_CONFIG]:
NullInjectorError: No provider for InjectionToken MSAL_CONFIG! I don't think it likes this taking a Configuration object
Our approach works in an existing app that was build in Angular 8 using the 0.1.4 version of the MSAL for Angular package. We went the approach of the main.ts doing the work to pull down a file from the /assets folder containing the information required to populate a MsalConfig instance (This no longer exists in the v1.0.0-beta2 package). Then we provided that for the MSAL_CONFIG token in the code that bootstraps the AppModule.
e.g.
platformBrowserDynamic([
{provide: ConfigurationService, useValue: configurationService},
{provide: MSAL_CONFIG, useValue: msalConfig}
]).bootstrapModule(AppModule)
.catch(err => console.error(err));
However, when we try to go that similar approach with the beta bits is when we get the error.
Since the MsalConfig class is now gone, we modified it to use a Configuration from the 'msal' package (since that's what the .forRoot takes in), but other than that it's the exact same approach.
Am I missing something? Thanks!
I have released a new beta for MSAL Angular that should address compatibility issues with Ivy: @azure/[email protected]
This version was built with the Angular 9 CLI, and has been tested with the new Angular 9 sample app. Please test this out and let me know of any feedback (positive and negative!).
You can see complete details in #1323
Thanks!
@willyt150 Can you checkout this commit (which is based on the Angular 9 sample) and let me know if doing something like that works for your app?
@jasonnutter I haven't had a chance to update our implementation to use the new beta, but the commit you've linked to above follows the very same approach as what we were doing.
The only slight difference is that we're setting some of the values programmatically, like the popup, for the handling of IE, but I would assume that should work ok.
I'm hoping to have a chance tomorrow to look into it.
@jasonnutter we've had a chance to try the new beta with our main.ts approach and it's working!
thank you very much!
For us, without changes, seems to work also. Can't test a lot because we have other libraries not compatible with ng9 yet so we'll not take it into prod.
@willyt150 @asanchezfe Great to hear, thanks for the feedback!
@jasonnutter thanks a lot!
Now it also works for us with Ivy.
@jasonnutter It works! 馃殌
But...
Any particular reason MsalService isn't provided in root?
https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/9d809a9fe7618768bc35614c7a457110fd8c96a9/lib/msal-angular/src/msal.service.ts#L31
If it's provided in root we don't have to provide it our self. Like it's done in the sample
https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/9d809a9fe7618768bc35614c7a457110fd8c96a9/samples/angular9-sample-app/src/app/app.module.ts#L94
ModuleWithProviders is deprecated (see https://angular.io/guide/migration-module-with-providers) in favor of ModuleWithProviders<MsalModule>
https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/9d809a9fe7618768bc35614c7a457110fd8c96a9/lib/msal-angular/src/msal.module.ts#L21
The demo app manually provides MSAL_CONFIG and MSAL_CONFIG_ANGULAR. That's fine.
https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/9d809a9fe7618768bc35614c7a457110fd8c96a9/samples/angular9-sample-app/src/app/app.module.ts#L87
However I find it easier just use forRoot like so MsalModule.forRoot(environment.msalConfig, environment.msalAngularConfig) then the MsalModule will setup the providers.
Lastly it would be nice if the typescript source files where published. Cause if I in vscode goto definition of MsalModule I get this
import { ModuleWithProviders } from "@angular/core";
import { Configuration } from "msal";
import { MsalAngularConfiguration } from "./msal-angular.configuration";
import * as 傻ngcc0 from '@angular/core';
import * as 傻ngcc1 from '@angular/common';
export declare class MsalModule {
static forRoot(config: Configuration, angularConfig?: MsalAngularConfiguration): ModuleWithProviders<MsalModule>;
static 傻mod: 傻ngcc0.傻傻NgModuleDefWithMeta<MsalModule, never, [typeof 傻ngcc1.CommonModule], never>;
static 傻inj: 傻ngcc0.傻傻InjectorDef<MsalModule>;
}
I expected this https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/src/msal.module.ts
Any particular reason MsalService isn't provided in root?
I'm not sure, I'll look into that.
ModuleWithProviders is deprecated
Good to know.
Lastly it would be nice if the typescript source files where published.
I'll see about including them, hopefully just a setting in ng-packagr.
Most helpful comment
We are working to upgrade
@azure/msal-angularto be compatible with latest version of Angular, include Ivy. We'll update this issue when we have an preview version you can try. Thanks!