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

Understand WCF claims-based Security (I)

A lot of information related to WCF Claims-Based security can be found from the web, below are some links

Building a Claims-Based Security Model in WCF
Fundamentals of WCF Security

Understand the WCF Identity Model is one of the key to successfully build a custom security solution. This post is just my notes when I am trying to build a Federated Security System.

Accessing ClaimSets

We access the claimsets from ServiceSecurityContext object

foreach (ClaimSet cs in
   operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets)
{
   // do something
}

Service Authorization Manager

ServiceAuthorizationManager is part of the WCF Identity Model Infrastructure, more details information can be found here. Below is how to use a custom service authorization manager and a simple service authorization manager looks like

<behaviors>
  <servicebehaviors>
    <behavior name="ServiceBehavior">
      <serviceauthorization principalPermissionMode="None"
        serviceAuthorizationManagerType=
          "ServiceAuthorizationManagers.AccessChecker,ServiceAuthorizationManagers" />
      <servicemetadata httpGetEnabled="true"/>
    </behavior>
  </servicebehaviors>
</behaviors>

AccessChecker implementation, CheckAccessCore is the core method, in this implementation, it finds the “name” claim and uses a Roles Provider to do the authorization

public class AccessChecker : ServiceAuthorizationManager
{
   const string NAME_CLAIM = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name";
   private Dictionary<string , string[]> _requirements = null;

   public AccessChecker()
   {
      // initializing...
   }

   protected override bool CheckAccessCore(OperationContext operationContext)
   {
      string header =
         operationContext.RequestContext.RequestMessage.Headers.Action;
      string[] requiredRoles;
      if (!this._requirements.TryGetValue(header, out requiredRoles))
      {
         return false;
      }

      foreach (ClaimSet cs in
         operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets)
      {
         foreach (Claim c in cs)
         {
            if (string.Compare(c.ClaimType, NAME_CLAIM, true) != 0)
               continue;
            foreach (string role in requiredRoles)
            {
               // c.Resource contains the user name
               if (Roles.Provider.IsUserInRole((string)c.Resource, role))
                  return true;
            }
         }
      }
      return false;
   }
}

Enable Windows Authentication in WCF (with SSL)

There is a bug (by design?) in .net framework 3.5 sp1 related to enable Windows Authentication (WCF).
If the client configuration file is missing the identity setting for the endpoint (highlighted), it will always return the follow exception.

System.ServiceModel.Security.MessageSecurityException: The HTTP request is unauthorized with client authentication scheme ‘Negotiate’.

But if you add the identity setting, everything works. The interesting thing is the value of userPrincipalName can be set to anything!

< ?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <system .serviceModel>
      <client>
         <endpoint address=https://enterprises:8020/test
                   binding="basicHttpBinding"
                   bindingConfiguration="SecureTransport"
                   contract="Contracts.IService"
                   name="client_endpoint">
            <identity>
               <userprincipalname value="dummy@whatever"/>
            </identity>
         </endpoint>
      </client>
      <bindings>
         <basichttpbinding>
            <binding name="SecureTransport">
               <security mode="Transport">
                  <transport clientCredentialType="Windows"/>
               </security>
            </binding>
         </basichttpbinding>
      </bindings>
   </system>
</configuration> 

References
http://merill.net/2009/02/microsoft-net-framework-35-sp1-breaks-microsoft-ccf-customer-care-framework/
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=364077

wsDualHttpBinding and port 80

When you’re using the default settings for wsDualHttpBinding, the client will try to listen on port 80 for messages from service, so you will receive an exception (tcp port 80 is being used by another application) if you have IIS running.

Solution for that is to define an explicit address for the client (through the ClientBaseAddress setting) More details can be found here