Types of property 'providers' are incompatible.
sforsandeep
Posted on June 22, 2021
I am trying to dynamically load MSAL configurations from JSON file. here is my Service
import { Injectable } from '@angular/core';
import { HttpClient, HttpBackend } from '@angular/common/http';
import { map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class ConfigService {
private config:any = null;
private env:any = null;
/**
* Use to get the data found in the second file (config file)
*/
public getConfig(key: any) {
return this.config[key];
}
/**
* Use to get the data found in the first file (env file)
*/
public getEnv(key: any) {
return this.env[key];
}
private settings: any;
private http: HttpClient;
constructor(private readonly httpHandler: HttpBackend) {
this.http = new HttpClient(httpHandler);
}
init(): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
var envFile:string="environment/conf.json";
this.http.get(envFile).pipe(map(res => res))
.pipe(map(res => res))
.subscribe(value => {
this.config=value;
this.http.get(envFile).pipe(map(res => res))
.subscribe(value => {
this.settings = value;
resolve(true);
},
(error) => {
reject(error);
});
});
});
}
getSettings(key?: string | Array<string>): any {
if (!key || (Array.isArray(key) && !key[0])) {
return this.settings;
}
if (!Array.isArray(key)) {
key = key.split('.');
}
let result = key.reduce((acc: any, current: string) => acc && acc[current], this.settings);
return result;
}
}
Here is my module for feeding all the options
import { HTTP_INTERCEPTORS } from "@angular/common/http";
import { APP_INITIALIZER, NgModule } from "@angular/core";
import { InjectionToken } from "@angular/core";
import { MsalBroadcastService, MsalGuard, MsalGuardConfiguration, MsalInterceptor, MsalInterceptorConfiguration, MsalModule, MsalService, MSAL_GUARD_CONFIG, MSAL_INSTANCE, MSAL_INTERCEPTOR_CONFIG } from "@azure/msal-angular";
import { BrowserCacheLocation, Configuration, InteractionType, IPublicClientApplication, LogLevel, PublicClientApplication } from "@azure/msal-browser";
import { ConfigService } from "./shared/services/config.service";
const isIE = window.navigator.userAgent.indexOf("MSIE ") > -1 || window.navigator.userAgent.indexOf("Trident/") > -1;
export function msalConfig(): Configuration {
const configuration:Configuration={
auth: {
clientId: 'clientid', // This is the ONLY mandatory field that you need to supply.
authority: 'https://login.microsoftonline.com/hidingtenentid', // Defaults to "https://login.microsoftonline.com/common"
redirectUri: 'http://localhost:4200', // Points to window.location.origin. You must register this URI on Azure portal/App Registration.
postLogoutRedirectUri: '/', // Indicates the page to navigate after logout.
navigateToLoginRequestUrl: true, // If "true", will navigate back to the original request location before processing the auth code response.
},
cache: {
cacheLocation: BrowserCacheLocation.LocalStorage, // Configures cache location. "sessionStorage" is more secure, but "localStorage" gives you SSO between tabs.
storeAuthStateInCookie: isIE, // Set this to "true" if you are having issues on IE11 or Edge
},
system: {
loggerOptions: {
loggerCallback(logLevel: LogLevel, message: string) {
console.log(message);
},
logLevel: LogLevel.Verbose,
piiLoggingEnabled: false
}
}
}
return configuration;
}
/**
* Add here the endpoints and scopes when obtaining an access token for protected web APIs. For more information, see:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/resources-and-scopes.md
*/
export function protectedResources(config:ConfigService): Map<string, Array<string>>{
return new Map([
['https://graph.microsoft.com/v1.0/me', ['user.read']],
[
'api/pepics',
[config.getSettings("ApiClientId")+ '/user_impersonation'],
],
]);
}
/**
* An optional silentRequest object can be used to achieve silent SSO
* between applications by providing a "login_hint" property.
*/
export const silentRequest = {
scopes: ["openid", "profile"],
loginHint: "example@domain.net"
};
/**
* Scopes you add here will be prompted for user consent during sign-in.
* By default, MSAL.js will add OIDC scopes (openid, profile, email) to any login request.
* For more information about OIDC scopes, visit:
* https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#openid-connect-scopes
*/
export const loginRequest = {
scopes: []
};
/**
* Here we pass the configuration parameters to create an MSAL instance.
* For more info, visit: https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/docs/v2-docs/configuration.md
*/
export function MSALInstanceFactory(): IPublicClientApplication {
return new PublicClientApplication(msalConfig());
}
/**
* MSAL Angular will automatically retrieve tokens for resources
* added to protectedResourceMap. For more info, visit:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/docs/v2-docs/initialization.md#get-tokens-for-web-api-calls
*/
export function MSALInterceptorConfigFactory(conf:ConfigService): MsalInterceptorConfiguration {
return {
interactionType: InteractionType.Redirect,
protectedResourceMap: protectedResources(conf)
};
}
/**
* Set your default interaction type for MSALGuard here. If you have any
* additional scopes you want the user to consent upon login, add them here as well.
*/
export function MSALGuardConfigFactory(): MsalGuardConfiguration {
return {
interactionType: InteractionType.Redirect,
authRequest: loginRequest
};
}
const AUTH_CONFIG_URL_TOKEN = new InjectionToken<string>('AUTH_CONFIG_URL');
export function initializerFactory(env: ConfigService): any {
// APP_INITIALIZER, except a function return which will return a promise
// APP_INITIALIZER, angular doesnt starts application untill it completes
const promise = env.init().then((value) => {
console.log(env.getSettings('clientID'));
});
return () => promise;
}
@NgModule({
providers: [
],
imports: [MsalModule]
})
export class MsalApplicationModule {
static forRoot() {
return {
ngModule: MsalApplicationModule,
providers: [
ConfigService,
{ provide: AUTH_CONFIG_URL_TOKEN },
{ provide: APP_INITIALIZER, useFactory: initializerFactory, multi: true },
{
provide: HTTP_INTERCEPTORS,
useClass: MsalInterceptor,
multi: true
},
{
provide: MSAL_INSTANCE,
useFactory: MSALInstanceFactory
},
{
provide: MSAL_GUARD_CONFIG,
useFactory: MSALGuardConfigFactory
},
{
provide: MSAL_INTERCEPTOR_CONFIG,
useFactory: MSALInterceptorConfigFactory
},
MsalService,
MsalGuard,
MsalBroadcastService
]
};
}
}
And this is my appmodule
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule,AppRoutingComonent } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'
import { DashboardComponent } from './pages/dashboard/dashboard.component';
import { SidebarMenuComponent } from './components/main-sidebar/sidebar-menu/sidebar-menu.component';
import { SidebarSearchComponent } from './components/main-sidebar/sidebar-search/sidebar-search.component';
import { MainSidebarComponent } from './components/main-sidebar/main-sidebar.component';
import { NavbarComponent } from './components/navbar/navbar.component';
import { SampleButtonComponent } from './samples/sample-button/sample-button.component';
import { GeneralElementsComponent } from './samples/general-elements/general-elements.component';
import { SimpleTablesComponent } from './samples/simple-tables/simple-tables.component';
import { DataTablesComponent } from './samples/data-tables/data-tables.component';
import { WidgetsComponent } from './samples/widgets/widgets.component';
import { SampleFormComponent } from './samples/sample-form/sample-form.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {DataTablesModule} from 'angular-datatables'
import { ToastrModule } from 'ngx-toastr';
import { AdvancedFormComponent } from './samples/advanced-form/advanced-form.component';
import { NgWizardModule, NgWizardConfig, THEME } from 'ng-wizard';
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { MsalApplicationModule } from './msal-application.module';
const ngWizardConfig: NgWizardConfig = {
theme: THEME.default
};
@NgModule({
declarations: [
AppComponent,
AppRoutingComonent,
DashboardComponent,
MainSidebarComponent,
SidebarMenuComponent,
SidebarSearchComponent,
NavbarComponent,
SampleButtonComponent,
GeneralElementsComponent,
SimpleTablesComponent,
DataTablesComponent,
WidgetsComponent,
SampleFormComponent,
AdvancedFormComponent
],
imports: [
BrowserModule,
DataTablesModule,
HttpClientModule,
AppRoutingModule,
MatDialogModule,
BrowserAnimationsModule, // required animations module
ToastrModule.forRoot(), // ToastrModule added,
NgWizardModule.forRoot(ngWizardConfig),
MsalApplicationModule.forRoot()
],
providers: [
{
provide: MatDialogRef,
useValue: {}
}
],
bootstrap: [AppComponent]
})
export class AppModule { }
But I am getting an error only at the import in appmodule
Error: src/app/app.module.ts:62:5 - error TS2322: Type '{ ngModule: typeof MsalApplicationModule; providers: (typeof MsalService | typeof MsalBroadcastService | typeof MsalGuard | typeof ConfigService | ... 5 more ... | { ...; })[]; }' is not assignable to type 'any[] | Type | ModuleWithProviders<{}>'.
Type '{ ngModule: typeof MsalApplicationModule; providers: (typeof MsalService | typeof MsalBroadcastService | typeof MsalGuard | typeof ConfigService | ... 5 more ... | { ...; })[]; }' is not assignable to type 'ModuleWithProviders<{}>'.
Types of property 'providers' are incompatible.
Type '(typeof MsalService | typeof MsalBroadcastService | typeof MsalGuard | typeof ConfigService | { provide: InjectionToken; useFactory?: undefined; multi?: undefined; useClass?: undefined; } | ... 4 more ... | { ...; })[]' is not assignable to type 'Provider[]'.
Type 'typeof MsalService | typeof MsalBroadcastService | typeof MsalGuard | typeof ConfigService | { provide: InjectionToken; useFactory?: undefined; multi?: undefined; useClass?: undefined; } | ... 4 more ... | { ...; }' is not assignable to type 'Provider'.
Type '{ provide: InjectionToken; useFactory?: undefined; multi?: undefined; useClass?: undefined; }' is not assignable to type 'Provider'.
Type '{ provide: InjectionToken; useFactory?: undefined; multi?: undefined; useClass?: undefined; }' is not assignable to type 'FactoryProvider'.
Types of property 'useFactory' are incompatible.
Type 'undefined' is not assignable to type 'Function'.62 MsalApplicationModule.forRoot()
Please help me. I didnt understand what I did wrong.
Posted on June 22, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 29, 2024