Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
При использовании перенаправлений с MSAL обязательно обрабатывать перенаправления с помощью MsalRedirectComponent или handleRedirectObservable.
Обратите внимание, что ниже добавлены конкретные рекомендации по использованию MSAL Angular с автономными компонентами Angular.
MsalRedirectComponent-
Подписка на
handleRedirectObservableвручную - Перенаправления с помощью автономных компонентов
1. MsalRedirectComponent: выделенный handleRedirectObservable компонент
Note
Этот подход несовместим с автономными компонентами Angular. Дополнительные рекомендации см. в разделе о перенаправлении с автономными компонентами ниже .
Это рекомендуемый подход для обработки перенаправлений:
-
@azure/msal-angularпредоставляет выделенный компонент перенаправления, который можно импортировать в приложение. Мы рекомендуем импортироватьMsalRedirectComponentи инициализировать его вместе сAppComponentв вашем приложении наapp.module.ts, так как это позволит обрабатывать все перенаправления без необходимости вашим компонентам вручную подписываться наhandleRedirectObservable(). - Страницы, которые должны выполнять действия после перенаправлений (например, действия, связанные с учетной записью пользователя, изменениями интерфейса и т. д.), должны подписаться на observable
inProgress$с фильтрацией поInteractionStatus.None. Это обеспечит отсутствие взаимодействия при выполнении функций. Обратите внимание, что последнее / самое недавнее значениеInteractionStatusтакже будет доступно при подписке на наблюдаемый объектinProgress$. Дополнительные сведения о проверке взаимодействия см. в нашей документации по событиям . - Если вы не хотите использовать
MsalRedirectComponent, вы должны самостоятельно обрабатывать перенаправления с помощьюhandleRedirectObservable(), как описано в подходе ниже. - Пример этого подхода см. в нашем примере модулей Angular .
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. Подписка на handleRedirectObservable вручную
Это не рекомендуемый нами подход, но если вам не удается выполнить начальную загрузку MsalRedirectComponent, вы должны обрабатывать перенаправления с помощью handleRedirectObservable следующим образом:
-
handleRedirectObservable()необходимо подписаться на каждую страницу, на которую может возникнуть перенаправление. Страницам, защищённым с помощью MSAL Guard, не нужно подписываться наhandleRedirectObservable(), так как перенаправления обрабатываются в Guard. - Не следует получать доступ к учетным записям пользователей или выполнять какие-либо действия, связанные с ними, до завершения
handleRedirectObservable(), так как до этого момента данные могут быть заполнены не полностью. Кроме того, если интерактивные API вызываются, пока выполняетсяhandleRedirectObservables(), возникнет ошибкаinteraction_in_progress. Дополнительные сведения о проверке взаимодействий см. в нашем документе о событиях, а подробную информацию об ошибкеinteraction_in_progress— в нашем документе об ошибках. - Примеры этого подхода см. в нашем примере модулей MSAL Angular .
Пример файла home.component.ts:
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 варианты
handleRedirectObservable принимает необязательный HandleRedirectPromiseOptions объект со следующими свойствами:
| Property | Type | Description |
|---|---|---|
hash |
string |
Необязательный хэш, который следует обработать вместо текущего хэша URL. |
navigateToLoginRequestUrl |
boolean |
Следует ли переходить к исходному URL-адресу запроса после обработки перенаправления. По умолчанию — true. Установите значение false, если хотите самостоятельно обрабатывать навигацию. |
Пример использования:
// 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
Непосредственная передача хэш-строки в handleRedirectObservable(hash) не рекомендуется. Используйте объект options вместо: handleRedirectObservable({ hash: "#..." })
3. Перенаправление с помощью автономных компонентов
Поскольку многие приложения Angular, использующие автономные компоненты, не могут выполнить bootstrap для MsalRedirectComponent, необходимо подписываться непосредственно на handleRedirectObservable. Наша рекомендация заключается в том, чтобы подписаться на него в app.component.ts файле.
- В зависимости от архитектуры вашего приложения вам также может потребоваться подписаться на
handleRedirectObservable()в других частях приложения. - Проверка хода выполнения взаимодействия по-прежнему применяется, ознакомьтесь с нашим документом о событиях , чтобы получить дополнительные сведения о проверке взаимодействия.
- Примеры этого подхода см. в нашем автономном примере Angular .
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();
}
}