<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: sforsandeep</title>
    <description>The latest articles on DEV Community by sforsandeep (@sforsandeep).</description>
    <link>https://dev.to/sforsandeep</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F654057%2Facd67080-a479-4ec5-8e9c-911a2d9f1115.jpeg</url>
      <title>DEV Community: sforsandeep</title>
      <link>https://dev.to/sforsandeep</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sforsandeep"/>
    <language>en</language>
    <item>
      <title>Types of property 'providers' are incompatible.</title>
      <dc:creator>sforsandeep</dc:creator>
      <pubDate>Tue, 22 Jun 2021 18:24:39 +0000</pubDate>
      <link>https://dev.to/sforsandeep/types-of-property-providers-are-incompatible-b6a</link>
      <guid>https://dev.to/sforsandeep/types-of-property-providers-are-incompatible-b6a</guid>
      <description>&lt;p&gt;I am trying to dynamically load MSAL configurations from JSON file. here is my Service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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&amp;lt;boolean&amp;gt; {
    return new Promise&amp;lt;boolean&amp;gt;((resolve, reject) =&amp;gt; {


      var envFile:string="environment/conf.json";
      this.http.get(envFile).pipe(map(res =&amp;gt; res))
      .pipe(map(res =&amp;gt; res))
    .subscribe(value =&amp;gt; {

      this.config=value;

      this.http.get(envFile).pipe(map(res =&amp;gt; res))
        .subscribe(value =&amp;gt; {
          this.settings = value;
          resolve(true);
        },
        (error) =&amp;gt; {
          reject(error);
        });
    });



    });
  }

  getSettings(key?: string | Array&amp;lt;string&amp;gt;): any {
    if (!key || (Array.isArray(key) &amp;amp;&amp;amp; !key[0])) {
      return this.settings;
    }

    if (!Array.isArray(key)) {
      key = key.split('.');
    }

    let result = key.reduce((acc: any, current: string) =&amp;gt; acc &amp;amp;&amp;amp; acc[current], this.settings);

    return result;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is my module for feeding all the options&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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 ") &amp;gt; -1 || window.navigator.userAgent.indexOf("Trident/") &amp;gt; -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&amp;lt;string, Array&amp;lt;string&amp;gt;&amp;gt;{
    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&amp;lt;string&amp;gt;('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) =&amp;gt; {
        console.log(env.getSettings('clientID'));
    });
    return () =&amp;gt; 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                     

            ]
        };
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is my appmodule&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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 { }



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But I am getting an error only at the import in appmodule &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;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&amp;lt;{}&amp;gt;'.&lt;br&gt;
  Type '{ ngModule: typeof MsalApplicationModule; providers: (typeof MsalService | typeof MsalBroadcastService | typeof MsalGuard | typeof ConfigService | ... 5 more ... | { ...; })[]; }' is not assignable to type 'ModuleWithProviders&amp;lt;{}&amp;gt;'.&lt;br&gt;
    Types of property 'providers' are incompatible.&lt;br&gt;
      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[]'.&lt;br&gt;
        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'.&lt;br&gt;
          Type '{ provide: InjectionToken; useFactory?: undefined; multi?: undefined; useClass?: undefined; }' is not assignable to type 'Provider'.&lt;br&gt;
            Type '{ provide: InjectionToken; useFactory?: undefined; multi?: undefined; useClass?: undefined; }' is not assignable to type 'FactoryProvider'.&lt;br&gt;
              Types of property 'useFactory' are incompatible.&lt;br&gt;
                Type 'undefined' is not assignable to type 'Function'.&lt;/p&gt;

&lt;p&gt;62     MsalApplicationModule.forRoot()&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Please help me. I didnt understand what I did wrong.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
