Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
MSAL untuk Angular dapat dikonfigurasi dengan berbagai cara. Artikel ini menjelaskan opsi konfigurasi yang tersedia untuk MSAL Angular, termasuk pendekatan statis dan dinamis, dan menyediakan sampel kode untuk mengintegrasikan autentikasi ke dalam aplikasi Anda. Gunakan panduan ini untuk memilih metode konfigurasi yang paling sesuai dengan persyaratan aplikasi Anda dan memberikan pengalaman masuk yang mulus bagi pengguna Anda.
Opsi Konfigurasi
@azure/msal-angular menerima tiga objek konfigurasi:
-
Konfigurasi: Ini adalah objek konfigurasi yang sama yang digunakan untuk pustaka inti
@azure/msal-browser. Semua opsi konfigurasi dapat ditemukan di sini. -
MsalGuardConfiguration: Serangkaian opsi khusus untuk penjaga Angular. -
MsalInterceptorConfiguration: Sekumpulan opsi khusus untuk pencegat Angular.
Konfigurasi khusus Angular
-
interactionTypeharus ditentukan padaMsalGuardConfigurationdanMsalInterceptorConfiguration, dan dapat disetel kePopupatauRedirect. - Objek
protectedResourceMappadaMsalInterceptorConfigurationdigunakan untuk melindungi rute. - Objek opsional
authRequestdapat ditentukan padaMsalGuardConfigurationdanMsalInterceptorConfigurationuntuk mengatur opsi tambahan. - String opsional
loginFailedRoutedapat diatur padaMsalGuardConfiguration. Msal Guard akan mengarahkan ke rute ini jika proses masuk diperlukan tetapi gagal.
Silakan lihat dokumen MsalInterceptor dan MsalGuard kami untuk detail selengkapnya tentang konfigurasi, penggunaan, dan perbedaan MSAL Angular v1.
Konfigurasi untuk pengalihan
Sebaiknya impor MsalRedirectComponent dan lakukan bootstrap dengan AppComponent jika Anda ingin menggunakan pengalihan. Silakan lihat dokumentasi pengalihan untuk detail selengkapnya.
Catatan: Pada MSAL v3.x, inisialisasi objek aplikasi sekarang diperlukan. Lihat panduan peningkatan v2-v3 untuk detail selengkapnya. Untuk detail tentang peningkatan ke MSAL Angular v5, lihat panduan peningkatan v4-v5.
MsalModule.forRoot
Kelas MsalModule berisi metode statis yang dapat dipanggil dalam file Anda 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 } from "@azure/msal-angular";
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/",
},
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,
},
MsalGuard,
],
bootstrap: [AppComponent, MsalRedirectComponent],
})
export class AppModule {}
Penyedia Pabrik
Anda juga dapat menyediakan opsi konfigurasi melalui penyedia pabrik.
import { MsalModule, MsalService, MsalInterceptor, MsalInterceptorConfiguration, MsalGuard, MsalGuardConfiguration, MsalBroadcastService, MsalRedirectComponent } from "@azure/msal-angular";
import { IPublicClientApplication, PublicClientApplication, InteractionType, BrowserCacheLocation } from "@azure/msal-browser";
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,
},
});
}
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,
authRequest: {
scopes: ["user.read"],
},
loginFailedRoute: "./login-failed",
};
}
@NgModule({
imports: [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,
},
MsalGuard,
MsalBroadcastService,
MsalService,
],
bootstrap: [AppComponent, MsalRedirectComponent],
})
export class AppModule {}
platformBrowserDynamic
Jika Anda perlu mengonfigurasi MSAL Angular secara dinamis (misalnya berdasarkan nilai yang dikembalikan dari API), Anda dapat menggunakan platformBrowserDynamic.
platformBrowserDynamic adalah factory platform yang digunakan untuk melakukan bootstrap pada aplikasi dan dapat menerima opsi konfigurasi.
platformBrowserDynamic harus sudah ada ketika aplikasi Angular disiapkan.
Berikut ini adalah contoh cara mengonfigurasi @azure/msal-angular secara dinamis dengan platformBrowserDynamic dan file json:
app.module.ts
import { MsalModule, MsalInterceptor, MsalService } from "@azure/msal-angular";
@NgModule({
imports: [MsalModule],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: MsalInterceptor,
multi: true,
},
MsalService,
],
bootstrap: [AppComponent],
})
export class AppModule {}
main.ts
import { enableProdMode } from "@angular/core";
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
import { AppModule } from "./app/app.module";
import { environment } from "./environments/environment";
import { MSAL_INSTANCE, MSAL_GUARD_CONFIG, MSAL_INTERCEPTOR_CONFIG } from "@azure/msal-angular";
import { PublicClientApplication, Configuration } from "@azure/msal-browser";
if (environment.production) {
enableProdMode();
}
function loggerCallback(logLevel: LogLevel, message: string) {
console.log("MSAL Angular: ", message);
}
fetch("/assets/configuration.json")
.then((response) => response.json())
.then((json) => {
platformBrowserDynamic([
{
provide: MSAL_INSTANCE,
useValue: new PublicClientApplication({
auth: json.msal.auth,
cache: json.msal.cache,
system: {
loggerOptions: {
loggerCallback,
logLevel: LogLevel.Info,
piiLoggingEnabled: false,
},
},
}),
},
{
provide: MSAL_GUARD_CONFIG,
useValue: {
interactionType: json.guard.interactionType,
authRequest: json.guard.authRequest,
loginFailedRoute: json.guard.loginFailedRoute,
} as MsalGuardConfiguration,
},
{
provide: MSAL_INTERCEPTOR_CONFIG,
useValue: {
interactionType: json.interceptor.interactionType,
protectedResourceMap: new Map(json.interceptor.protectedResourceMap),
} as MsalInterceptorConfiguration,
},
])
.bootstrapModule(AppModule)
.catch((err) => console.error(err));
});
src/assets/configuration.json
{
"msal": {
"auth": {
"clientId": "clientid",
"authority": "https://login.microsoftonline.com/common/",
"redirectUri": "http://localhost:4200/",
"postLogoutRedirectUri": "http://localhost:4200/",
"navigateToLoginRequestUrl": true
},
"cache": {
"cacheLocation": "localStorage",
"storeAuthStateInCookie": true
}
},
"guard": {
"interactionType": "redirect",
"authRequest": {
"scopes": ["user.read"]
},
"loginFailedRoute": "/login-failed"
},
"interceptor": {
"interactionType": "redirect",
"protectedResourceMap": [["https://graph.microsoft.com/v1.0/me", ["user.read"]]]
}
}
Konfigurasi dinamis menggunakan provider factory dan APP_INITIALIZER
Untuk mengonfigurasi MSAL Angular secara dinamis, Anda dapat menggunakan Factory Provider dengan APP_INITIALIZER.
src/app/config.service.ts
import { Injectable } from "@angular/core";
import { HttpClient, HttpBackend } from "@angular/common/http";
import { map } from "rxjs/operators";
@Injectable({
providedIn: "root",
})
export class ConfigService {
private settings: any;
private http: HttpClient;
constructor(private readonly httpHandler: HttpBackend) {
this.http = new HttpClient(httpHandler);
}
init(endpoint: string): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
this.http
.get(endpoint)
.pipe(map((result) => result))
.subscribe(
(value) => {
this.settings = value;
resolve(true);
},
(error) => {
reject(error);
}
);
});
}
getSettings(key?: string | Array<string>): any {
if (!key || (Array.isArray(key) && !key[0])) {
return this.settings;
}
if (!Array.isArray(key)) {
key = key.split(".");
}
let result = key.reduce((account: any, current: string) => account && account[current], this.settings);
return result;
}
}
src/app/msal-config-dynamic.module.ts
import { InjectionToken, NgModule, APP_INITIALIZER } from "@angular/core";
import { IPublicClientApplication, PublicClientApplication, LogLevel } from "@azure/msal-browser";
import { MsalGuard, MsalInterceptor, MsalBroadcastService, MsalInterceptorConfiguration, MsalModule, MsalService, MSAL_GUARD_CONFIG, MSAL_INSTANCE, MSAL_INTERCEPTOR_CONFIG, MsalGuardConfiguration } from "@azure/msal-angular";
import { HTTP_INTERCEPTORS } from "@angular/common/http";
import { ConfigService } from "./config.service";
const AUTH_CONFIG_URL_TOKEN = new InjectionToken<string>("AUTH_CONFIG_URL");
export function initializerFactory(env: ConfigService, configUrl: string): any {
const promise = env.init(configUrl).then((value) => {
console.log("finished getting configurations dynamically.");
});
return () => promise;
}
export function loggerCallback(logLevel: LogLevel, message: string) {
console.log(message);
}
export function MSALInstanceFactory(config: ConfigService): IPublicClientApplication {
return new PublicClientApplication({
auth: config.getSettings("msal").auth,
cache: config.getSettings("msal").cache,
system: {
loggerOptions: {
loggerCallback,
logLevel: LogLevel.Info,
piiLoggingEnabled: false,
},
},
});
}
export function MSALInterceptorConfigFactory(config: ConfigService): MsalInterceptorConfiguration {
const protectedResourceMap = new Map<string, Array<string>>(config.getSettings("interceptor").protectedResourceMap);
return {
interactionType: config.getSettings("interceptor").interactionType,
protectedResourceMap,
};
}
export function MSALGuardConfigFactory(config: ConfigService): MsalGuardConfiguration {
return {
interactionType: config.getSettings("guard").interactionType,
authRequest: config.getSettings("guard").authRequest,
loginFailedRoute: config.getSettings("guard").loginFailedRoute,
};
}
@NgModule({
providers: [],
imports: [MsalModule],
})
export class MsalConfigDynamicModule {
static forRoot(configFile: string) {
return {
ngModule: MsalConfigDynamicModule,
providers: [
ConfigService,
{ provide: AUTH_CONFIG_URL_TOKEN, useValue: configFile },
{ provide: APP_INITIALIZER, useFactory: initializerFactory, deps: [ConfigService, AUTH_CONFIG_URL_TOKEN], multi: true },
{
provide: MSAL_INSTANCE,
useFactory: MSALInstanceFactory,
deps: [ConfigService],
},
{
provide: MSAL_GUARD_CONFIG,
useFactory: MSALGuardConfigFactory,
deps: [ConfigService],
},
{
provide: MSAL_INTERCEPTOR_CONFIG,
useFactory: MSALInterceptorConfigFactory,
deps: [ConfigService],
},
MsalService,
MsalGuard,
MsalBroadcastService,
{
provide: HTTP_INTERCEPTORS,
useClass: MsalInterceptor,
multi: true,
},
],
};
}
}
src/app/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 { HttpClientModule } from "@angular/common/http";
import { MsalRedirectComponent } from "@azure/msal-angular";
import { DetailComponent } from "./detail/detail.component";
import { MsalConfigDynamicModule } from "./msal-config-dynamic.module";
@NgModule({
declarations: [AppComponent, HomeComponent, ProfileComponent, DetailComponent],
imports: [BrowserModule, BrowserAnimationsModule, AppRoutingModule, MatButtonModule, MatToolbarModule, MatListModule, HttpClientModule, MsalConfigDynamicModule.forRoot("assets/configuration.json")],
providers: [],
bootstrap: [AppComponent, MsalRedirectComponent],
})
export class AppModule {}
src/assets/configuration.json
{
"msal": {
"auth": {
"clientId": "clientid",
"authority": "https://login.microsoftonline.com/common/",
"redirectUri": "http://localhost:4200/",
"postLogoutRedirectUri": "http://localhost:4200/",
"navigateToLoginRequestUrl": true
},
"cache": {
"cacheLocation": "localStorage",
"storeAuthStateInCookie": true
}
},
"guard": {
"interactionType": "redirect",
"authRequest": {
"scopes": ["user.read"]
},
"loginFailedRoute": "/login-failed"
},
"interceptor": {
"interactionType": "redirect",
"protectedResourceMap": [["https://graph.microsoft.com/v1.0/me", ["user.read"]]]
}
}
MsalGuard - Permintaan autentikasi dinamis
MsalGuard juga memungkinkan Anda mengubah authRequest secara dinamis saat runtime. Ini memungkinkan Anda memilih otoritas yang berbeda untuk rute, atau secara dinamis menambahkan cakupan berdasarkan RouterStateSnapshot.
export function MSALGuardConfigFactory(): MsalGuardConfiguration {
return {
interactionType: InteractionType.Redirect,
authRequest: (authService, state) => {
return {
scopes: state.root.url.some((x) => x.path === "calendar") ? ["user.read", " Calendars.Read"] : ["user.read"],
};
},
loginFailedRoute: "./login-failed",
};
}
Konfigurasi untuk aplikasi Angular dengan komponen mandiri
Aplikasi Angular yang menggunakan komponen mandiri dapat menggunakan factory provider seperti di atas dalam file app.config.ts, yang kemudian diimpor ke main.ts untuk proses bootstrap.
Silakan lihat Sampel Angular Standalone kami untuk penggunaan.
// app.config.ts
import { ApplicationConfig, importProvidersFrom } from "@angular/core";
import { provideRouter } from "@angular/router";
import { routes } from "./app.routes";
import { BrowserModule } from "@angular/platform-browser";
import { provideHttpClient, withInterceptorsFromDi, HTTP_INTERCEPTORS, withFetch, withInterceptors } from "@angular/common/http";
import { provideNoopAnimations } from "@angular/platform-browser/animations";
import { IPublicClientApplication, PublicClientApplication, InteractionType, BrowserCacheLocation, LogLevel } from "@azure/msal-browser";
import { MsalInterceptor, MSAL_INSTANCE, MsalInterceptorConfiguration, MsalGuardConfiguration, MSAL_GUARD_CONFIG, MSAL_INTERCEPTOR_CONFIG, MsalService, MsalGuard, MsalBroadcastService } from "@azure/msal-angular";
export function loggerCallback(logLevel: LogLevel, message: string) {
console.log(message);
}
export function MSALInstanceFactory(): IPublicClientApplication {
return new PublicClientApplication({
auth: {
clientId: "clientid",
authority: "https://login.microsoftonline.com/common/",
redirectUri: "/",
postLogoutRedirectUri: "/",
},
cache: {
cacheLocation: BrowserCacheLocation.LocalStorage,
},
system: {
allowPlatformBroker: false, // Disables WAM Broker
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,
authRequest: {
scopes: ["user.read"],
},
loginFailedRoute: "/login-failed",
};
}
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
importProvidersFrom(BrowserModule),
provideNoopAnimations(),
provideHttpClient(withInterceptorsFromDi(), withFetch()),
{
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,
],
};
// main.ts
import { bootstrapApplication } from "@angular/platform-browser";
import { appConfig } from "./app/app.config";
import { AppComponent } from "./app/app.component";
bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err));