技术求助:如何通过ADFS作为身份提供商实现MS Office用户直接认证并解决适配问题
解决方案:让MS Office通过ADFS OIDC完成WebDAV认证
我来帮你拆解问题根源,再一步步给出具体的修复方案:
问题核心分析
你的思路方向是对的,但卡在了两个关键点:
- Office的嵌入式浏览器在处理MS-OFBA跳转时,不会自动携带之前的
OpenIdConnect.nonceCookie——这是Office内置浏览器的安全限制,导致ADFS收到请求时因为缺少nonce验证返回401,触发Windows凭证弹窗。 - 中间件的注册顺序和响应修改时机需要调整,才能确保OIDC挑战逻辑和Office兼容格式的响应正确衔接。
具体修复步骤
1. 调整中间件注册顺序(关键)
挑战触发逻辑必须在OIDC中间件之前执行,Office响应修改逻辑要在OIDC之后。正确的顺序如下:
// 第一步:触发OIDC挑战的中间件,放在最前面 app.Use(async (context, next) => { await next.Invoke(); // 修正判断逻辑:仅对未认证的WebDAV请求触发挑战 if (!context.Request.User.Identity.IsAuthenticated && IsWebDav(context.Request)) { context.Response.StatusCode = 401; context.Authentication.Challenge("ADFS"); } }); // 第二步:ADFS OIDC中间件,处理挑战生成跳转URL和nonce app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions("ADFS") { RedirectUri = "https://your-app-domain/signin-oidc", // 需和ADFS信赖方配置一致 ResponseType = OpenIdConnectResponseType.IdToken, Authority = "https://adfs-provider.hostname/adfs", ClientId = "your-client-id", // 调整nonce Cookie配置,让Office浏览器能读取 NonceCookie = new CookieAuthenticationOptions { HttpOnly = false, SecurePolicy = CookieSecurePolicy.Always, SameSite = SameSiteMode.None } }); // 第三步:修改响应为Office兼容格式的中间件 app.Use(async (context, next) => { await next.Invoke(); var provider = "ADFS"; var challenge = context.Authentication.AuthenticationResponseChallenge; bool isAdfsChallenge = challenge != null && challenge.AuthenticationTypes?.Any(at => string.Equals(at, provider, StringComparison.Ordinal)) == true; // 仅对OIDC生成的302跳转响应做修改 if (isAdfsChallenge && context.Response.StatusCode == 302) { var loginUri = context.Response.Headers["Location"].ToString(); var successUri = $"{context.Request.Scheme}://{context.Request.Host.ToUriComponent()}{context.Request.Path}"; // 提取nonce并编码到loginUri中(绕过Cookie传递限制) var nonceValue = context.Request.Cookies.Keys .FirstOrDefault(k => k.StartsWith("OpenIdConnect.nonce."))? .Split('.') .Last(); if (!string.IsNullOrEmpty(nonceValue)) { loginUri += loginUri.Contains('?') ? "&" : "?"; loginUri += $"nonce={Uri.EscapeDataString(nonceValue)}"; } // 重置响应为Office兼容的403格式 context.Response.StatusCode = 403; context.Response.Headers.Clear(); context.Response.Headers.Add("X-FORMS_BASED_AUTH_REQUIRED", new[] { $"{loginUri}?ReturnUrl={Uri.EscapeDataString(successUri)}" }); context.Response.Headers.Add("X-FORMS_BASED_AUTH_RETURN_URL", new[] { successUri }); context.Response.Headers.Add("X-FORMS_BASED_AUTH_DIALOG_SIZE", new[] { "800x600" }); } });
2. 配置ADFS接受查询参数中的nonce
默认ADFS只认可Cookie中的nonce,需要修改ADFS设置允许通过查询参数传递:
- 通过ADFS管理控制台:进入服务 > 认证方法,找到OpenID Connect设置,启用"允许通过查询参数传递nonce"(ADFS 2019+支持)
- 或者用PowerShell命令:
Set-AdfsProperties -EnableOidcNonceInQueryString $true
替代方案:改用WS-Federation协议
如果OIDC的nonce问题难以彻底解决,推荐切换到ADFS的WS-Federation协议——它的认证流程不需要nonce,更适配Office的OFBA机制:
- 注册WS-Federation中间件替代OIDC
- 触发挑战时,直接生成ADFS的WS-Fed登录URL,返回403+自定义头,Office就能直接加载ADFS的凭证页面,无需处理nonce问题。
额外注意事项
- 确保ADFS的信赖方信任配置中,你的应用回调地址已被添加为允许的地址
- 测试时用Fiddler监控完整请求链,确认nonce被正确传递到ADFS
- 若Office仍无法加载ADFS页面,检查ADFS是否配置了SameSite=None的Cookie(跨域场景下需要)
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

