Service certificate and transportwithmessagecredentials in wcf - wcf

I have a WCF service which I want to authentciate using client certificate which I can correctly achieve.My confusion is with securing the data correctly so even if someone intercepts cannot decrypt it.The service runs on https and i am using the below web.config in the service part .The client can be any local worker process or web form or anything.So the question is the below settings the correct way top secure it .
On the client side I configure the service certificate as clientChannelservice.ClientCredentials.ServiceCertificate.DefaultCertificate = GetServiceCertificate(); but it does not make a different even if I do or do not provide this service certificate .Jo just wondering that whether I have my service secured correctly or not since when I write the data to the logs I see the return values is not encoded and is transferred as such.Is it because it's protected by SSL or what .If someone can clear my confusion.
<system.serviceModel>
<diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="true"
logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />
</diagnostics>
<services>
<service behaviorConfiguration="customBehavior" name="CertProtectedWCF.Service1">
<endpoint
address="https://localhost:123/Service1.svc"
binding="wsHttpBinding"
bindingConfiguration="customWsHttpBinding"
contract="CertProtectedWCF.IService1" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="customWsHttpBinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="Certificate" negotiateServiceCredential="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="customBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceCredentials>
<clientCertificate>
<authentication
certificateValidationMode="PeerTrust"
revocationMode="NoCheck" />
</clientCertificate>
<serviceCertificate
findValue="ACS2SigningCertificate"
x509FindType="FindBySubjectName"
storeLocation="LocalMachine"
storeName="My" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="false" />
</system.serviceModel>

The client gets the server certificate as part of SSL protocol. With a self-signed certificate the client cannot verify that they got the right thing by using a CA chain. But it certainly can use that certificate to decrypt...

Related

Configure Client Certificates on WCF service in Azure WebApp

I have a WCF service that I want to configure with Transport Security and Client Certificates. I have this working on my local IIS instance, but having troubles configuring it in an Azure Web App.
Here are som snippets from the web.config:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<behavior name="ApiBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<clientCertificate>
<certificate
findValue="<Thumbprint>"
storeLocation="CurrentUser"
storeName="My"
x509FindType="FindByThumbprint" />
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<bindings>
<wsHttpBinding>
<binding name="apiBindingSecure" textEncoding="utf-8">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="ApiService" behaviorConfiguration="ApiBehavior">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="apiBindingSecure" contract="IApiService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
When I call the service I get the following error:
The SSL settings for the service 'SslRequireCert' does not match those of the IIS 'None'.
I found that in IIS this relates to the SSL Settings -> Client certificates -> Accept setting:IIS SSL seettings
However in Azure this has to be done through a web.config setting:
<location path="BdoApiService.svc" >
<system.webServer>
<security>
<access sslFlags="SslRequireCert,SslNegotiateCert" />
</security>
</system.webServer>
</location>
I tried different combinations of settings: "Ssl"; "Ssl,SslRequireCert,SslNegotiateCert"; "SslNegotiateCert", etc.
But when I set sslFlags, I always get the following error in the browser:
The page cannot be displayed because an internal server error has occurred.
What can I do to get this working?

Cannot find the X.509 certificate in WCF service hosted in Azure

I'm trying to make a certificate based authentication platform for my WCF service, and I've followed all the tutorials and made my certificate and installed it in IIS and everything works great running locally, but as soon as I publish it to Azure I get the exception
Cannot find the X.509 certificate using the following search criteria: StoreName 'My', StoreLocation 'LocalMachine', FindType 'FindBySubjectName', FindValue 'CN=tempCert'.
I've uploaded the .pvk to azure
I've put it in my settings
And I made sure to add it to my app settings for the website
However it still does not work once I publish it. This is my configuration in my Web.Config file for the service model
<system.serviceModel>
<services>
<service name="clientSecurity">
<endpoint binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding"
name="wsHttpEndpoint" contract="uConnect.Web.IUConnectService" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="wsHttpEndpointBinding">
<security>
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client />
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate findValue="CN=tempCert" x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
And as I mentioned it works perfectly when I run it locally, it only throws an exception once I publish it to azure. Any help would be welcome since I've been trying to fix this for some time now.
You need to specify the certificate store, in Azure WebApps - these get loaded in currentUser. Add storeLocation="CurrentUser" storeName="My" to the serviceCertificate element.

Securing WCF with basichttpbinding

I am using basicHttpBinding,message security and x509 certificate in my WCF service(.Net Framework 4.0).The config looks like this:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<serviceCertificate findValue="MyWebSite" storeLocation="LocalMachine"
storeName="My" x509FindType="FindBySubjectName" />
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="CToSave.ValidateClient, CToSave" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
<standardEndpoints>
<webScriptEndpoint>
<standardEndpoint crossDomainScriptAccessEnabled="True"/>
</webScriptEndpoint>
</standardEndpoints>
<services>
<service behaviorConfiguration="ServiceBehavior" name="CToSave.MyService">
<endpoint address="" binding="basicHttpBinding" contract="CToSave.IMyService" bindingConfiguration="BindingConfig"/>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="BindingConfig" openTimeout="00:50:00" sendTimeout="00:50:00" receiveTimeout="00:50:00" closeTimeout="00:50:00" maxReceivedMessageSize="2147483647">
<security mode="Message">
<message clientCredentialType="Certificate"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
A PHP client will be consuming this service. In order to consume it,will the client need a certificate at his end?I would prefer that the client doesnt have to generate a certificate.
If the clinet has to get a certificate,will my config change? If yes,what changes will I have to make?
I have read dozens of articles on basihttpbinding+security but none of them indicate anything about the certificate on the client-side. Please help.
Yes, client needs a certificate because of this:
<security mode="Message">
<message clientCredentialType="Certificate"/>
</security>
In general client does not generate its own certificate but gets it from agree provider (can be cert authority in the organization or a public authority or service owner).
In any case you need a good WS-Security library for PHP since you need to generate the message format WCF expects (this is message level security).
Actually it is possible to validate certificate by identity on a client

WCF Service: behavior with serviceCredentials with certificate - how should I configure it for Azure?

I have simple WCF Service Service1 with the following config:
<behaviors>
<serviceBehaviors>
<behavior name="SecuredBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>
<serviceCredentials type="System.ServiceModel.Description.ServiceCredentials">
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WCFS.Service1,WCFS"/>
<serviceCertificate findValue="BasicWCFCert" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
<windowsAuthentication includeWindowsGroups="false"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="SecuredWsHttpBinding">
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="WCFS.Service1" behaviorConfiguration="SecuredBehavior">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="SecuredWsHttpBinding"
name="End1" contract="WCFS.IService1" />
</service>
</services>
So on my development machine I'm using this service with certificate "BasicWCFCert" stored in LocalMachine in "My" (Personal) location.
How should I change it before publishing this service in Azure?
How can I tell Service1 to use one of certificates uploaded to Azure?
Have you tried attaching the cert in the role configuration screen as show below?
You can get the thumbprint by running certmgr.msc and going to the relevant certificate.

WCF rejects messages with additional signed elements

We have a WCF 4.0 service over https that allows the client to sign the message to identify themselves. We can then use the cert to give the client the proper rights on the back end. This works fine when a WCF 4.0 client sends the request, but when a non-WCF attempts to send the request, it fails with the following: CryptographicException: Unable to resolve the '#Id-{Guid goes here}' URI in the signature to compute the digest. Upon inspecting the clients request, this failure occurs whenever anything more than the To and Timestamp nodes are signed. The non-WCF client expects to sign the body, Action, MessageID, and ReplyTo sections. Can WCF be configured to expect and allow these signatures or, better yet, allow them if they are there but don't fault if they aren't?
Service config file:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<extensions>
<behaviorExtensions>
<add name="wsdlExtensions" type="MyWCFElements" />
</behaviorExtensions>
<bindingElementExtensions>
<add name="httpsViaProxyTransport" type="MyWCFElements" />
</bindingElementExtensions>
</extensions>
<behaviors>
<endpointBehaviors>
<behavior name="WsdlBehavior">
<wsdlExtensions singleFile="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="WebServicesServiceBehavior">
<serviceMetadata httpsGetEnabled="false" httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceAuthenticationManager serviceAuthenticationManagerType="MyServiceAuthenticationManager" />
<serviceAuthorization serviceAuthorizationManagerType="MyServiceAuthorizationManager" />
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyUserNameValidator" />
<clientCertificate>
<authentication certificateValidationMode="PeerTrust" trustedStoreLocation="LocalMachine" />
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="SignedWebServicesF5BindingConfig">
<textMessageEncoding />
<security authenticationMode="CertificateOverTransport" allowInsecureTransport="true" requireDerivedKeys="false" securityHeaderLayout="Lax" />
<httpsViaProxyTransport />
</binding>
</customBinding>
</bindings>
<services>
<service behaviorConfiguration="WebServicesServiceBehavior" name="WebService">
<endpoint address="signed" binding="customBinding" behaviorConfiguration="WsdlBehavior" bindingConfiguration="SignedWebServicesF5BindingConfig" contract="IWebServicesContract" name="SignedWebServices"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
After working with Microsoft, the answer seems to be that you cannot use CertificateOverTransport and sign the message body, which is what our client was attempting to do. We moved to MutualCertificateDuplex and changed the ProtectionLevel of our response to ProtectionLevel.None (since we aren't interested in signing the response). We're now able to receive a request and get a response over https, so we can still rely on the transport for encryption while the security of the message is maintained at the message level, not the transport level.
Hope this helps someone else, this seems to be fairly common in WCF interop scenarios but there isn't a ton of guidance about this on the web.