WIF in depth: Validating Security Tokens outside of WIF
Sometimes it is necessary to validate SecurityTokens issued by an Windows Identity Foundation (WIF) driven Identity Provider (IdP) in a Service Provider (SP) application that has no reference to WIF.
When it came to validating the xml signature of the token I ran into an exception on calling the CheckSignature() method of the SignedXml class:
System.Security.Cryptography.CryptographicException: SignatureDescription could not be created for the signature algorithm supplied.
What this exception message basically states is that it does not know the specified signature algorithm. The name of this algorithm is set by the corresponding xml attribute in the raw token data as http://www.w3.org/2001/04/xmldsig-more#rsa-sha256.
The problem here is that this signature algorithm is not supported by the core .NET framework (http://blogs.msdn.com/b/shawnfa/archive/2008/08/25/using-rsacryptoserviceprovider-for-rsa-sha256-signatures.aspx). I found some blog posts on how to activate support for this algorithm, but it did not really work out for me.
So after I failed trying to adjust the code of the SP application to fit WIF, I had a look at the other side of the pipe: my Identity Provider implemented using WIF:
I did not tell WIF to use RSA-SHA256 as signature algorithm anywhere and my X.509 certificate also used RSA-SHA1. So obviously this algorithm must be set somewhere inside of WIF as default value. And indeed it is: If you do not explicitly specify the signature algorithm when calling a constructor of the X509SigningCredentials it is set to RSA-SHA256 by default:
public X509SigningCredentials(X509Certificate2 certificate, SecurityKeyIdentifier ski) : this( new X509SecurityToken(certificate), ski, "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "http://www.w3.org/2001/04/xmlenc#sha256") { }
So the solution to this problem is to use another constructor of the X509SigningCredentials class on setting the SigningCredentials of the SecurityTokenService.
An example:
this.SigningCredentials = new X509SigningCredentials( certificate, "http://www.w3.org/2000/09/xmldsig#rsa-sha1", "http://www.w3.org/2000/09/xmldsig#sha1");
Another issue I was facing on manually validating the xml signature of a security token is that the default SignedXml class was not able to find the Id element of the security token. The following article did the trick for me: http://blogs.msdn.com/b/shawnfa/archive/2004/04/05/108098.aspx