Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disable or bypass MSAL authentication when running Angular e2e tests?

I want to set up some end to end tests for my Angular application, which requires the use of the MSAL library to authenticate with some downstream services. When I try to run my e2e tests locally, the MSAL library is forcing me to authenticate with a username/password.

This is a problem because our CI/CD e2e testing should not have any human-intervention; thus I am looking for a way to either bypass the MSAL authentication or set up a service-account to login. Unfortunately there is not a lot of documentation surrounding MSAL for Angular (especially when it comes to e2e testing), but this seems like a common issue that others may have run into.

I've tried to disable the MsalModule from our app.module.ts file but I am still prompted for login when I try to run the application. I've also seen some articles trying to programmatically log in, but this does not work for us as MSAL is technically not an Angular component we are able to touch.

app.module.ts:

@NgModule({
  ...
  imports: [
    ...
    MsalModule.forRoot({
      clientID: '<client_id>',
      authority: <microsoft_authority_url>,
      validateAuthority: true,
      redirectUri: "http://localhost:4200/",
      cacheLocation : "localStorage",
      postLogoutRedirectUri: "http://localhost:4200/",
      navigateToLoginRequestUrl: true,
      popUp: true,
      consentScopes: [ "user.read"],
      unprotectedResources: ["https://www.microsoft.com/en-us/"],
      protectedResourceMap: protectedResourceMap,
      logger: loggerCallback,
      correlationId: '1234',
      level: LogLevel.Info,
      piiLoggingEnabled: true
    })
  ],
  entryComponents: [SaveDialogComponent,
                    GenericDialog, MassChangeDialogComponent],
  providers: [TitleCasePipe,
    {provide: HTTP_INTERCEPTORS, useClass: MsalInterceptor, multi: true}],
  bootstrap: [AppComponent]
})
export class AppModule { }

Expected result: removing the MSAL authentication module should allow our application to run without needing to log in.

Actual result: application is still prompting for log in, or does not render correctly.

like image 365
Alan Bentley Avatar asked Jun 14 '19 14:06

Alan Bentley


2 Answers

I solved that by adding a property enableMsal into my environment.test.ts (and same property with value true in prod environment):

export const environment = {
  production: false,
  enableMsal: false,
};

Then used it in routing module (by default called app-routing.module.ts, like this:

//... 
const guards: any[] = environment.enableMsal ? [MsalGuard] : [];

const routes: Routes = [
  {path: '', redirectTo: '/main', pathMatch: 'full'},
  {path: 'main', component: MainComponent, canActivate: guards},
  {path: 'other', component: OtherComponent, canActivate: guards},
];
//...

In case you don't know how to configure multiple environments, angular has a good guide here.

like image 74
Philip Patrick Avatar answered Oct 02 '22 09:10

Philip Patrick


To Bypass MSAL you can mock the implementation of MsalGuard, MsalService and MsalInterceptor inside main-skip-login.ts which is a replica of main.ts file.

import { MsalGuard, MsalInterceptor, MsalService } from '@azure/msal-angular';

MsalGuard.prototype.canActivate = () => true;

MsalInterceptor.prototype.intercept = (req, next) => {
  const access = localStorage.getItem('access_token');
  req = req.clone({
    setHeaders: {
      Authorization: `Bearer ${access}`
    }
  });
  return next.handle(req);
};

MsalService.prototype.getAccount = (): any => {
  if (!localStorage.getItem('access_token')) return undefined;
  return {
    idToken: {
      scope: [],
      // other claims if required
    }
  };
};

Then create a configuration named e2e inside angular.json and replace main.ts with main-skip-login.ts.

"configurations": {
            "e2e": {
              "fileReplacements": [
                {
                  "replace": "src/main.ts",
                  "with": "src/main-skip.login.ts"
                }
              ]
}}

Now you can run project with this configuration and set localStorage with authentic token to bypass MSAL auth flow. You can also play with mocking logic to get the desired outcome.

like image 33
murgank Avatar answered Oct 02 '22 09:10

murgank