MVC Core应用中如何强制Microsoft Graph重新身份验证并获取有效客户端
问题根因
你遇到的MsalUiRequiredException: No account or login hint was passed to the AcquireTokenSilent call报错有两个核心原因:
- 仅设置
ForceRefresh = true只能强制刷新可用的刷新令牌,如果刷新令牌也过期、或者用户会话对应的令牌缓存中没有匹配的账户信息,静默获取令牌的逻辑本身就无法生效,必须触发交互式身份验证流程才能拿到新的令牌。 ITokenAcquisition不会自动触发登录跳转,你在控制器异常处理逻辑里直接尝试静默拿新令牌的操作本身就缺少用户交互的环节,自然会报错。
修复方案
方案1:最小改动适配原有逻辑
不需要修改ConfigureServices里的Graph客户端注册逻辑,只需要调整控制器里的异常处理代码:
捕获到MsalUiRequiredException之后,不要尝试在当前请求里直接重建Graph客户端获取新令牌,而是返回身份验证挑战,强制用户重新登录,登录完成后会自动跳转回当前操作页面:
if (ex.InnerException.InnerException is MsalUiRequiredException) { string[] _scopes = _config.GetValue<string>("AzureAd:GraphScopes")?.Split(' '); return Challenge( new AuthenticationProperties { RedirectUri = Request.Path.Value }, OpenIdConnectDefaults.AuthenticationScheme); }
注意:需要先引入Microsoft.AspNetCore.Authentication.OpenIdConnect命名空间才能使用OpenIdConnectDefaults常量
方案2:优化Graph客户端注册,自带令牌刷新能力
推荐直接使用微软官方封装的Graph扩展,省去自己维护身份验证提供器的逻辑,不需要手动处理令牌过期问题:
- 先安装
Microsoft.Identity.Web.MicrosoftGraphNuGet包 - 修改
ConfigureServices里的注册逻辑:
services.AddMicrosoftIdentityWebAppAuthentication(Configuration) .EnableTokenAcquisitionToCallDownstreamApi(_scopes) // 这里的_scopes是你定义的Graph权限数组 .AddMicrosoftGraph(options => { options.Scopes = _scopes; // 可按需全局开启强制刷新,默认关闭即可,只有异常场景才需要强制刷新 // options.TokenAcquisitionOptions.ForceRefresh = true; }) .AddInMemoryTokenCaches(); // 生产环境可替换为分布式缓存
- 直接在控制器构造函数注入
GraphServiceClient即可使用,不需要自己维护实例,令牌过期后扩展会自动处理刷新逻辑,静默刷新失败的场景再按方案1的方式返回挑战即可。
额外排查点
如果修改后还是报找不到账户的错误,检查当前登录用户的Claims是否包含http://schemas.microsoft.com/identity/claims/objectidentifier(用户OID)和tid(租户ID)两个声明,缺少这两个声明的话ITokenAcquisition无法匹配到缓存中的账户信息。
内容的提问来源于stack exchange,提问作者ficelles
相关产品推荐
相关产品推荐

