I have a web service hosted in IIS over https. I am able to connect to the service from a test client application and ger returned results.
I want to look at the certificate used in the request, but the server seems to have no record of this.
I'm doing basicHttpBinding as defined here:
<basicHttpBinding>
<binding name="basicHttpBinding">
<security mode="Transport" />
</binding>
</basicHttpBinding>
When creating my local service proxy in the client code, I attach an x509 cert thusly, with userCerts being a non-empty list of the certs in the local cert store
var service = new WcfBasicServiceClient();
service.ClientCredentials.ClientCertificate.Certificate = userCerts[0];
double randomDouble = service.GetRandomDouble();
Again, the call goes through to the service.
On the server side, I'm attempting to examine the certificate used. However, the ServiceSecurityContext.Current.PrimaryIdentity
is a generic identity. ALso, the OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets
is an empty set. It's as if the server has no knowledge of the certificate used.
var securityContext = ServiceSecurityContext.Current;
var primaryIdentity = securityContext.PrimaryIdentity;
Logger.Info("Primary Identity: " + primaryIdentity);
Logger.Info("auth type: " + primaryIdentity.AuthenticationType);
Logger.Info("name: " + primaryIdentity.Name);
// gets an empty list here
// https://stackoverflow.com/a/7528703/680268
if (OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets == null)
{
Logger.Warn("claimset service configured wrong");
return;
}
if (OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets.Count <= 0)
{
Logger.Warn("claimset empty - service configured wrong");
return;
}
var cert = ((X509CertificateClaimSet)OperationContext.Current.ServiceSecurityContext.
AuthorizationContext.ClaimSets[0]).X509Certificate;
Logger.Info("cert serial num: " + cert.SerialNumber);
Logger.Info("subj name: " + cert.SubjectName);
Logger.Info("thumb print: " + cert.Thumbprint);
Also, on the IIS website settings, I've set "Accept" under SSL settings, but do not have "require SSL" enabled.
What is misconfigured on my service that it is not accepting x509 certs in client requests?
Here is my service's web.config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="httpsBinding" allowCookies="true" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="WcfServiceLibrary1.WcfBasicService">
<endpoint address="" binding="basicHttpBinding" contract="WcfServiceLibrary1.IWcfBasicService" name="basicHttpBinding" bindingConfiguration="httpsBinding">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Edit, I updated my web.config and app.config to specify the client crednetial type of Certificate, but then I get an error as follows when trying to make the call on the client:
ErrorSystem.ServiceModel.Security.MessageSecurityException: The HTTP request was forbidden with client authentication scheme 'Anonymous'. ---> System.Net.WebException: The remote server returned an error: (403) Forbidden.
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
--- End of inner exception stack trace ---
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(HttpWebRequest request, HttpWebResponse response, WebException responseException, HttpChannelFactory`1 factory)
at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory`1 factory, WebException responseException, ChannelBinding channelBinding)