or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

authentication-service.mdcomponents-module.mdevent-broadcasting.mdhttp-interceptor.mdindex.mdroute-protection.md
tile.json

components-module.mddocs/

Components and Module System

Angular components and module configuration for complete MSAL integration including redirect handling, dependency injection setup, and navigation optimization.

Capabilities

MsalRedirectComponent

Dedicated component for handling authentication redirects in Angular applications, ensuring proper redirect flow processing.

/**
 * Component for handling authentication redirects
 * Should be used as a dedicated route for redirect handling
 */
@Component({
  selector: 'app-redirect',
  template: ''
})
class MsalRedirectComponent implements OnInit {
  /**
   * Handles redirect observable on component initialization
   * Processes authentication results from redirect flows
   */
  ngOnInit(): void;
}

Usage Example:

import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { MsalRedirectComponent } from "@azure/msal-angular";

const routes: Routes = [
  {
    path: 'auth/redirect',
    component: MsalRedirectComponent
  },
  // Other routes...
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

MsalModule

Main module for MSAL Angular integration providing comprehensive configuration and dependency injection setup.

/**
 * Main Angular module for MSAL integration
 * Provides all necessary components, services, and configuration
 */
class MsalModule {
  /**
   * Configures the module with MSAL instance and configuration objects
   * @param msalInstance - The MSAL browser instance
   * @param guardConfig - Configuration for MsalGuard
   * @param interceptorConfig - Configuration for MsalInterceptor
   * @returns ModuleWithProviders containing all MSAL providers
   */
  static forRoot(
    msalInstance: IPublicClientApplication, 
    guardConfig: MsalGuardConfiguration, 
    interceptorConfig: MsalInterceptorConfiguration
  ): ModuleWithProviders<MsalModule>;
}

Complete Application Setup:

import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { HttpClientModule, HTTP_INTERCEPTORS } from "@angular/common/http";
import { RouterModule } from "@angular/router";

import { PublicClientApplication, InteractionType, LogLevel } from "@azure/msal-browser";
import { 
  MsalModule, 
  MsalRedirectComponent,
  MsalService, 
  MsalGuard, 
  MsalInterceptor,
  MsalBroadcastService,
  MsalGuardConfiguration,
  MsalInterceptorConfiguration,
  MSAL_INSTANCE,
  MSAL_GUARD_CONFIG,
  MSAL_INTERCEPTOR_CONFIG
} from "@azure/msal-angular";

import { AppComponent } from "./app.component";
import { AppRoutingModule } from "./app-routing.module";

// MSAL Configuration
const msalConfig = {
  auth: {
    clientId: "your-client-id",
    authority: "https://login.microsoftonline.com/your-tenant-id",
    redirectUri: window.location.origin + "/auth/redirect",
    postLogoutRedirectUri: window.location.origin
  },
  cache: {
    cacheLocation: "localStorage",
    storeAuthStateInCookie: false
  },
  system: {
    loggerOptions: {
      loggerCallback: (level: LogLevel, message: string) => {
        console.log(`MSAL [${LogLevel[level]}]: ${message}`);
      },
      logLevel: LogLevel.Warning
    }
  }
};

const msalInstance = new PublicClientApplication(msalConfig);

// Guard Configuration
const guardConfig: MsalGuardConfiguration = {
  interactionType: InteractionType.Redirect,
  authRequest: {
    scopes: ["user.read", "openid", "profile"]
  },
  loginFailedRoute: "/login-failed"
};

// Interceptor Configuration
const interceptorConfig: MsalInterceptorConfiguration = {
  interactionType: InteractionType.Redirect,
  protectedResourceMap: new Map([
    ["https://graph.microsoft.com/v1.0/me", ["user.read"]],
    ["https://graph.microsoft.com/v1.0/users", ["user.read.all"]],
    ["https://api.myapp.com/", ["api://myapp-id/access_as_user"]]
  ])
};

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    AppRoutingModule,
    MsalModule.forRoot(msalInstance, guardConfig, interceptorConfig)
  ],
  providers: [
    // HTTP Interceptor registration
    {
      provide: HTTP_INTERCEPTORS,
      useClass: MsalInterceptor,
      multi: true
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

MsalCustomNavigationClient

Custom navigation client for optimizing single-page application navigation and improving user experience during authentication flows.

/**
 * Custom navigation client for Angular client-side navigation optimization
 * Extends MSAL's NavigationClient to work better with Angular Router
 */
class MsalCustomNavigationClient extends NavigationClient {
  /**
   * Custom navigation implementation for Angular applications
   * @param url - URL to navigate to
   * @param options - Navigation options
   * @returns Promise resolving to boolean indicating navigation success
   */
  navigateInternal(url: string, options: NavigationOptions): Promise<boolean>;
}

Advanced Setup with Custom Navigation:

import { Injectable } from "@angular/core";
import { Router } from "@angular/router";
import { Location } from "@angular/common";
import { 
  MsalCustomNavigationClient,
  MSAL_INSTANCE 
} from "@azure/msal-angular";
import { 
  PublicClientApplication, 
  NavigationClient,
  NavigationOptions 
} from "@azure/msal-browser";

@Injectable()
export class CustomNavigationService extends MsalCustomNavigationClient {
  constructor(
    private router: Router,
    private location: Location
  ) {
    super();
  }

  navigateInternal(url: string, options: NavigationOptions): Promise<boolean> {
    // Custom navigation logic using Angular Router
    if (options.noHistory) {
      this.location.replaceState(url);
      return Promise.resolve(true);
    } else {
      return this.router.navigateByUrl(url);
    }
  }
}

// Factory function for MSAL instance with custom navigation
export function MSALInstanceFactory(): PublicClientApplication {
  const msalInstance = new PublicClientApplication(msalConfig);
  
  // Set custom navigation client
  const customNavigationClient = new CustomNavigationService(
    // Router and Location will be injected
  );
  msalInstance.setNavigationClient(customNavigationClient);
  
  return msalInstance;
}

@NgModule({
  providers: [
    {
      provide: MSAL_INSTANCE,
      useFactory: MSALInstanceFactory,
      deps: [Router, Location]
    },
    CustomNavigationService
  ]
})
export class AppModule { }

Lazy Loading and Feature Modules

// Shared MSAL module for feature modules
@NgModule({
  imports: [CommonModule],
  providers: [
    // Services are already provided by root MsalModule
    // Just import the services in feature modules
  ],
  exports: []
})
export class SharedMsalModule { }

// Feature module with MSAL integration
@NgModule({
  declarations: [
    ProfileComponent,
    DashboardComponent
  ],
  imports: [
    CommonModule,
    SharedMsalModule,
    RouterModule.forChild([
      { 
        path: 'profile', 
        component: ProfileComponent,
        canActivate: [MsalGuard]
      },
      { 
        path: 'dashboard', 
        component: DashboardComponent,
        canActivate: [MsalGuard]
      }
    ])
  ]
})
export class UserModule { }

Environment-Specific Configuration

// environment.prod.ts
export const environment = {
  production: true,
  msalConfig: {
    auth: {
      clientId: "prod-client-id",
      authority: "https://login.microsoftonline.com/prod-tenant-id",
      redirectUri: "https://myapp.com/auth/redirect"
    }
  }
};

// environment.ts
export const environment = {
  production: false,
  msalConfig: {
    auth: {
      clientId: "dev-client-id",
      authority: "https://login.microsoftonline.com/dev-tenant-id",
      redirectUri: "http://localhost:4200/auth/redirect"
    }
  }
};

// app.module.ts
import { environment } from "../environments/environment";

const msalInstance = new PublicClientApplication(environment.msalConfig);

@NgModule({
  imports: [
    MsalModule.forRoot(msalInstance, guardConfig, interceptorConfig)
  ]
})
export class AppModule { }

Dependency Injection Tokens

All injection tokens for configuring MSAL services:

/** Injection token for the MSAL browser instance */
const MSAL_INSTANCE: InjectionToken<string>;

/** Injection token for MsalGuard configuration */
const MSAL_GUARD_CONFIG: InjectionToken<string>;

/** Injection token for MsalInterceptor configuration */
const MSAL_INTERCEPTOR_CONFIG: InjectionToken<string>;

/** Injection token for MsalBroadcastService configuration */
const MSAL_BROADCAST_CONFIG: InjectionToken<string>;

Testing Configuration

import { TestBed } from "@angular/core/testing";
import { 
  MsalModule, 
  MsalService, 
  MSAL_INSTANCE 
} from "@azure/msal-angular";
import { PublicClientApplication } from "@azure/msal-browser";

describe('Component with MSAL', () => {
  let mockMsalInstance: jasmine.SpyObj<PublicClientApplication>;

  beforeEach(() => {
    // Create mock MSAL instance
    mockMsalInstance = jasmine.createSpyObj('PublicClientApplication', [
      'getAllAccounts',
      'loginPopup',
      'logoutPopup',
      'acquireTokenSilent'
    ]);

    TestBed.configureTestingModule({
      imports: [
        // Use a minimal configuration for testing
        MsalModule
      ],
      providers: [
        {
          provide: MSAL_INSTANCE,
          useValue: mockMsalInstance
        }
      ]
    });
  });

  it('should create', () => {
    const service = TestBed.inject(MsalService);
    expect(service).toBeTruthy();
    expect(service.instance).toBe(mockMsalInstance);
  });
});

Package Metadata

/** Package version constant for version tracking and debugging */
const version: string;

Usage for Version Tracking:

import { version } from "@azure/msal-angular";

console.log(`Using @azure/msal-angular version: ${version}`);

// Include in error reports or debugging information
const debugInfo = {
  msalAngularVersion: version,
  userAgent: navigator.userAgent,
  timestamp: new Date().toISOString()
};