ASP.NET Core 6 MVC获取令牌报MsalUiRequiredException错误
问题说明
ASP.NET Core 6 MVC项目调用Microsoft Graph API时,执行GetAccessTokenForUserAsync()方法获取用户令牌抛出MsalUiRequiredException异常,错误信息如下:
An MsalUiRequiredException was thrown due to a challenge for the user. No account or login hint was passed to the AcquireTokenSilent call
现有相关代码配置:
Program.cs
JwtSecurityTokenHandler.DefaultMapInboundClaims = false; // Add services to the container. builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd")) .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) .AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph")) .AddInMemoryTokenCaches();
appSettings.json
"MicrosoftGraph": { "BaseUrl": "https://graph.microsoft.com/v1.0", "Scopes": "user.read" },
控制器代码
[AuthorizeForScopes(Scopes = new string[] { "user.read" })] public class UserManagementController : Controller { ... [AuthorizeForScopes(Scopes = new string[] { "user.read" })] public async Task<IActionResult> Index() { try { var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new string[] { "user.read" }); return View(); } catch(Exception ex) { return BadRequest("An error occurred loading the user management page."); } } }
解决方案
这个报错绝大多数原因是自定义try-catch块吞掉了MsalUiRequiredException异常。[AuthorizeForScopes]特性本身依赖捕获这个异常来触发增量同意、重新认证的交互流程,异常被业务代码拦截后,框架无法触发交互逻辑,就会持续抛出该错误。按以下步骤调整即可:
- 调整异常捕获逻辑,不要拦截
MsalUiRequiredException,将该类型异常直接抛出给框架处理,其他业务异常再走自定义错误返回:[AuthorizeForScopes(Scopes = new string[] { "user.read" })] public class UserManagementController : Controller { ... [AuthorizeForScopes(Scopes = new string[] { "user.read" })] public async Task<IActionResult> Index() { try { var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new string[] { "user.read" }); return View(); } catch (MsalUiRequiredException) { // 抛出给框架处理,自动触发权限同意/重新登录流程 throw; } catch(Exception ex) { return BadRequest("An error occurred loading the user management page."); } } } - 检查Program.cs中
initialScopes变量的赋值,确保其包含user.read权限,不要传入空数组。如果不需要自定义初始scope集合,直接传入明确的权限数组即可:.EnableTokenAcquisitionToCallDownstreamApi(new []{ "user.read" }) - 核对Azure AD应用注册配置:
- API权限页已添加
Microsoft Graph -> User.Read委托权限 - 配置的重定向URI和实际调试/部署的站点地址完全匹配
- 没有配置额外的条件访问策略强制要求多因素认证等额外交互步骤(如果有,对应权限需要提前在scope中声明)
- API权限页已添加
调整完成后首次访问接口时,框架会自动拉起权限同意流程,用户完成授权后令牌会写入内存缓存,后续调用即可正常获取令牌。
内容的提问来源于stack exchange,提问作者Cef
相关产品推荐
相关产品推荐

