多子域网站对接Azure/ADFS登录报NONCE错误问题咨询
问题结论
你的推测完全成立,IDX21323 NONCE校验错误的核心原因就是启动阶段固定配置的RedirectUri与用户实际访问的源站域名不匹配。
错误原理说明
- OIDC认证流程生成的nonce校验值,默认会写入发起登录请求的当前域名下的cookie,用于回调时校验返回的ID令牌合法性,防范重放攻击
- 当前配置下,用户在子域
subdomain.customer.nl发起登录时,传给微软身份平台的redirect_uri被固定写为主域customer.nl,登录完成后请求会被重定向到主域 - 主域域名下无法读取子域写入的nonce cookie,校验环节拿不到请求上下文中存储的nonce值,和ID令牌中携带的nonce无法匹配,就会抛出对应错误
- 你在
SignIn方法中修改的AuthenticationProperties.RedirectUri是认证流程完成后业务层面的站内跳转地址,不是传给身份平台的OAuth回调地址,因此修改该值不会影响登录跳转URL中的redirect_uri参数。
适配多子域场景的解决方案
前置配置
首先去Azure AD/ADFS的应用注册配置页,将所有需要支持的域名的回调地址(例如https://customer.nl/signin-oidc、https://subdomain.customer.nl/signin-oidc)添加到应用的重定向URI白名单中,否则身份平台会直接拦截域名不匹配的回调请求。
代码修改
移除启动阶段硬编码的固定RedirectUri、PostLogoutRedirectUri配置,通过OIDC中间件的通知事件,在每次发起认证请求时动态生成当前访问域名对应的回调地址,修改后的ConfigureAuth代码参考如下:
public void ConfigureAuth(IAppBuilder app) { app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); app.UseCookieAuthentication(new CookieAuthenticationOptions() { CookieManager = new SystemWebCookieManager(), // 如需多子域共享登录态可配置根域Cookie,不需要可删除该行 CookieDomain = ".customer.nl" }); app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { ClientId = clientId, Authority = authority, // 删除固定赋值的RedirectUri、PostLogoutRedirectUri配置 Scope = OpenIdConnectScope.OpenIdProfile, ResponseType = OpenIdConnectResponseType.IdToken, TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = false }, Notifications = new OpenIdConnectAuthenticationNotifications { RedirectToIdentityProvider = context => { var request = context.OwinContext.Request; var currentOrigin = $"{request.Scheme}://{request.Host}"; // 路径需和OIDC中间件默认/自定义配置的CallbackPath一致,默认值为/signin-oidc context.ProtocolMessage.RedirectUri = $"{currentOrigin}/signin-oidc"; context.ProtocolMessage.PostLogoutRedirectUri = currentOrigin; return Task.CompletedTask; }, AuthenticationFailed = OnAuthenticationFailed } }); }
注意事项
- 不要通过设置
OpenIdConnectProtocolValidator.RequireNonce = false绕过校验,该操作会关闭nonce防重放校验能力,大幅降低认证流程安全性 - 如果自定义过OIDC中间件的
CallbackPath属性,拼接RedirectUri时的路径需要和自定义值保持一致 - 若不需要多子域共享登录状态,无需配置
CookieDomain属性,各子域独立维护认证Cookie即可
内容的提问来源于stack exchange,提问作者Cryothic
相关产品推荐
相关产品推荐

