ASP.NET Core MVC调用Microsoft Graph API获取用户请求挂起问题解决
解决ASP.NET Core MVC中Graph API请求无限挂起的问题
问题描述
在ASP.NET Core MVC应用中调用Microsoft Graph API获取当前用户信息时,graphServiceClient.Me.GetAsync()请求无限挂起,无法完成。已完成的配置包括:
- 应用在Microsoft Identity平台注册,已授予
User.Read委派API权限 - 控制器及GraphServiceClient创建代码如下:
控制器代码
[HttpGet] public async Task<IActionResult> Index() { try { var graphServiceClient = GetGraphServiceClient(); var entraIDUser = await graphServiceClient.Me.GetAsync(); return View(); } catch (Exception ex) { _logger.LogError("An error occured when trying to return Index page: " + ex.Message); return StatusCode(500, "An error occured when trying to return Index page"); } }
GetGraphServiceClient方法代码
private GraphServiceClient GetGraphServiceClient() { var scopes = new[] { "User.Read" }; var tenantId = _configuration.GetValue<string>("AzureAd:TenantId"); var clientId = _configuration.GetValue<string>("AzureAd:ClientId"); var options = new DeviceCodeCredentialOptions { AuthorityHost = AzureAuthorityHosts.AzurePublicCloud, ClientId = clientId, TenantId = tenantId, DeviceCodeCallback = (code, cancellation) => { Console.WriteLine(code.Message); return Task.FromResult(0); }, }; var deviceCodeCredential = new DeviceCodeCredential(options); var graphClient = new GraphServiceClient(deviceCodeCredential, scopes); return graphClient; }
解决方案
1. 替换DeviceCodeCredential为Web应用适配的认证方式
DeviceCodeCredential是为桌面/设备类应用设计的交互式认证方案,在ASP.NET Core MVC这类Web应用场景下完全不适用——它会等待用户在终端输入设备码完成认证,但Web应用没有终端交互环境,直接导致请求无限挂起。
正确的做法是使用当前已登录用户的访问令牌调用Graph API,修改GetGraphServiceClient方法:
private readonly IHttpContextAccessor _httpContextAccessor; private readonly IConfiguration _configuration; private readonly ILogger<YourController> _logger; // 构造函数注入依赖 public YourController(IHttpContextAccessor httpContextAccessor, IConfiguration configuration, ILogger<YourController> logger) { _httpContextAccessor = httpContextAccessor; _configuration = configuration; _logger = logger; } private GraphServiceClient GetGraphServiceClient() { // 获取当前登录用户的access_token var accessToken = _httpContextAccessor.HttpContext.GetTokenAsync("access_token").Result; return new GraphServiceClient( new DelegateAuthenticationProvider(requestMessage => { requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); return Task.CompletedTask; })); }
2. 配置Web应用的Azure AD认证流程
在Program.cs中完善认证配置,添加Graph API权限支持:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd")) .EnableTokenAcquisitionToCallDownstreamApi(new[] { "User.Read" }) .AddInMemoryTokenCaches(); // 注册HttpContextAccessor,用于获取当前请求上下文 builder.Services.AddHttpContextAccessor();
3. 验证权限配置
- 确认应用注册中
User.Read权限为委派权限 - 如果是多租户应用或需要管理员级访问,需确保权限已获得租户管理员同意;单租户场景下,用户首次登录时会自动授权该权限
4. 检查异步调用逻辑
确保控制器方法始终使用await处理异步操作,避免同步阻塞(原代码中的await graphServiceClient.Me.GetAsync()是正确的,无需修改)
内容的提问来源于stack exchange,提问作者StanSm789
相关产品推荐
相关产品推荐

