如何在Angular+Nest.js全栈应用中集成微软身份认证授权?
解决方案:Angular + NestJS 集成微软身份认证(授权码流)
一、配置本地Nest API的URI
1. Azure后端应用注册配置
在Azure Portal的后端App Registration页面,进入Expose an API面板:
- 点击
Set配置Application ID URI,可使用默认的api://<后端client-id>,也可自定义为更直观的标识(比如api://nest-backend-local),这个URI是API的唯一识别符,后续token验证会用到。 - 添加Delegated类型的API权限范围(Scope),比如
access_as_user,用于授权用户访问API。
2. NestJS本地配置
在项目的.env配置文件中添加核心参数:
AZURE_TENANT_ID=<你的租户ID> AZURE_BACKEND_CLIENT_ID=<后端App Registration的Client ID> AZURE_API_AUDIENCE=<刚才配置的Application ID URI> LOCAL_API_URL=http://localhost:3000 # 你的NestJS本地服务地址
同时配置CORS允许前端跨域请求:
// main.ts async function bootstrap() { const app = await NestFactory.create(AppModule); app.enableCors({ origin: 'http://localhost:4200', // Angular本地服务地址 credentials: true, allowedHeaders: ['Authorization', 'Content-Type'], }); await app.listen(3000); } bootstrap();
二、保护NestJS API
1. 安装依赖
npm install @nestjs/passport passport passport-azure-ad npm install --save-dev @types/passport-azure-ad
2. 创建认证模块与策略
新建auth/auth.module.ts:
import { Module } from '@nestjs/common'; import { PassportModule } from '@nestjs/passport'; import { AzureADStrategy } from './azure-ad.strategy'; @Module({ imports: [PassportModule], providers: [AzureADStrategy], exports: [PassportModule], }) export class AuthModule {}
新建auth/azure-ad.strategy.ts,实现Bearer Token验证逻辑:
import { Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { BearerStrategy } from 'passport-azure-ad'; import { ConfigService } from '@nestjs/config'; @Injectable() export class AzureADStrategy extends PassportStrategy(BearerStrategy) { constructor(configService: ConfigService) { super({ identityMetadata: `https://login.microsoftonline.com/${configService.get('AZURE_TENANT_ID')}/v2.0/.well-known/openid-configuration`, clientID: configService.get('AZURE_BACKEND_CLIENT_ID'), audience: configService.get('AZURE_API_AUDIENCE'), validateIssuer: true, loggingLevel: 'info', passReqToCallback: false, }); } async validate(payload: any) { // 可根据token payload中的用户信息做额外校验(比如关联数据库用户) return { userId: payload.oid, username: payload.name, email: payload.email }; } }
3. 保护API路由
在需要鉴权的控制器上添加@UseGuards(AuthGuard('azure-ad')):
import { Controller, Get, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; @Controller('protected') export class ProtectedController { @Get() @UseGuards(AuthGuard('azure-ad')) getProtectedData() { return { message: '这是受保护的API数据' }; } }
三、前后端集成(Angular MSAL + NestJS)
1. Angular MSAL配置映射API权限
在app.module.ts中配置MsalModule,确保protectedResourceMap将NestJS API地址关联到后端的权限Scope:
import { MsalModule, MsalInterceptor } from '@azure/msal-angular'; import { HTTP_INTERCEPTORS } from '@angular/common/http'; @NgModule({ imports: [ MsalModule.forRoot({ auth: { clientId: '<前端App Registration的Client ID>', authority: 'https://login.microsoftonline.com/<你的租户ID>', redirectUri: 'http://localhost:4200', // 已配置的前端回调地址 }, cache: { cacheLocation: 'localStorage', storeAuthStateInCookie: false, }, }, { popUp: true, // 使用弹窗登录模式 protectedResourceMap: new Map([ ['http://localhost:3000/protected', ['api://nest-backend-local/access_as_user']] ]) }) ], providers: [ { provide: HTTP_INTERCEPTORS, useClass: MsalInterceptor, multi: true } ] }) export class AppModule {}
2. 调用受保护的NestJS API
在Angular组件中直接发起请求,MsalInterceptor会自动在请求头中带上Authorization Token:
import { HttpClient } from '@angular/common/http'; import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: `<button (click)="fetchProtectedData()">获取受保护数据</button>` }) export class AppComponent { constructor(private http: HttpClient) {} fetchProtectedData() { this.http.get('http://localhost:3000/protected').subscribe(data => { console.log('获取到受保护数据:', data); }); } }
关键注意事项
- 确保前端App Registration已添加后端API的Delegated权限,且已完成用户/管理员授权(测试环境可在Azure中点击“授予管理员同意”)。
- 可通过解码工具查看access token的
aud字段,必须与后端的Application ID URI完全一致,否则验证会失败。 - 生产环境部署时,需将本地地址替换为实际服务器域名,并同步更新Azure的CORS、权限配置。
内容的提问来源于stack exchange,提问作者Visrut
相关产品推荐
相关产品推荐

