接入Azure AD登录
约 608 字
接入Azure AD登录
安装依赖
npm install @azure/msal-browser
npm install @azure/msal-angular
在 app.module.ts
导入配置
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { PublicClientApplication, IPublicClientApplication, BrowserCacheLocation, InteractionType, LogLevel } from "@azure/msal-browser";
import { MSAL_GUARD_CONFIG, MSAL_INSTANCE, MSAL_INTERCEPTOR_CONFIG, MsalBroadcastService, MsalGuard, MsalRedirectComponent, MsalGuardConfiguration, MsalInterceptor, MsalInterceptorConfiguration, MsalModule, MsalService } from '@azure/msal-angular';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule,
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]
})
export class AppModule { }
const isIE =
window.navigator.userAgent.indexOf("MSIE ") > -1 ||
window.navigator.userAgent.indexOf("Trident/") > -1;
export function MSALInterceptorConfigFactory(): MsalInterceptorConfiguration {
const GRAPH_ENDPOINT = 'Enter_the_Graph_Endpoint_Herev1.0/me';
const protectedResourceMap = new Map<string, Array<string>>();
protectedResourceMap.set(GRAPH_ENDPOINT, ['user.read']);
return {
interactionType: InteractionType.Popup,
protectedResourceMap,
};
}
export function MSALGuardConfigFactory(): MsalGuardConfiguration {
return {
interactionType: InteractionType.Popup,
authRequest: {
scopes: ['user.read'],
},
};
}
export function MSALInstanceFactory(): IPublicClientApplication {
return new PublicClientApplication({
auth: {
clientId: 'Enter_the_Application_Id_here',
authority: 'https://login.microsoftonline.com/Enter_the_Tenant_Info_Here',
redirectUri: 'Enter_the_Redirect_Uri_Here',
},
cache: {
cacheLocation: BrowserCacheLocation.LocalStorage,
storeAuthStateInCookie: isIE, // set to true for IE 11
},
system: {
loggerOptions: {
logLevel: LogLevel.Info,
piiLoggingEnabled: false,
},
},
});
}
配置 app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LoginComponent } from './pages/login/login.component';
import { BrowserUtils } from '@azure/msal-browser';
const routes: Routes = [];
@NgModule({
imports: [RouterModule.forRoot(routes, {
// Don't perform initial navigation in iframes or popups
initialNavigation:
!BrowserUtils.isInIframe() && !BrowserUtils.isInPopup()
? 'enabledNonBlocking'
: 'disabled', // Set to enabledBlocking to use Angular Universal
})],
exports: [RouterModule]
})
export class AppRoutingModule { }
配置 app.component.html
<ng-container *ngIf="currentUserName; else elseBlock">
<div>{{currentUserName}}</div>
<button (click)="logout()">登出</button>
</ng-container>
<ng-template #elseBlock>
<button (click)="login()">登录</button>
</ng-template>
<div class="container">
<!--This is to avoid reload during acquireTokenSilent() because of hidden iframe -->
<router-outlet *ngIf="!isIframe"></router-outlet>
</div>
配置 app.component.ts
import { Component, OnInit, Inject, OnDestroy } from '@angular/core';
import { MsalService, MsalBroadcastService, MSAL_GUARD_CONFIG, MsalGuardConfiguration } from '@azure/msal-angular';
import { AuthenticationResult, InteractionStatus, InteractionType, PopupRequest, RedirectRequest } 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 {
isIframe = false;
currentUserName: string | undefined;
private readonly _destroying$ = new Subject<void>();
constructor(
@Inject(MSAL_GUARD_CONFIG) private msalGuardConfig: MsalGuardConfiguration,
private authService: MsalService,
private msalBroadcastService: MsalBroadcastService
) { }
ngOnInit(): void {
this.isIframe = window !== window.parent && !window.opener;
this.msalBroadcastService.inProgress$
.pipe(
filter((status: InteractionStatus) => status === InteractionStatus.None),
takeUntil(this._destroying$)
)
.subscribe(() => {
this.setLoginDisplay();
});
}
setLoginDisplay() {
this.currentUserName = this.authService.instance.getAllAccounts()[0].name;
}
login() {
if (this.msalGuardConfig.interactionType === InteractionType.Popup) {
if (this.msalGuardConfig.authRequest) {
this.authService.loginPopup({ ...this.msalGuardConfig.authRequest } as PopupRequest)
.subscribe((response: AuthenticationResult) => {
this.authService.instance.setActiveAccount(response.account);
});
} else {
this.authService.loginPopup()
.subscribe((response: AuthenticationResult) => {
this.authService.instance.setActiveAccount(response.account);
});
}
} else {
if (this.msalGuardConfig.authRequest) {
this.authService.loginRedirect({ ...this.msalGuardConfig.authRequest } as RedirectRequest);
} else {
this.authService.loginRedirect();
}
}
}
logout() {
if (this.msalGuardConfig.interactionType === InteractionType.Popup) {
this.authService.logoutPopup({
postLogoutRedirectUri: "/",
mainWindowRedirectUri: "/"
});
} else {
this.authService.logoutRedirect({
postLogoutRedirectUri: "/",
});
}
}
ngOnDestroy(): void {
this._destroying$.next(undefined);
this._destroying$.complete();
}
}
添加 <app-redirect>
选择器
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>msal-angular-tutorial</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
<app-redirect></app-redirect>
</body>
</html>
选择重定向登录
export function MSALInterceptorConfigFactory(): MsalInterceptorConfiguration {
const GRAPH_ENDPOINT = 'Enter_the_Graph_Endpoint_Herev1.0/me';
const protectedResourceMap = new Map<string, Array<string>>();
protectedResourceMap.set(GRAPH_ENDPOINT, ['user.read']);
return {
interactionType: InteractionType.Redirect,
protectedResourceMap,
};
}
export function MSALGuardConfigFactory(): MsalGuardConfiguration {
return {
interactionType: InteractionType.Redirect,
authRequest: {
scopes: ['user.read'],
},
};
}
选择弹出窗口登录
export function MSALInterceptorConfigFactory(): MsalInterceptorConfiguration {
const GRAPH_ENDPOINT = 'Enter_the_Graph_Endpoint_Herev1.0/me';
const protectedResourceMap = new Map<string, Array<string>>();
protectedResourceMap.set(GRAPH_ENDPOINT, ['user.read']);
return {
interactionType: InteractionType.Popup,
protectedResourceMap,
};
}
export function MSALGuardConfigFactory(): MsalGuardConfiguration {
return {
interactionType: InteractionType.Popup,
authRequest: {
scopes: ['user.read'],
},
};
}