Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Przed rozpoczęciem tutaj upewnij się, że rozumiesz, jak zainicjować obiekt aplikacji.
@azure/msal-angular używa systemu zdarzeń udostępnianego przez @azure/msal-browser, który emituje zdarzenia związane z uwierzytelnianiem i biblioteką MSAL oraz może być używany do aktualizowania interfejsu użytkownika, wyświetlania komunikatów o błędach itd.
Korzystanie ze zdarzeń w aplikacji
Zdarzenia w @azure/msal-angular są obsługiwane przez MsalBroadcastService i są dostępne po zasubskrybowaniu obiektu obserwowalnego msalSubject$ w MsalBroadcastService.
Oto przykład sposobu korzystania z emitowanych zdarzeń w aplikacji:
import { MsalBroadcastService } from '@azure/msal-angular';
import { EventMessage, EventType } from '@azure/msal-browser';
export class AppComponent implements OnInit, OnDestroy {
private readonly _destroying$ = new Subject<void>();
constructor(
//...
private msalBroadcastService: MsalBroadcastService
) {}
ngOnInit(): void {
this.msalBroadcastService.msalSubject$
.pipe(
// Optional filtering of events.
filter((msg: EventMessage) => msg.eventType === EventType.LOGIN_SUCCESS),
takeUntil(this._destroying$)
)
.subscribe((result: EventMessage) => {
// Do something with the result
});
}
ngOnDestroy(): void {
this._destroying$.next(null);
this._destroying$.complete();
}
}
Pamiętaj, że może być konieczne rzutowanie elementu result.payload jako określonego typu, aby zapobiec błędom kompilacji. Typ ładunku będzie zależeć od zdarzenia i można go znaleźć w naszej dokumentacji tutaj.
ngOnInit(): void {
this.msalBroadcastService.msalSubject$
.pipe(
filter((msg: EventMessage) => msg.eventType === EventType.LOGIN_SUCCESS),
)
.subscribe((result: EventMessage) => {
// Casting payload as AuthenticationResult to access account
const payload = result.payload as AuthenticationResult;
this.authService.instance.setActiveAccount(payload.account);
});
}
Pełny przykład użycia zdarzeń można znaleźć w naszym przykładzie tutaj.
Tabela zdarzeń
Aby uzyskać więcej informacji o EventMessage obiekcie, w tym pełną tabelę zdarzeń, które są obecnie emitowane przez @azure/msal-browser (w tym opisy i powiązane ładunki), zapoznaj się z dokumentacją tutaj.
Obsługa błędów za pomocą zdarzeń
Ponieważ parametr EventError in EventMessage jest zdefiniowany jako AuthError | Error | null, należy zweryfikować błąd jako prawidłowy typ przed uzyskaniem dostępu do określonych właściwości.
Zapoznaj się z poniższym przykładem tego, jak można zrzutować błąd do AuthError, aby uniknąć błędów TypeScript:
import { MsalBroadcastService } from '@azure/msal-angular';
import { EventMessage, EventType } from '@azure/msal-browser';
export class AppComponent implements OnInit, OnDestroy {
private readonly _destroying$ = new Subject<void>();
constructor(
//...
private msalBroadcastService: MsalBroadcastService
) {}
ngOnInit(): void {
this.msalBroadcastService.msalSubject$
.pipe(
// Optional filtering of events
filter((msg: EventMessage) => msg.eventType === EventType.LOGIN_FAILURE),
takeUntil(this._destroying$)
)
.subscribe((result: EventMessage) => {
if (result.error instanceof AuthError) {
// Do something with the error
}
});
}
ngOnDestroy(): void {
this._destroying$.next(null);
this._destroying$.complete();
}
}
Przykład obsługi błędów można również znaleźć w naszym przykładzie MSAL Angular B2C.
Synchronizowanie zalogowanego stanu na kartach i oknach
Jeśli chcesz zaktualizować interfejs użytkownika, gdy użytkownik loguje się lub wylogowuje z aplikacji w innej karcie lub oknie, możesz zasubskrybować zdarzenia ACCOUNT_ADDED i ACCOUNT_REMOVED. Ładunek będzie obiektem AccountInfo , który został dodany lub usunięty.
import { MsalService, MsalBroadcastService } from '@azure/msal-angular';
import { EventMessage, EventType } from '@azure/msal-browser';
export class AppComponent implements OnInit, OnDestroy {
private readonly _destroying$ = new Subject<void>();
constructor(
//...
private authService: MsalService,
private msalBroadcastService: MsalBroadcastService
) {}
ngOnInit(): void {
this.authService.instance.enableAccountStorageEvents(); // Register the storage listener that will be emitting the events
this.msalBroadcastService.msalSubject$
.pipe(
// Optional filtering of events
filter((msg: EventMessage) => msg.eventType === EventType.ACCOUNT_ADDED || msg.eventType === EventType.ACCOUNT_REMOVED),
takeUntil(this._destroying$)
)
.subscribe((result: EventMessage) => {
if (this.authService.msalInstance.getAllAccounts().length === 0) {
// Account logged out in a different tab, redirect to homepage
window.location.pathname = "/";
} else {
// Update UI to show user is signed in. result.payload contains the account that was logged in
}
});
}
ngOnDestroy(): void {
this._destroying$.next(null);
this._destroying$.complete();
}
}
Pełny przykład można również znaleźć w naszych przykładach.
Obserwowalny element inProgress$
Obiekt Observable inProgress$ jest również obsługiwany przez element MsalBroadcastService i należy go subskrybować, gdy aplikacja musi znać stan interakcji, w szczególności aby sprawdzić, czy interakcje zostały zakończone. Zalecamy sprawdzenie, czy stan interakcji to InteractionStatus.None, przed wywołaniem funkcji związanych z kontami użytkowników.
Należy pamiętać, że ostatnia / najnowsza wartość InteractionStatus będzie również dostępna podczas subskrybowania obserwowalnego obiektu inProgress$.
Zapoznaj się z poniższym przykładem użycia. Pełny przykład można również znaleźć w naszych przykładach. Pełną listę stanów interakcji można znaleźć tutaj.
import { Component, OnInit, Inject, OnDestroy } from '@angular/core';
import { MsalBroadcastService} from '@azure/msal-angular';
import { InteractionStatus } from '@azure/msal-browser';
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(
// Filtering for all interactions to be completed
filter((status: InteractionStatus) => status === InteractionStatus.None),
takeUntil(this._destroying$)
)
.subscribe(() => {
// Do something related to user accounts or UI here
})
}
ngOnDestroy(): void {
this._destroying$.next(null);
this._destroying$.complete();
}
}
Konfiguracje opcjonalne MsalBroadcastService
MsalBroadcastService można opcjonalnie skonfigurować tak, aby odtwarzał wcześniejsze zdarzenia w momencie subskrypcji. Domyślnie dostępne są zdarzenia emitowane po zasubskrybowaniu elementu MsalBroadcastService. Mogą wystąpić przypadki, w których potrzebne są zdarzenia sprzed subskrypcji. Podając konfigurację parametru MsalBroadcastServiceeventsToReplay i ustawiając parametr na liczbę, ta liczba przeszłych zdarzeń będzie dostępna w ramach subskrypcji.
Aby uzyskać więcej informacji na temat odtwarzania zdarzeń, zobacz dokumentację RxJS w temacie ReplaySubjects tutaj.
Element MsalBroadcastService można skonfigurować w pliku app.module.ts w następujący sposób:
// app.module.ts
import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { AppComponent } from './app.component';
import { MsalModule, MsalService, MsalGuard, MsalInterceptor, MsalBroadcastService, MsalRedirectComponent, MSAL_BROADCAST_CONFIG } from "@azure/msal-angular"; // Import MsalBroadcastService and MSAL_BROADCAST_CONFIG here
import { PublicClientApplication, InteractionType, BrowserCacheLocation } from "@azure/msal-browser";
@NgModule({
imports: [
MsalModule.forRoot( new PublicClientApplication({ // MSAL Configuration
auth: {
clientId: "clientid",
authority: "https://login.microsoftonline.com/common/",
redirectUri: "http://localhost:4200/",
postLogoutRedirectUri: "http://localhost:4200/",
navigateToLoginRequestUrl: true
},
cache: {
cacheLocation : BrowserCacheLocation.LocalStorage,
},
system: {
loggerOptions: {
loggerCallback: () => {},
piiLoggingEnabled: false
}
}
}), {
interactionType: InteractionType.Popup, // MSAL Guard Configuration
authRequest: {
scopes: ['user.read']
},
loginFailedRoute: "/login-failed"
}, {
interactionType: InteractionType.Redirect, // MSAL Interceptor Configuration
protectedResourceMap
})
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: MsalInterceptor,
multi: true
},
{
provide: MSAL_BROADCAST_CONFIG, // Add configuration to providers here
useValue: {
eventsToReplay: 2 // Set how many events you want to replay when subscribing
}
},
MsalGuard,
MsalBroadcastService // Ensure the MsalBroadcastService is provided
],
bootstrap: [AppComponent, MsalRedirectComponent]
})
export class AppModule {}