使用AuthServices多IdP:如何在ACS与回调Action间传递entityId?
解决方案:在Sustainsys.Saml2中识别用户所属的Identity Provider
我来帮你搞定这个问题!在Sustainsys.Saml2框架里,完全不需要强制IdP发送特殊声明,就能在回调Action里获取到对应的IdP EntityId,这里有几个实用的方法:
方法1:利用框架默认生成的IdentityProvider Claim
Sustainsys.Saml2在处理SAML响应时,会自动把IdP的EntityId添加到用户的Claims集合里,对应的Claim类型是http://schemas.microsoft.com/ws/2008/06/identity/claims/identityprovider。你直接在ExternalLoginCallback里提取就行:
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null) { // 获取SAML认证的结果 var authResult = await HttpContext.AuthenticateAsync(Saml2Defaults.AuthenticationScheme); if (!authResult.Succeeded) { // 处理认证失败的逻辑,比如跳回登录页 return RedirectToAction("Login"); } // 提取IdP的EntityId var idpEntityId = authResult.Principal.FindFirstValue("http://schemas.microsoft.com/ws/2008/06/identity/claims/identityprovider"); // 接下来就可以用这个idpEntityId来判断用户属于哪个IdP了 // ...你的业务逻辑 }
这个方法最省心,完全依赖框架的默认行为,不需要改任何额外配置。
方法2:发起认证时主动传递IdP EntityId
如果想更主动地控制这个值的传递,你可以在触发SAML登录挑战的时候,把IdP的EntityId存入AuthenticationProperties里,之后在回调里取出来:
触发登录的代码(比如用户选择某个IdP后的Action)
public IActionResult LoginWithSpecificIdp(string idpEntityId) { var authProperties = new AuthenticationProperties { Items = { { "TargetIdpEntityId", idpEntityId } }, RedirectUri = Url.Action("ExternalLoginCallback") }; // 针对指定的IdP发起认证挑战 return Challenge(authProperties, Saml2Defaults.AuthenticationScheme, idpEntityId); }
回调Action中提取值
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null) { // 获取认证时的属性集合 var authProperties = await HttpContext.GetAuthenticationAsyncProperties(Saml2Defaults.AuthenticationScheme); if (authProperties?.Items.TryGetValue("TargetIdpEntityId", out var idpEntityId) == true) { // 这里就拿到了发起登录时指定的IdP EntityId // ...你的验证逻辑 } // 后续业务处理 // ... }
这种方式适合你需要在发起登录时就明确记录目标IdP的场景,完全可控。
方法3:通过认证事件自定义处理
你还可以借助Sustainsys的Saml2AuthenticationEvents,在认证完成时手动把IdP的EntityId添加到用户Claims或者属性里:
在你的Startup.cs(或者Program.cs)的认证配置里添加这个事件:
services.AddAuthentication() .AddSaml2(options => { // 这里是你已有的Saml2配置,比如IdP元数据、SP配置等 // ... options.Events = new Saml2AuthenticationEvents { OnAuthenticated = context => { // 从SAML响应里直接获取IdP的Issuer(也就是EntityId) var idpEntityId = context.Saml2Response.Issuer.Value; // 可以添加一个自定义Claim,方便后续取用 context.Principal.AddClaim(new Claim("CustomIdpEntityId", idpEntityId)); // 也可以把值存入AuthenticationProperties context.Properties.Items["CustomIdpEntityId"] = idpEntityId; return Task.CompletedTask; } }; });
之后在ExternalLoginCallback里,你就可以通过authResult.Principal.FindFirstValue("CustomIdpEntityId")或者从属性集合里提取这个值了。
内容的提问来源于stack exchange,提问作者sav931
相关产品推荐
相关产品推荐

