ASP.NET Core中Azure AD SSO集成Graph API日历功能引发无限重定向循环
ASP.NET Core Azure AD SSO + Graph API 无限重定向循环问题排查与解决
原因分析
- 错误的RedirectUri配置:捕获
MicrosoftIdentityWebChallengeUserException后,你将跳转目标设为Initiative/Index,而非当前请求的Events/Index。用户完成权限同意或认证后会被导向Initiative/Index,若该页面同样需要认证/权限,或路由权限配置触发再次Challenge,就会形成循环。 - 令牌获取Scheme不匹配:
GetAccessTokenForUserAsync中指定OpenIdConnectDefaults.AuthenticationScheme不符合当前认证上下文——用户已通过OpenIdConnect登录,身份存储在Cookie中,获取令牌应基于Cookie认证Scheme。 - 权限未正确配置:若Azure AD应用注册未添加
Calendars.ReadWrite委派权限,或未完成用户/管理员同意,会反复触发权限请求,导致循环。
解决方法
1. 修正RedirectUri为当前请求页面
捕获异常时,跳转回当前请求的页面,而非其他路由:
catch (MicrosoftIdentityWebChallengeUserException ex) { _logger.LogInformation($"MicrosoftIdentityWebChallengeUserException {ex.Message}"); // 跳回当前的Events/Index页面,或用HttpContext.Request.Path获取通用路径 var redirectUrl = Url.Action("Index", "Events"); return Challenge(new AuthenticationProperties { RedirectUri = redirectUrl }, OpenIdConnectDefaults.AuthenticationScheme); }
2. 调整令牌获取的AuthenticationScheme
将令牌获取的Scheme改为Cookie认证Scheme(需引入Microsoft.AspNetCore.Authentication.Cookies命名空间):
using Microsoft.AspNetCore.Authentication.Cookies; // ... var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync( scopes: scopes, authenticationScheme: CookieAuthenticationDefaults.AuthenticationScheme);
3. 验证Azure AD应用权限配置
- 登录Azure门户,进入你的应用注册页面
- 在「API权限」中添加
Microsoft Graph的Calendars.ReadWrite委派权限 - 租户内应用点击「授予管理员同意」;多租户应用确保用户首次登录时能看到权限同意提示
4. 直接使用Microsoft Graph客户端(推荐)
既然已调用AddMicrosoftGraph(),可直接注入GraphServiceClient操作日历,无需手动获取令牌,简化代码同时避免令牌获取问题:
private readonly GraphServiceClient _graphClient; public EventsController(GraphServiceClient graphClient) { _graphClient = graphClient; } public async Task<IActionResult> Index() { try { // 示例:获取用户日历列表 var calendars = await _graphClient.Me.Calendars.Request().GetAsync(); _logger.LogInformation($"获取到{calendars.Count}个日历"); return View(calendars); } catch (MicrosoftIdentityWebChallengeUserException ex) { _logger.LogInformation($"MicrosoftIdentityWebChallengeUserException {ex.Message}"); var redirectUrl = HttpContext.Request.Path; return Challenge(new AuthenticationProperties { RedirectUri = redirectUrl }, OpenIdConnectDefaults.AuthenticationScheme); } catch (Exception ex) { _logger.LogInformation($"Exception {ex.Message}"); return RedirectToAction("Index", "Home"); } }
内容的提问来源于stack exchange,提问作者lasantha
相关产品推荐
相关产品推荐

