Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MsalInterceptor and MsalService classes are no longer working in providers property for standalone projects #6040

Closed
fayeBabacar78 opened this issue May 18, 2023 · 1 comment
Assignees
Labels
bug-unconfirmed A reported bug that needs to be investigated and confirmed msal-angular Related to @azure/msal-angular package msal-browser Related to msal-browser package public-client Issues regarding PublicClientApplications question Customer is asking for a clarification, use case or information.

Comments

@fayeBabacar78
Copy link

fayeBabacar78 commented May 18, 2023

Core Library

MSAL.js v2 (@azure/msal-browser)

Core Library Version

2.37.0

Wrapper Library

MSAL Angular (@azure/msal-angular)

Wrapper Library Version

2.5.7

Public or Confidential Client?

Public

Description

I'm building an angular project using the standlone api, so in my app, I no longer rely on the AppModule to configure providers. I used to do so but many things have changed with the standalone api for example providers are now functions instead of classes.
This is not working actually and I think it's because of the new approach to define providers, by usingfunctions.

Error Message

main.ts:7 Error: NG0204: Can't resolve all parameters for MsalInterceptor: (?, ?, ?, ?, ?).
at getUndecoratedInjectableFactory (core.mjs:9296:15)
at injectableDefOrInjectorDefFactory (core.mjs:9286:16)
at providerToFactory (core.mjs:9354:51)
at providerToRecord (core.mjs:9316:25)
at R3Injector.processProvider (core.mjs:9213:24)
at core.mjs:9041:59
at forEachSingleProvider (core.mjs:9387:13)
at new R3Injector (core.mjs:9041:9)
at new EnvironmentNgModuleRefAdapter (core.mjs:21574:26)
at internalCreateApplication (core.mjs:26694:25)

Msal Logs

No response

MSAL Configuration

const isIE = window.navigator.userAgent.indexOf('MSIE ') > -1 || window.navigator.userAgent.indexOf('Trident/') > -1;

export function msalInstanceFactory(): IPublicClientApplication {
  return new PublicClientApplication({
    auth: {
      clientId: '',
      authority: '',
      redirectUri: 'http://localhost:4200/portal',
    },
    cache: {
      cacheLocation: BrowserCacheLocation.LocalStorage,
      storeAuthStateInCookie: isIE
    },
  })
}

export function MsalGuardConfFactory(): MsalGuardConfiguration {
  return {
    interactionType: InteractionType.Redirect,
    authRequest: {scopes: ['user.read']}
  } as MsalGuardConfiguration;
}

export function MsalInterceptorConfFactory(): MsalInterceptorConfiguration {
  const baseUrl = '';
  return {
    interactionType: InteractionType.Redirect,
    protectedResourceMap: new Map([[baseUrl, [baseUrl + '/.default']]])
  } as MsalInterceptorConfiguration
}

Relevant Code Snippets

Before:

@NgModule({
  providers: [
    {
      provide: MSAL_INSTANCE,
      useFactory: MsalInstanceFactory
    },
    {
      provide: MSAL_GUARD_CONFIG,
      useFactory: MsalGuardConfFactory
    },
    {
      provide: MSAL_INTERCEPTOR_CONFIG,
      useFactory: MsalInterceptorConfFactory
    },
    {
      provide: HTTP_INTERCEPTORS,
      useClass: MsalInterceptor,
      multi: true
    },
    MsalGuard,
    MsalService,
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

After:

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    {
      provide: MSAL_INSTANCE,
      useFactory: msalInstanceFactory
    },
    {
      provide: MSAL_GUARD_CONFIG,
      useFactory: msalGuardConfFactory
    },
    {
      provide: MSAL_INTERCEPTOR_CONFIG,
      useFactory: msalInterceptorConfFactory
    },
    {
      provide: HTTP_INTERCEPTORS,
      useClass: MsalInterceptor,
      multi: true
    },
    MsalService,
    provideHttpClient(withInterceptorsFromDi())
  ]
};

Login component:

@Component({
  selector: 'app-login',
  standalone: true,
  imports: [CommonModule, ButtonModule],
  providers: [],
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss']
})
export default class LoginComponent {

  isIframe = false;
  isLoggedIn = false;

  msalService = Inject(MsalService);
  broadcastService = inject(MsalBroadcastService);

  constructor(
    @Inject(MSAL_GUARD_CONFIG) private msalGuardConfig: MsalGuardConfiguration ) {
  }

  ngOnInit(): void {
    this.isIframe = window !== window.parent && !window.opener;
    this.broadcastService.inProgress$ // interaction status
      .pipe(filter((status: InteractionStatus) => status === InteractionStatus.None)) // no interaction
      .pipe() // takeUntilDestroyed(this)
      .subscribe(() => {
        this.isLoggedIn = this.isSignedIn();
      })
  }

  isSignedIn() {
    return this.msalService.instance.getAllAccounts().length > 0;
  }

  signIn() {
    if (this.msalGuardConfig.authRequest) {
      this.msalService.loginRedirect({...this.msalGuardConfig.authRequest} as RedirectRequest);
    } else {
      this.msalService.loginRedirect();
    }
  }

  async signOut() { // sign out using redirects
    await this.msalService.logoutRedirect({
      postLogoutRedirectUri: 'http://localhost:4200/portal'
    });
  }
}

Reproduction Steps

Before:

@NgModule({
  providers: [
    {
      provide: MSAL_INSTANCE,
      useFactory: MsalInstanceFactory
    },
    {
      provide: MSAL_GUARD_CONFIG,
      useFactory: MsalGuardConfFactory
    },
    {
      provide: MSAL_INTERCEPTOR_CONFIG,
      useFactory: MsalInterceptorConfFactory
    },
    {
      provide: HTTP_INTERCEPTORS,
      useClass: MsalInterceptor,
      multi: true
    },
    MsalGuard,
    MsalService,
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

After:

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    {
      provide: MSAL_INSTANCE,
      useFactory: msalInstanceFactory
    },
    {
      provide: MSAL_GUARD_CONFIG,
      useFactory: msalGuardConfFactory
    },
    {
      provide: MSAL_INTERCEPTOR_CONFIG,
      useFactory: msalInterceptorConfFactory
    },
    {
      provide: HTTP_INTERCEPTORS,
      useClass: MsalInterceptor,
      multi: true
    },
    MsalService,
    provideHttpClient(withInterceptorsFromDi())
  ]
};

Expected Behavior

This is to let msal handles the token acquisition for api requests.

Identity Provider

Azure AD / MSA

Browsers Affected (Select all that apply)

Chrome, Edge

Regression

No response

Source

Internal (Microsoft)

@fayeBabacar78 fayeBabacar78 added bug-unconfirmed A reported bug that needs to be investigated and confirmed question Customer is asking for a clarification, use case or information. labels May 18, 2023
@ghost ghost added the Needs: Attention 👋 Awaiting response from the MSAL.js team label May 18, 2023
@github-actions github-actions bot added msal-angular Related to @azure/msal-angular package msal-browser Related to msal-browser package public-client Issues regarding PublicClientApplications labels May 18, 2023
@ghost ghost assigned tnorling May 18, 2023
@tnorling
Copy link
Collaborator

Closing as duplicate of #5988. We are unlikely to make any updates to support this in v2. We'll consider changes for v3 and provide any updates in the linked issue.

@ghost ghost removed the Needs: Attention 👋 Awaiting response from the MSAL.js team label May 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug-unconfirmed A reported bug that needs to be investigated and confirmed msal-angular Related to @azure/msal-angular package msal-browser Related to msal-browser package public-client Issues regarding PublicClientApplications question Customer is asking for a clarification, use case or information.
Projects
None yet
Development

No branches or pull requests

2 participants