Átirányítások használata az MSAL Angularban

Ha átirányításokat használ az MSAL-lal, kötelező kezelni az átirányításokat a(z) MsalRedirectComponent vagy a(z) handleRedirectObservable használatával.

Vegye figyelembe, hogy az MSAL Angular és az Angular különálló összetevőinek használatához az alábbiakban konkrét útmutatást adunk.

  1. MsalRedirectComponent
  2. handleRedirectObservable Feliratkozás manuálisan
  3. Átirányítások önálló összetevőkkel

1. MsalRedirectComponent: Dedikált handleRedirectObservable összetevő

Note

Ez a megközelítés nem kompatibilis az Angular önálló összetevőivel. További útmutatásért tekintse meg a különálló összetevőkkel rendelkező átirányításokról szóló szakaszt.

Ez az átirányítások kezelésének ajánlott megközelítése:

  • @azure/msal-angular dedikált átirányítási összetevőt biztosít, amely importálható az alkalmazásba. Javasoljuk a MsalRedirectComponent importálását, valamint ennek bootstrapelését a AppComponent mellett az alkalmazásban, a app.module.ts platformon, mivel ez kezeli az összes átirányítást anélkül, hogy az összetevőknek manuálisan fel kellene iratkozniuk a handleRedirectObservable()-ra.
  • Azoknak az oldalaknak, amelyek átirányításokat követően műveleteket szeretnének végrehajtani (pl. felhasználói fiókkal kapcsolatos műveletek, a felhasználói felület módosításai stb.), fel kell iratkozniuk a inProgress$ observable-ra, a InteractionStatus.None értékre szűrve. Ez biztosítja, hogy a függvények végrehajtása során ne történjen interakció. Vegye figyelembe, hogy az utolsó / legutóbbi InteractionStatus is rendelkezésre áll a inProgress$ Observable-ra való előfizetéskor. Az interakciók ellenőrzéséről további információt az eseményekkel kapcsolatos dokumentációnkban talál.
  • Ha nem szeretné használni a MsalRedirectComponentparancsot, az átirányításokat saját magával handleRedirectObservable() kezelnie, az alábbi megközelítésben leírtak szerint.
  • Erre a megközelítésre példaként tekintse meg az Angular-modulok mintáját .

msal.redirect.component.ts

// This component is part of @azure/msal-angular and can be imported and bootstrapped
import { Component, OnInit } from "@angular/core";
import { MsalService } from "./msal.service.ts";

@Component({
  selector: 'app-redirect', // Selector to be added to index.html
  template: ''
})
export class MsalRedirectComponent implements OnInit {
  
  constructor(private authService: MsalService) { }
  
  ngOnInit(): void {    
      this.authService.handleRedirectObservable().subscribe();
  }
  
}

index.html

<body>
  <app-root></app-root>
  <app-redirect></app-redirect> <!-- Selector for additional bootstrapped component -->
</body>

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';

import { MatButtonModule } from '@angular/material/button';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatListModule } from '@angular/material/list';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { ProfileComponent } from './profile/profile.component';

import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import { IPublicClientApplication, PublicClientApplication, InteractionType, BrowserCacheLocation, LogLevel } from '@azure/msal-browser';
import { MsalGuard, MsalInterceptor, MsalBroadcastService, MsalInterceptorConfiguration, MsalModule, MsalService, MSAL_GUARD_CONFIG, MSAL_INSTANCE, MSAL_INTERCEPTOR_CONFIG, MsalGuardConfiguration, MsalRedirectComponent } from '@azure/msal-angular'; // Redirect component imported from msal-angular

export function loggerCallback(logLevel: LogLevel, message: string) {
  console.log(message);
}

export function MSALInstanceFactory(): IPublicClientApplication {
  return new PublicClientApplication({
    auth: {
      clientId: '00001111-aaaa-2222-bbbb-3333cccc4444',
      redirectUri: 'http://localhost:4200',
      postLogoutRedirectUri: 'http://localhost:4200'
    },
    cache: {
      cacheLocation: BrowserCacheLocation.LocalStorage,
    },
    system: {
      loggerOptions: {
        loggerCallback,
        logLevel: LogLevel.Info,
        piiLoggingEnabled: false
      }
    }
  });
}

export function MSALInterceptorConfigFactory(): MsalInterceptorConfiguration {
  const protectedResourceMap = new Map<string, Array<string>>();
  protectedResourceMap.set('https://graph.microsoft.com/v1.0/me', ['user.read']);

  return {
    interactionType: InteractionType.Redirect,
    protectedResourceMap
  };
}

export function MSALGuardConfigFactory(): MsalGuardConfiguration {
  return { interactionType: InteractionType.Redirect };
}

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    ProfileComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    AppRoutingModule,
    MatButtonModule,
    MatToolbarModule,
    MatListModule,
    HttpClientModule,
    MsalModule
  ],
  providers: [
    {
      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
  ],
  bootstrap: [AppComponent, MsalRedirectComponent] // Redirect component bootstrapped here
})
export class AppModule { }

app.component.ts

import { Component, OnInit, Inject, OnDestroy } from '@angular/core';
import { MsalBroadcastService, InteractionStatus } from '@azure/msal-angular';
import { Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent implements OnInit, OnDestroy {
  private readonly _destroying$ = new Subject<void>();

  constructor(
    private msalBroadcastService: MsalBroadcastService
  ) {}

  ngOnInit(): void {
    this.msalBroadcastService.inProgress$
      .pipe(
        filter((status: InteractionStatus) => status === InteractionStatus.None),
        takeUntil(this._destroying$)
      )
      .subscribe(() => {
        // Do user account/UI functions here
      })
  }

2. Manuális feliratkozás a(z) handleRedirectObservable szolgáltatásra

Ez nem az általunk javasolt megközelítés, de ha nem tudja beüzemelni a MsalRedirectComponent-t, az átirányításokat az alábbiak szerint a handleRedirectObservable használatával kell kezelnie:

  • handleRedirectObservable() minden olyan oldalra elő kell fizetnie, amelyre átirányítás történhet. Az MSAL Guard által védett lapokra nem kell előfizetni handleRedirectObservable(), mivel az átirányítások feldolgozása a Guardban történik.
  • A felhasználói fiókokhoz való hozzáférést, illetve a velük kapcsolatos bármilyen művelet végrehajtását nem szabad megtenni, amíg a(z) handleRedirectObservable() be nem fejeződik, mivel addig előfordulhat, hogy nem töltődik fel teljesen. Emellett, ha interaktív API-kat hívnak meg, miközben a(z) handleRedirectObservables() folyamatban van, az interaction_in_progress hibát eredményez. Az interakciók ellenőrzéséről további információt az eseményekről szóló dokumentumunkban, valamint a hibákról szóló dokumentumunkban talál a interaction_in_progress hibával kapcsolatos részletekért.
  • Erre a megközelítésre példákért tekintse meg az MSAL Angular-modulok mintáját .

Példa home.component.ts fájlra:

import { Component, OnInit } from '@angular/core';
import { MsalBroadcastService, MsalService } from '@azure/msal-angular';
import { AuthenticationResult } from '@azure/msal-browser';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {

  constructor(private authService: MsalService) { }

  ngOnInit(): void {
    this.authService.handleRedirectObservable().subscribe({
      next: (result: AuthenticationResult) => {
        // Perform actions related to user accounts here
      },
      error: (error) => console.log(error)
    });
  }

}

handleRedirectObservable beállítások

handleRedirectObservable a következő tulajdonságokkal rendelkező opcionális HandleRedirectPromiseOptions objektumot fogad el:

Property Típus Description
hash string Opcionális hash az aktuális URL-hash helyett történő feldolgozáshoz.
navigateToLoginRequestUrl boolean Az, hogy az átirányítás feldolgozása után átirányítson-e az eredeti kérés URL-címére. Alapértelmezett érték: true. Állítsa be, false ha saját maga szeretné kezelni a navigációt.

Gyakorlati példa:

// Basic usage - processes redirect and navigates to original URL
this.authService.handleRedirectObservable().subscribe();

// Disable automatic navigation after redirect
this.authService.handleRedirectObservable({ navigateToLoginRequestUrl: false }).subscribe({
  next: (result: AuthenticationResult) => {
    if (result) {
      // Handle navigation yourself
      this.router.navigate(['/home']);
    }
  }
});

// Process a specific hash
this.authService.handleRedirectObservable({ hash: '#code=...' }).subscribe();

Note

A hashkarakterlánc közvetlen átadása a(z) handleRedirectObservable(hash) számára elavult. Használja inkább a beállításobjektumot: handleRedirectObservable({ hash: "#..." }).

3. Átirányítások önálló összetevőkkel

Mivel sok, önálló komponenseket használó Angular-alkalmazás nem tudja bootstrapelni a MsalRedirectComponent-t, a(z) handleRedirectObservable elemre közvetlenül kell feliratkozni. Javasoljuk, hogy iratkozzon fel rá a app.component.ts fájlban.

  • Az alkalmazás architektúrájától függően előfordulhat, hogy az alkalmazás más részein is fel kell iratkoznia a(z) handleRedirectObservable() elemre.
  • A folyamatban lévő interakciók ellenőrzése továbbra is érvényes. Az interakciók ellenőrzéséről további információt az eseményekről szóló dokumentumunkban talál.
  • Erre a megközelítésre példákat az Angular önálló mintájában talál.

Példa fájlra app.component.ts :

import { Component, OnInit, Inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { MsalService, MsalBroadcastService, MSAL_GUARD_CONFIG, MsalGuardConfiguration } from '@azure/msal-angular';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
    standalone: true,
    imports: [CommonModule, RouterModule]
})
export class AppComponent implements OnInit {

  constructor(
    @Inject(MSAL_GUARD_CONFIG) private msalGuardConfig: MsalGuardConfiguration,
    private authService: MsalService,
    private msalBroadcastService: MsalBroadcastService
  ) {}

  ngOnInit(): void {
    this.authService.handleRedirectObservable().subscribe();
  }
}