You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:00:16