忽略SAML2响应中的AuthenticationContext



我们有一个asp.net 5 web应用程序,它将作为我们用户的服务提供商
为此,我们选择了ITfoxtec Identity SAML 2.0
请求成功,但在响应中我们得到以下错误:

System.ArgumentException:IDX13300:"System.String"必须是绝对Uri,原来是:"System.Uri">

为了完整起见,这里是完整的堆栈跟踪:

Microsoft.IdentityModel.Tokens.Saml2SecurityTokenReadException:IDX13102:读取Saml2SecurityToken的"System.String"时引发异常。内部异常:"System.ArgumentException"。--->System.ArgumentException:IDX13300:"System.String"必须是绝对Uri,其为:"System.Uri"位于Microsoft.IdentityModel.Tokens.Saml2.Saml2AuthenticationContext.set_DeclarationReference(Uri值)位于Microsoft.IdentityModel.Tokens.Saml2.Saml2Serializer.ReadAuthenticationContext(XmlDictionaryReader读取器)---内部异常堆栈跟踪结束---位于Microsoft.IdentityModel.Tokens.Saml2.Saml2Serializer.ReadAuthenticationContext(XmlDictionaryReader读取器)位于Microsoft.IdentityModel.Tokens.Saml2.Saml2Serializer.ReadAuthenticationStatement(XmlDictionaryReader读取器)位于Microsoft.IdentityModel.Tokens.Saml2.Saml2Serializer.ReadAssertion(XmlReader读取器)位于Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ReadSaml2Token(XmlReader读取器)位于Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ReadSaml2Token(字符串令牌)位于ITfoxtec.Identity.Saml2.Saml2AuthnRespone.ReadSecurityToken(字符串标记字符串)ITfoxtec.Identity.Saml2.Saml2AuthnRespone.Read(字符串xml,布尔validateXmlSignature)位于ITfoxtec.Identity.Saml2.Saml2PostBinding.Read(HttpRequest请求、Saml2Request saml2RequestResponse、字符串messageName、布尔validateXmlSignature)位于ITfoxtec.Identity.Saml2.Saml2Binding1.ReadSamlResponse(HttpRequest请求,Saml2Response Saml2Response)位于F:\Dev\ashilon\SsoGovILApi\Controllers\SamlController.cs:line 45中的SsoGovILApi.Controller.SamlController.AssertionConsumerService()位于Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper映射程序、ObjectMethodExecutor执行程序、Object控制器、Object[]参数)位于Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g_Await|12_0(ControllerActionInvoker调用程序,ValueTask1 actionResultValueTask)位于Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g_Await|10_0(ControllerActionInvoker调用程序,任务lastTask,状态next,作用域范围,对象状态,布尔值isCompleted)位于Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed上下文)在Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State&Next,Scope&Scope,Object&State,Boolean&isCompleted)位于Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()---上一位置的堆栈结束跟踪---位于Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g_Await|19_0(ResourceInvoker调用程序,Task lastTask,State next,Scope Scope,Object State,Boolean isCompleted)位于Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g_Logged|17_1(资源调用程序调用程序)位于Microsoft.AspNetCore.Routing.EndpointMiddleware.g_AwaitRequestTask|6_0(端点,任务请求任务,ILogger记录器)位于Microsoft.AspNetCore.Authorization.AuthenticationMiddleware.IInvoke(HttpContext上下文)位于Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.IInvoke(HttpContext上下文)位于Serilog.AspNetCore.RequestLoggingMiddleware.Invoke(HttpContext HttpContext)位于Microsoft.AspNetCore.Builder.Extensions.UsePathBaseMiddleware.IInvoke(HttpContext上下文)位于Microsoft.AspNetCore.Server.IIIS.Core.IISHttpContextOfT1.ProcessRequestAsync()

我查找了错误,发现身份验证上下文可以忽略,一些库提供了此选项,例如:
IgnoreAuthenticationContextInResponse兼容性标志

ITfoxtec图书馆也有办法做到这一点吗?

提前感谢,
ashilon

您可以实现自己版本的Saml2AuthnResponse,并在Saml2SecurityTokenHandler属性上设置自己的Saml2ResponseSecurityTokenHandler实现。

我认为应该可以在您自己的Saml2ResponseSecurityTokenHandler实现中更改身份验证上下文验证。

我自己也遇到了同样的问题,而且Idp发送了一个不兼容的AuthnContextClassRef。至少使用.net内核,可以在不需要自定义Saml2ResponseSecurityTokenHandler的情况下,通过对Saml2AuthnResponse进行最小的更改来避免错误:传递给ReadSecuritytoken/ReadClaimsIdentity的tokenstring可以安全地修改,而不会影响签名验证。Saml2AuthnRespone:中修改的读取方法

var tokenString = assertionElement.OuterXml;
if (this.TokenProcessor != null)
{
tokenString = this.TokenProcessor.ProcessToken(tokenString);
}
Saml2SecurityToken = ReadSecurityToken(tokenString);
ClaimsIdentity = ReadClaimsIdentity(tokenString, detectReplayedTokens);

为一个方法提供一个属性来操作tokenString就可以了。实现我自己的Saml2AuthnRespone似乎有点过头了,由于保护级别的原因,创建一个只替换读取方法的派生类似乎不可行。

作为解决此问题的简单方法,我所做的只是从响应的xml中删除saml:AuthnContextDeclRef元素
这是清理前POC状态下的代码:

public async Task<IActionResult> AssertionConsumerService()
{
var binding = new Saml2PostBinding();
var saml2AuthnResponse = new Saml2AuthnResponse(_config);
var httpRequest = Request.ToGenericHttpRequest();
// Remove AuthnContextDeclRef element
var samlResponseXml = Encoding.UTF8.GetString(Convert.FromBase64String(httpRequest.Form["SAMLResponse"] ?? string.Empty));
var root = XElement.Parse(samlResponseXml);
XNamespace ns = "urn:oasis:names:tc:SAML:2.0:assertion";
root.Element(ns + "Assertion")?.Element(ns + "AuthnStatement")?.Element(ns + "AuthnContext")?.Element(ns + "AuthnContextDeclRef")?.Remove();
httpRequest.Form["SAMLResponse"] = Convert.ToBase64String(Encoding.UTF8.GetBytes(root.ToString()));
binding.ReadSamlResponse(httpRequest, saml2AuthnResponse);
if (saml2AuthnResponse.Status != Saml2StatusCodes.Success)
{
throw new AuthenticationException($"SAML Response status: {saml2AuthnResponse.Status}");
}
binding.Unbind(httpRequest, saml2AuthnResponse);
await saml2AuthnResponse.CreateSession(HttpContext, claimsTransform: ClaimsTransform.Transform);
var relayStateQuery = binding.GetRelayStateQuery();
var returnUrl = relayStateQuery.ContainsKey(RelayStateReturnUrl) ? relayStateQuery[RelayStateReturnUrl] : Url.Content("~/");
return Redirect(returnUrl);
}  

相关内容

  • 没有找到相关文章

最新更新