ASP.NET Core对接ADFS 2016时GetExternalLoginInfoAsync返回null如何解决
问题根因与修正方案
1. 中间件顺序错误(最高优先级修复)
ASP.NET Core 中间件执行顺序严格匹配注册顺序,Identity 外部登录临时数据存储在 Session 中,必须将
UseSession放在UseAuthentication之前,否则身份验证中间件读取不到 Session 里的外部登录上下文,直接导致GetExternalLoginInfoAsync返回 null。
修正后的Configure代码:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); // 先启用Session,再执行身份验证逻辑 app.UseSession(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); }
2. WsFederation 配置缺失必要参数
- 缺少 SignInScheme 指定:必须指定为 Identity 预设的外部登录方案
IdentityConstants.ExternalScheme,否则外部登录凭据不会写入对应 Cookie,GetExternalLoginInfoAsync无法读取到有效数据 - 缺少声明映射配置:ADFS 返回的标准声明类型需要和 Identity 预期的声明类型匹配,必须显式配置映射规则
Wreply参数必须和 ADFS 信赖方配置的回调地址完全一致,包括大小写、末尾斜杠、路径层级
修正后的 WsFederation 注册代码:
using Microsoft.AspNetCore.Identity; services.AddAuthentication().AddWsFederation(options => { options.MetadataAddress = "https://你的ADFS元数据地址"; options.Wtrealm = "https://你的应用信赖方标识"; options.Wreply = "https://你的应用域名/AdfsCallback/CallbackAsync"; // 必须指定外部登录专属方案 options.SignInScheme = IdentityConstants.ExternalScheme; // 映射ADFS返回的标准声明到Identity预期类型 options.TokenValidationParameters.NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"; options.TokenValidationParameters.RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"; // 开发环境如果ADFS用自签名证书可以临时加这段跳过校验,生产环境必须删除 if (env.IsDevelopment()) { options.BackchannelHttpHandler = new HttpClientHandler { ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true }; } });
3. 回调接口缺少必要配置
- 回调接口必须加
[AllowAnonymous]特性,否则未登录状态下会被权限拦截,身份上下文会直接丢失 - 若读取信息为空可以打印当前请求的所有声明排查ADFS是否正常返回了凭据
修正后的回调控制器代码:
[AllowAnonymous] [HttpPost] public async Task<ContentResult> CallbackAsync() { var info = await _signInManager.GetExternalLoginInfoAsync(); if (info == null) { SLog.AddMessage("AdfsControllers.Post", "info is null", 5); // 打印返回的声明排查问题 foreach (var claim in User.Claims) { SLog.AddMessage("ADFS返回声明", $"{claim.Type}:{claim.Value}", 5); } } else { SLog.AddMessage("AdfsControllers.Post", info.ToString(), 5); // 后续可执行本地账号绑定/自动创建逻辑 var signInResult = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false); if (signInResult.Succeeded) { // 登录成功跳转对应页面 } } return base.Content("Hello", "text/html"); }
4. ADFS 端配置校验
- 确保信赖方信任中已启用 WS-Federation 被动协议
- 确保信赖方已发布至少
名称ID、用户主体名称这两个必要声明 - 确保令牌签名证书已经加入到应用服务器的信任根证书列表
内容的提问来源于stack exchange,提问作者Carl-Johan Uhlin
相关产品推荐
相关产品推荐

