在Windows Identity Foundation中调试SAML令牌分析器错误

时间:2014-03-24 04:17:22

标签: asp.net-mvc-4 wif saml-2.0 ws-federation

我正在寻找在使用WIF时解决SAML令牌解析错误的方法。我对这项技术很陌生,所以我可能会错过一些明显的技术。

我编写了一个使用WS-Federation进行外部身份验证的示例MVC应用程序。 我在本地使用ThinkTecture服务器试用它,它就像一个魅力。但是当我尝试使用外部STS服务器(CA CloudMinder)时,我在WIF中遇到错误:

Application Error: 'Element' is an invalid XmlNodeType. System.Xml.XmlException XmlException System.Xml.XmlException: 'Element' is an invalid XmlNodeType.
   at System.Xml.XmlReader.ReadEndElement()
   at System.IdentityModel.Tokens.Saml2SecurityTokenHandler.ReadAssertion(XmlReader reader)
   at System.IdentityModel.Tokens.Saml2SecurityTokenHandler.ReadToken(XmlReader reader)
   at System.IdentityModel.Tokens.SecurityTokenHandlerCollection.ReadToken(XmlReader reader)
   at System.IdentityModel.Services.TokenReceiver.ReadToken(String tokenXml, XmlDictionaryReaderQuotas readerQuotas, FederationConfiguration federationConfiguration)
   at System.IdentityModel.Services.WSFederationAuthenticationModule.SignInWithResponseMessage(HttpRequestBase request)
   at System.IdentityModel.Services.WSFederationAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs args)
   at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) Void ReadEndElement()    at System.Xml.XmlReader.ReadEndElement()
   at System.IdentityModel.Tokens.Saml2SecurityTokenHandler.ReadAssertion(XmlReader reader)
   at System.IdentityModel.Tokens.Saml2SecurityTokenHandler.ReadToken(XmlReader reader)
   at System.IdentityModel.Tokens.SecurityTokenHandlerCollection.ReadToken(XmlReader reader)
   at System.IdentityModel.Services.TokenReceiver.ReadToken(String tokenXml, XmlDictionaryReaderQuotas readerQuotas, FederationConfiguration federationConfiguration)
   at System.IdentityModel.Services.WSFederationAuthenticationModule.SignInWithResponseMessage(HttpRequestBase request)
   at System.IdentityModel.Services.WSFederationAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs args)
   at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

这显然与正在发送回的实际SAML令牌的格式有关。 我想我可以按如下方式捕获令牌并记录下来:

void WSFederationAuthenticationModule_SignInError(object sender, ErrorEventArgs e)
{                           
  var message = FederatedAuthentication.WSFederationAuthenticationModule.GetSignInResponseMessage(
     new HttpRequestWrapper(HttpContext.Current.Request));
}

我无法共享实际令牌本身。但我想知道,如果您知道如何解决这些错误的任何方法 - 例如手动验证令牌的某种方式。

任何建议表示赞赏。

1 个答案:

答案 0 :(得分:3)

好的,所以我使用的一种技术对于缩小问题非常有用,就是子类化并注册我自己的Saml2SecurityTokenHandler

这有助于我验证问题是SAML令牌中元素的顺序 - 显然,当涉及到SAML断言中的Signature元素的位置时,WIF非常宽容 - 它要求它紧跟在Issuer元素之后。< / p>

public class ForgivingSaml2SecurityTokenHandler : Saml2SecurityTokenHandler
{
    public override SecurityToken ReadToken(XmlReader reader)
    {
        reader = SanitizeToken(reader);
        return base.ReadToken(reader);
    }

    XmlReader SanitizeToken(XmlReader reader)
    {             
        var xmlDoc = new XmlDocument();
        xmlDoc.Load(reader);
        var ns = new XmlNamespaceManager(xmlDoc.NameTable);
        ns.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");
        ns.AddNamespace("sa", "urn:oasis:names:tc:SAML:2.0:assertion");
        var issuerNode = xmlDoc.SelectSingleNode("//sa:Issuer", ns);
        var signatureNode = xmlDoc.SelectSingleNode("//ds:Signature", ns);
        signatureNode.ParentNode.InsertAfter(signatureNode, issuerNode);
        string sanitizedToken = xmlDoc.InnerXml;            
        return new XmlTextReader(new StringReader(sanitizedToken));           
    }    
}

所以上面的内容并不能真正解决问题,因为修改令牌会导致签名检查失败,但它允许我验证订单确实是问题,因为我能够修改正确的令牌并使其成为现实令牌。失败的方式与有问题的令牌表现相同 - 显然在WIF签名检查之前正在执行令牌结构检查。

注册我在web.config文件中注册后使用的子类标记处理程序:

<identityConfiguration saveBootstrapContext="true">
  <securityTokenHandlers>
    <remove type="System.IdentityModel.Tokens.Saml2SecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
    <add type="ExploringSaml.ForgivingSaml2SecurityTokenHandler, ExploringSaml" ></add>        
  </securityTokenHandlers>