如何通过MSAL库在AAD V2端点实现Web API访问MS Graph用户配置文件的用户同意流程
我来帮你梳理这个场景的完整实现方案,从Angular5客户端的MSAL配置到ASP.NET Core Web API的Graph资源调用,一步步拆解:
整体流程概述
你的场景核心是Angular5客户端通过MSAL获取针对Web API的访问令牌 → 携带令牌调用ASP.NET Core Web API → Web API通过On-Behalf-Of(委托)流程获取Graph API的令牌 → 最终返回Graph资源给客户端,整个链路依赖AAD v2端点的身份认证机制。
关键步骤与代码示例
1. Angular5客户端MSAL配置与令牌获取
首先完成MSAL的初始化,确保请求的作用域指向你的Web API,这样获取到的令牌才能被Web API验证通过:
import { MsalService, LogLevel, InteractionRequiredAuthError } from '@azure/msal-angular'; import { Logger } from '@azure/msal-browser'; constructor(private msalService: MsalService) { // 初始化日志记录器 const logger = new Logger((logLevel, message) => { console.log(`MSAL日志: ${message}`); }, { level: LogLevel.Info }); // 配置MSAL核心参数 this.msalService.initialize({ auth: { clientId: '你的融合应用ClientId', // 从apps.dev.microsoft.com获取 authority: 'https://login.microsoftonline.com/common', // AAD v2公共端点 redirectUri: 'http://localhost:4200', // Angular应用回调地址 postLogoutRedirectUri: 'http://localhost:4200' }, cache: { cacheLocation: 'localStorage', storeAuthStateInCookie: false }, system: { logger } }); // 设置当前活跃账户(自动登录后恢复会话) const accounts = this.msalService.getAllAccounts(); if (accounts.length > 0) { this.msalService.setActiveAccount(accounts[0]); } } // 调用Web API获取Graph资源的方法 async fetchGraphDataViaApi() { const tokenRequest = { scopes: ['api://你的WebAPI-ClientId/access_as_user'] // 必须和Web API的受众配置一致 }; try { // 静默获取令牌(优先从缓存取) const tokenResponse = await this.msalService.acquireTokenSilent(tokenRequest); // 携带令牌调用Web API const apiResponse = await fetch('https://localhost:5001/api/graphdata', { headers: { 'Authorization': `Bearer ${tokenResponse.accessToken}` } }); if (!apiResponse.ok) throw new Error('Web API请求失败'); const graphData = await apiResponse.json(); console.log('获取到的Graph资源:', graphData); return graphData; } catch (error) { // 静默获取失败时触发交互式弹窗登录 if (error instanceof InteractionRequiredAuthError) { await this.msalService.acquireTokenPopup(tokenRequest); // 重试调用API return this.fetchGraphDataViaApi(); } console.error('令牌获取或API调用出错:', error); throw error; } }
2. ASP.NET Core Web API配置与Graph调用
Web API需要先验证客户端传来的令牌,再通过委托流程获取Graph的访问令牌,最终调用Graph API返回资源:
2.1 核心配置(Program.cs)
var builder = WebApplication.CreateBuilder(args); // 配置AAD v2身份认证 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd")); // 配置Graph服务(集成委托流程) builder.Services.AddMicrosoftGraph(builder.Configuration.GetSection("Graph")) .AddDownstreamWebApi("GraphApi", builder.Configuration.GetSection("Graph")) .AddInMemoryTokenCaches(); // 开发环境用内存缓存,生产建议换分布式缓存 builder.Services.AddControllers(); var app = builder.Build(); app.UseHttpsRedirection(); app.UseAuthentication(); // 启用认证 app.UseAuthorization(); // 启用授权 app.MapControllers(); app.Run();
2.2 配置文件(appsettings.json)
{ "AzureAd": { "Instance": "https://login.microsoftonline.com/", "TenantId": "common", "ClientId": "你的Web API应用ClientId", // 从apps.dev.microsoft.com注册的Web API应用ID "ClientSecret": "你的Web API客户端密码", "Audience": "api://你的WebAPI-ClientId" // 必须和Angular请求的作用域前缀一致 }, "Graph": { "BaseUrl": "https://graph.microsoft.com/v1.0", "Scopes": "user.read mail.read" // 你需要调用的Graph权限 } }
2.3 编写API控制器
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Identity.Web; [ApiController] [Route("api/[controller]")] [Authorize] // 只有携带有效令牌的请求才能访问 public class GraphDataController : ControllerBase { private readonly IDownstreamWebApi _downstreamWebApi; public GraphDataController(IDownstreamWebApi downstreamWebApi) { _downstreamWebApi = downstreamWebApi; } [HttpGet] public async Task<IActionResult> GetGraphUserData() { try { // 自动通过委托流程获取Graph令牌并调用API var userProfile = await _downstreamWebApi.CallWebApiAsync<object>( "GraphApi", options => options.RelativePath = "me" // 调用Graph的用户信息接口 ); return Ok(userProfile); } catch (Exception ex) { return BadRequest($"调用Graph API失败:{ex.Message}"); } } }
关键注意事项
- 应用注册配置:
- Angular的融合应用需在apps.dev.microsoft.com中添加Web API的权限(API权限 → 添加权限 → 我的API → 选择你的Web API应用)。
- Web API应用需启用委托流程,同时添加Graph API的委托权限,并授予管理员同意(若需要用户无需手动同意)。
- 作用域格式:Angular中请求的作用域必须是
api://[WebAPI-ClientId]/[权限名称],确保和Web API的Audience配置完全匹配。 - HTTPS要求:AAD身份认证流程强制要求HTTPS,开发时需确保Angular和Web API都启用HTTPS。
内容的提问来源于stack exchange,提问作者user1672994
相关产品推荐
相关产品推荐

