MSAL Angular'da yeniden yönlendirmeleri kullanma

MSAL ile yeniden yönlendirmeler kullanılırken, yeniden yönlendirmeleri MsalRedirectComponent veya handleRedirectObservable ile işlemek zorunludur.

MSAL Angular'ı aşağıdaki Angular tek başına bileşenleriyle kullanmak için belirli yönergeler eklendiğini unutmayın.

  1. MsalRedirectComponent
  2. El ile abone handleRedirectObservable
  3. Tek başına bileşenlerle yeniden yönlendirmeler

1. MsalRedirectComponent: Ayrılmış handleRedirectObservable bir bileşen

Note

Bu yaklaşım, Angular tek başına bileşenleriyle uyumlu değildir. Daha fazla kılavuz için aşağıdaki tek başına bileşenlerle yeniden yönlendirmeler bölümüne bakın.

Bu, yeniden yönlendirmeleri işlemek için önerilen yaklaşımımızdır:

  • @azure/msal-angular uygulamanıza aktarabileceğiniz ayrılmış bir yeniden yönlendirme bileşeni sağlar. Tüm yeniden yönlendirmeleri, bileşenlerinizin handleRedirectObservable()’e manuel olarak abone olmasını gerektirmeden işleyeceği için, MsalRedirectComponent öğesini içe aktarmanızı ve bunu app.module.ts üzerindeki uygulamanızda AppComponent ile birlikte başlatmanızı öneririz.
  • Yönlendirmelerin ardından işlevler gerçekleştirmek isteyen sayfalar (ör. kullanıcı hesabı işlevleri, kullanıcı arabirimi değişiklikleri vb.) InteractionStatus.None için filtreleme yaparak inProgress$ observable’ına abone olmalıdır. Bu, işlevleri gerçekleştirirken devam eden hiçbir etkileşim olmamasını sağlar. inProgress$ gözlemlenebilirine abone olunduğunda, son / en güncel InteractionStatus değerinin de mevcut olacağını unutmayın. Etkileşimleri denetleme hakkında daha fazla bilgi için lütfen olaylarla ilgili belgelerimize bakın.
  • MsalRedirectComponent kullanmak istemiyorsanız, aşağıda açıklanan yaklaşıma göre yeniden yönlendirmeleri handleRedirectObservable() kendiniz yönetmeniz gerekir.
  • Bu yaklaşımın bir örneği için Angular modülleri örneğimize bakın.

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. Elle handleRedirectObservable abone olma

Bu, önerdiğimiz yaklaşım değildir; ancak MsalRedirectComponent önyükleyemiyorsanız, yönlendirmeleri aşağıdaki gibi handleRedirectObservable kullanarak işlemeniz gerekir:

  • handleRedirectObservable() yeniden yönlendirmenin gerçekleşebileceği her sayfada abone olunmalıdır. MSAL Guard tarafından korunan sayfaların, yeniden yönlendirmeler Guard'da işlendiği için handleRedirectObservable()öğesine abone olması gerekmez.
  • handleRedirectObservable() tamamlanana kadar kullanıcı hesaplarına erişilmemeli veya bunlarla ilgili herhangi bir işlem yapılmamalıdır; çünkü bu süre içinde hesaplar henüz tam olarak doldurulmamış olabilir. Ayrıca, handleRedirectObservables() devam ederken etkileşimli API'ler çağrılırsa, bu interaction_in_progress hatasına neden olur. Etkileşimleri denetleme hakkında daha fazla bilgi için olaylarla ilgili belgemize ve hatayla ilgili ayrıntılar için hatalarla ilgili interaction_in_progress belgemize bakın.
  • Bu yaklaşımın örnekleri için MSAL Angular modülleri örneğimize bakın.

home.component.ts dosyası örneği:

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 Seçenekler

handleRedirectObservable aşağıdaki özelliklere sahip isteğe bağlı HandleRedirectPromiseOptions bir nesneyi kabul eder:

Mülkiyet Türü Description
hash string Geçerli URL karması yerine işlenmek üzere isteğe bağlı karma.
navigateToLoginRequestUrl boolean Yeniden yönlendirme işlendikten sonra özgün istek URL'sine gidilip gidilmeyeceği. Varsayılan değer true’dır. Gezinmeyi kendiniz yönetmek istiyorsanız false olarak ayarlayın.

Örnek kullanım:

// 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

Bir hash dizesinin doğrudan handleRedirectObservable(hash) öğesine geçirilmesi kullanımdan kaldırılmıştır. Bunun yerine options nesnesini kullanın: handleRedirectObservable({ hash: "#..." }).

3. Bağımsız bileşenlerle yeniden yönlendirmeler

Tek başına bileşenler kullanan birçok Angular uygulaması MsalRedirectComponent bileşenini önyükleyemediğinden, handleRedirectObservable öğesine doğrudan abone olunmalıdır. Önerimiz dosyada app.component.ts abone olmaktır.

  • Uygulama mimarinize bağlı olarak, diğer alanlarda da handleRedirectObservable() öğesine abone olmanız gerekebilir.
  • Devam eden etkileşimleri denetleme hala geçerlidir. Etkileşimleri denetleme hakkında daha fazla bilgi için lütfen olaylarla ilgili belgemize bakın.
  • Bu yaklaşımın örnekleri için angular tek başına örneğimize bakın.

Dosya örneği 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();
  }
}