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

authentication-service.mddocs/

Authentication Service

Core authentication functionality providing login, logout, token acquisition, and user account management through Angular services and reactive patterns.

Capabilities

MsalService

Main authentication service that wraps MSAL Browser functionality with Angular-specific implementations and Observable patterns.

/**
 * Main authentication service for MSAL Angular integration
 * Implements IMsalService interface and provides Angular-specific authentication operations
 */
class MsalService implements IMsalService {
  /** The underlying MSAL browser instance */
  instance: IPublicClientApplication;
  
  /** Initializes the MSAL instance */
  initialize(): Observable<void>;
  
  /** Handles redirect responses from authentication flows */
  handleRedirectObservable(hash?: string): Observable<AuthenticationResult>;
  
  /** Initiates login using popup window */
  loginPopup(request?: PopupRequest): Observable<AuthenticationResult>;
  
  /** Initiates login using redirect flow */
  loginRedirect(request?: RedirectRequest): Observable<void>;
  
  /** Acquires tokens silently using cached credentials */
  acquireTokenSilent(silentRequest: SilentRequest): Observable<AuthenticationResult>;
  
  /** Acquires tokens using popup window */
  acquireTokenPopup(request: PopupRequest): Observable<AuthenticationResult>;
  
  /** Acquires tokens using redirect flow */
  acquireTokenRedirect(request: RedirectRequest): Observable<void>;
  
  /** Initiates SSO silent authentication */
  ssoSilent(request: SsoSilentRequest): Observable<AuthenticationResult>;
  
  /** Logs out user using redirect flow */
  logoutRedirect(logoutRequest?: EndSessionRequest): Observable<void>;
  
  /** Logs out user using popup window */
  logoutPopup(logoutRequest?: EndSessionPopupRequest): Observable<void>;
  
  /** @deprecated Use logoutRedirect or logoutPopup instead */
  logout(logoutRequest?: EndSessionRequest): Observable<void>;
  
  /** Gets the current logger instance */
  getLogger(): Logger;
  
  /** Sets a new logger instance */
  setLogger(logger: Logger): void;
}

Usage Examples:

import { Component, OnInit, Inject } from "@angular/core";
import { MsalService } from "@azure/msal-angular";
import { AuthenticationResult, PopupRequest } from "@azure/msal-browser";

@Component({
  selector: 'app-login',
  template: `
    <button (click)="login()" *ngIf="!isLoggedIn">Login</button>
    <button (click)="logout()" *ngIf="isLoggedIn">Logout</button>
    <div *ngIf="isLoggedIn">Welcome, {{ username }}!</div>
  `
})
export class LoginComponent implements OnInit {
  isLoggedIn = false;
  username = '';

  constructor(private authService: MsalService) {}

  ngOnInit() {
    // Check if user is already logged in
    this.isLoggedIn = this.authService.instance.getAllAccounts().length > 0;
    if (this.isLoggedIn) {
      this.username = this.authService.instance.getAllAccounts()[0].username;
    }
  }

  login() {
    const loginRequest: PopupRequest = {
      scopes: ["user.read", "openid", "profile"]
    };

    this.authService.loginPopup(loginRequest).subscribe({
      next: (result: AuthenticationResult) => {
        console.log('Login successful', result);
        this.isLoggedIn = true;
        this.username = result.account?.username || '';
      },
      error: (error) => console.error('Login failed', error)
    });
  }

  logout() {
    this.authService.logoutPopup({
      postLogoutRedirectUri: window.location.origin
    }).subscribe({
      next: () => {
        this.isLoggedIn = false;
        this.username = '';
      }
    });
  }
}

IMsalService Interface

Interface defining the contract for MsalService, useful for testing and dependency injection.

/**
 * Interface defining the contract for MsalService
 * Provides type safety and enables easy mocking for testing
 */
interface IMsalService {
  instance: IPublicClientApplication;
  
  initialize(): Observable<void>;
  handleRedirectObservable(): Observable<AuthenticationResult | null>;
  loginPopup(request?: PopupRequest): Observable<AuthenticationResult>;
  loginRedirect(request?: RedirectRequest): Observable<void>;
  acquireTokenSilent(silentRequest: SilentRequest): Observable<AuthenticationResult>;
  acquireTokenPopup(request: PopupRequest): Observable<AuthenticationResult>;
  acquireTokenRedirect(request: RedirectRequest): Observable<void>;
  ssoSilent(request: SsoSilentRequest): Observable<AuthenticationResult>;
  logoutRedirect(logoutRequest?: EndSessionRequest): Observable<void>;
  logoutPopup(logoutRequest?: EndSessionRequest): Observable<void>;
  logout(logoutRequest?: EndSessionRequest): Observable<void>;
  getLogger(): Logger;
  setLogger(logger: Logger): void;
}

Token Acquisition Examples

import { Component } from "@angular/core";
import { MsalService } from "@azure/msal-angular";
import { SilentRequest, PopupRequest } from "@azure/msal-browser";

@Component({
  selector: 'app-api-call',
  template: '<button (click)="callApi()">Call Protected API</button>'
})
export class ApiCallComponent {
  constructor(private authService: MsalService) {}

  async callApi() {
    const account = this.authService.instance.getAllAccounts()[0];
    
    // Try silent token acquisition first
    const silentRequest: SilentRequest = {
      scopes: ["https://graph.microsoft.com/.default"],
      account: account
    };

    try {
      const result = await this.authService.acquireTokenSilent(silentRequest).toPromise();
      console.log('Token acquired silently', result?.accessToken);
      
      // Use token for API call
      this.makeApiCall(result?.accessToken);
    } catch (error) {
      console.log('Silent token acquisition failed, falling back to popup');
      
      // Fall back to popup if silent acquisition fails
      const popupRequest: PopupRequest = {
        scopes: ["https://graph.microsoft.com/.default"]
      };
      
      this.authService.acquireTokenPopup(popupRequest).subscribe({
        next: (result) => {
          console.log('Token acquired via popup', result.accessToken);
          this.makeApiCall(result.accessToken);
        },
        error: (error) => console.error('Token acquisition failed', error)
      });
    }
  }

  private makeApiCall(token: string) {
    // Make HTTP request with token
    // This would typically be handled by MsalInterceptor automatically
  }
}

Redirect Handling

import { Component, OnInit } from "@angular/core";
import { MsalService } from "@azure/msal-angular";

@Component({
  selector: 'app-root',
  template: '<router-outlet></router-outlet>'
})
export class AppComponent implements OnInit {
  constructor(private authService: MsalService) {}

  ngOnInit() {
    // Handle redirect responses when app loads
    this.authService.handleRedirectObservable().subscribe({
      next: (result) => {
        if (result) {
          console.log('Redirect login successful', result);
          // Handle successful authentication
        }
      },
      error: (error) => {
        console.error('Redirect login failed', error);
        // Handle authentication error
      }
    });
  }
}