CAB
CAB

Reputation: 1148

Failure validating SAML 2 assertion using Windows Identity Foundation

I'm trying to replace a custom SAML 2 library, for which I have no source code, with the WIF, for which I have no experience. I'm having no luck finding example code, so I'm working trial-and--error style. The code seems to almost work, but I get a very terse The signature verification failed. message and nothing else.

For inputs to this process I have an X509 certificate and a base-64 encoded, SAML 2 assertion.

My code is;

// Load X509 certificate
string rootPath = System.AppDomain.CurrentDomain.BaseDirectory;
string certFilePath = ConfigurationManager.AppSettings["SAMLCertLocation"];
certFilePath = Path.Combine(rootPath, certFilePath);
msg = string.Format("SAMLCertLocation: [{0}]", certFilePath);
Trace.TraceInformation(msg);
X509Certificate2 cert = new X509Certificate2(certFilePath, String.Empty);

// build token handler configuration
List<System.IdentityModel.Tokens.SecurityToken> serviceTokens = new List<System.IdentityModel.Tokens.SecurityToken>();
serviceTokens.Add(new System.IdentityModel.Tokens.X509SecurityToken(cert));

ConfigurationBasedIssuerNameRegistry issuers = new ConfigurationBasedIssuerNameRegistry();
issuers.AddTrustedIssuer(cert.Thumbprint, cert.Issuer);

SecurityTokenHandlerConfiguration config = new SecurityTokenHandlerConfiguration()
{
    AudienceRestriction = { AudienceMode = AudienceUriMode.Never },
    CertificateValidator = X509CertificateValidator.None,            
    // RevocationMode = X509RevocationMode.NoCheck,             // no such property
    IssuerNameRegistry = issuers,
    MaxClockSkew = TimeSpan.FromMinutes(5),
    ServiceTokenResolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(serviceTokens.AsReadOnly(), false)
};

// extract the assertion from the request
byte[] data = Convert.FromBase64String(reqstr);
string assertion = Encoding.UTF8.GetString(data);
Trace.TraceInformation(assertion);

// read and validate the assertion
Saml2SecurityTokenHandler handler = new Saml2SecurityTokenHandler();
handler.Configuration = config;
bool canReadToken = handler.CanReadToken(XmlReader.Create(new StringReader(assertion)));
msg = string.Format("CanReadToken [{0}]", canReadToken);
Trace.TraceInformation(msg);
if (canReadToken)
{
    try
    {
        System.IdentityModel.Tokens.SecurityToken token = handler.ReadToken(XmlReader.Create(new StringReader(assertion)));
        ClaimsIdentityCollection claims = handler.ValidateToken(token);
        msg = string.Format("SAML Claims [{0}]", claims.ToString());
        Trace.TraceInformation(msg);
    }
    catch (Exception e)
    {
        msg = string.Format("Validation Exception [{0}]", e.Message);
        Trace.TraceInformation(msg);
    }
}

The error I'm getting out is;

2016-09-15T19:34:39  PID[6504] Information CanReadToken [True]
2016-09-15T19:34:39  PID[6504] Information Validation Exception [ID6013: The signature verification failed.]
2016-09-19T13:13:13  PID[11912] Information Validation Exception [System.Security.Cryptography.CryptographicException: ID6013: The signature verification failed.
    at Microsoft.IdentityModel.Protocols.XmlSignature.SignedXml.VerifySignature(HashAlgorithm hash, AsymmetricSignatureDeformatter deformatter, String signatureMethod)
    at Microsoft.IdentityModel.Protocols.XmlSignature.SignedXml.StartSignatureVerification(SecurityKey verificationKey)
    at Microsoft.IdentityModel.Protocols.XmlSignature.EnvelopedSignatureReader.OnEndOfRootElement()
    at Microsoft.IdentityModel.Protocols.XmlSignature.EnvelopedSignatureReader.Read()
    at System.Xml.XmlReader.ReadEndElement()
    at Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ReadAssertion(XmlReader reader)
    at Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ReadToken(XmlReader reader)
    at AXAWeb.Code.Saml20Login.Saml20Login.SamlLogon(String samlString, String absoluteUrl) in Saml20Login.cs:line 189]

The signature section from the assertion is this;

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
  <SignedInfo>
    <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
    <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
    <Reference URI="#SAML-a964f232-77ab-40d1-a74a-f85dfe10f57d">
      <Transforms>
        <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
        <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
      </Transforms>
      <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
      <DigestValue>B9q+BrqH+Fq74R8eCqd+Vd+vKkw=</DigestValue>
    </Reference>
  </SignedInfo>
  <SignatureValue>...snip for brevity...</SignatureValue>
  <KeyInfo>
    <X509Data>
      <X509Certificate>...snip for brevity...</X509Certificate>
    </X509Data>
    <X509Data>
      <X509IssuerSerial>
        <X509IssuerName>CN=Entrust Certification Authority - L1K, OU="(c) 2012 Entrust, Inc. - for authorized use only", OU=See www.entrust.net/legal-terms, O="Entrust, Inc.", C=US</X509IssuerName>
        <X509SerialNumber>1356031830</X509SerialNumber>
      </X509IssuerSerial>
    </X509Data>
  </KeyInfo>
</Signature>

I expect I'm missing something in configuration, so I inserted changes based on information in this question. It didn't change my results, however.

Does anyone with experience know what I need to add to make this work?

Upvotes: 0

Views: 2607

Answers (2)

Thuan
Thuan

Reputation: 1628

A very annoying problem of WIF's signature validation is that it uses an internal implementation of SignedXml which doesn't support tracing. For the record, the public System.Security.Cryptography.Xml.SignedXml has support for tracing and thus it is easier to find out what goes wrong. Anyway, in my experience, I would suggest you check if your assertion xml contain white spaces. If yes, you need to use the PreserveWhiteSpaces setting when reading it into an XmlReader.

Edited: Two other things to check is if you wire up the right certificate for verifying signature, and if you can verify signature for the assertion using System.Security.Cryptography.Xml.SignedXml: https://msdn.microsoft.com/en-us/library/ms229950(v=vs.110).aspx

Upvotes: 4

rbrayb
rbrayb

Reputation: 46720

Have a look at active-directory-dotnet-webapp-wsfederation.

Essentially rip out the SAMl stuff and use the OWIN Nuget Ws-Fed package.

Of course, this assumes that your IDP supports WS-FEd?

Upvotes: 0

Related Questions