Troubleshooting!

1. m_safeCertContext is an invalid handle

I got this issue when try to assign a X509SigningCredentials to the custom STSConfiguration.


this.SigningCredentials = new X509SigningCredentials(cert);

Solutions:

Make sure don’t call cert.Reset() before passing the cert to X509SigningCredentials constructor

2. Keyset does not exist

Solutions:

http://stackoverflow.com/questions/602345/cryptographicexception-keyset-does-not-exist-but-only-through-wcf

http://msdn.microsoft.com/en-us/library/aa702621.aspx

3. A potentially dangerous Request.Form value was detected from the client (wresult=”<trust:RequestSecuri…”).

Solutions:

Make sure you have this setting in your web.config (under system.web)


<httpRuntime requestValidationMode="2.0"/>

http://social.msdn.microsoft.com/Forums/en-US/Geneva/thread/b6428ea6-e705-4c66-a6fe-8e9f51f73311

http://volkanuzun.com/blog/post/2010/10/14/A-potentially-dangerous-RequestForm-value-was-detected-from-the-client-(wresult3d3ctrustRequestSecuri).aspx

Generating Federation Metadata using WIF APIs

Just like all the Service Oriented approaches, metadata is the key, for example, with web services, you just have to build the service (using ASMX file or WCF) it will generate the WSDL file for your service automatically, so the client code can easily consume. We expect the same thing with WIF, unfortunately, we cannot just build a STS and then somehow it exposes the federation metadata for that.

Most of the samples in WIF SDK and the Programming WIF book are showing you how to generate the metadata from a Visual Studio template. But there is almost no documentation on how to create the federation metadata manually (or dynamically), especially when you build a custom STS using MVC (hopefully we will have the template for MVC soon, but still not solving the dynamic issue).

WIF itself does provide APIs for this task, below are some very simple codes (I copy most of them from http://netpl.blogspot.com/2011/08/quest-for-customizing-adfs-sign-in-web.html). I just tried to put thing together and see how to use the WIF metadata API. For a more complete sample, please see the link above.


const string _endpoint = "http://yoursts.com";

static void Main(string[] args)
{
 string endpointId = _endpoint;
 EntityDescriptor entityDescriptor = new EntityDescriptor(
 new EntityId(endpointId));

 // Signature, I created a certificate using portecle and installed
 // it under TrustedPeople/CurrentUser
 X509Certificate2 cert =
 CertificateUtil.GetCertificate(
 StoreName.TrustedPeople, StoreLocation.CurrentUser, "CN=HoaSTSCert, C=US");

 entityDescriptor.SigningCredentials = new X509SigningCredentials(cert);

 SecurityTokenServiceDescriptor roleDescriptor = new SecurityTokenServiceDescriptor();

 // required protocols supported
 roleDescriptor.ProtocolsSupported.Add(new Uri(WSFederationMetadataConstants.Namespace));
 roleDescriptor.Contacts.Add(new ContactPerson(ContactType.Administrative));

 // This section is for key descriptor
 SecurityKeyIdentifierClause clause = new X509RawDataKeyIdentifierClause(cert);
 SecurityKeyIdentifier ski = new SecurityKeyIdentifier(clause);
 KeyDescriptor signingKey = new KeyDescriptor(ski);
 signingKey.Use = KeyType.Signing;
 roleDescriptor.Keys.Add(signingKey);

// This section is for endpoint
 string activeSTSUrl = _endpoint;
 EndpointAddress endpointAddress = new EndpointAddress(
 new Uri(activeSTSUrl),
 null,
 null,
 (XmlDictionaryReader)null,
 null);

 // Active endpoint
 roleDescriptor.SecurityTokenServiceEndpoints.Add(endpointAddress);
 // Passive endpoint
 roleDescriptor.PassiveRequestorEndpoints.Add(endpointAddress);

 roleDescriptor.ClaimTypesOffered.Add(new DisplayClaim(ClaimTypes.Role));
 roleDescriptor.ClaimTypesOffered.Add(new DisplayClaim(ClaimTypes.Name));

 entityDescriptor.RoleDescriptors.Add(roleDescriptor);

 // Serialize process...
 MetadataSerializer serializer = new MetadataSerializer();

 //MemoryStream stream = new MemoryStream();
 string fileName = @"FederationMetadata.xml";
 XmlWriter writer = XmlWriter.Create(fileName);
 XmlWriterSettings settings = new XmlWriterSettings();
 settings.Indent = true;

 serializer.WriteMetadata(writer, entityDescriptor);

 writer.Flush();

 Console.WriteLine("done...");
 Console.WriteLine(string.Format("Output: {0}",
 Path.Combine(Environment.CurrentDirectory, fileName)));
}