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

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.

Related

Service certificate and transportwithmessagecredentials in 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...

WCF HTTPS and multiple sites in IIS

I am trying to configure IIS to host one set of binaries in two IIS websites. So we want to be able to access the urls:
http://external.example.com/ADataService
https://external.example.com/ADataService
http://internal.example.com/ADataService
internal.example.com and external.example.com are set up as different IIS sites to allow us to assign them different application pools. However when I added HTTPS support to our web.config, the internal HTTP support stopped working; http://internal.example.com/ADataService now returns the error:
Could not find a base address that matches scheme https for the endpoint with binding CustomBinding. Registered base address schemes are [http].
Here are the details of our web.config
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<bindings>
<customBinding>
<binding name="jsonCustomMapper">
<webMessageEncoding webContentTypeMapperType="Service.JSONCustomMapper, Service" />
<httpTransport manualAddressing="true" />
</binding>
<binding name="httpsjsonCustomMapper">
<webMessageEncoding webContentTypeMapperType="Service.JSONCustomMapper, Service" />
<httpsTransport manualAddressing="true" />
</binding>
</customBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="defaultBehavior">
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Service.Service" behaviorConfiguration="defaultBehavior">
<endpoint address="json" binding="customBinding" bindingConfiguration="jsonCustomMapper" behaviorConfiguration="jsonBehavior" contract="Service.IJSONService" />
<endpoint address="json" binding="customBinding" bindingConfiguration="httpsjsonCustomMapper" behaviorConfiguration="jsonBehavior" contract="Service.IJSONService" />
</service>
</services>
</system.serviceModel>
From what I understand multipleSiteBindingsEnabled="true" and HTTPS do not mix, but I don't understand what resources they would be sharing? If we have internal.example.com and external.example.com hosted in different app pools, I thought they would have process isolation?
seems that adding an HTTPS certificate to the site for "internal.example.com" fixed the issue. Note: without this certificate we were not able to access internal.example.com over either HTTP or HTTPS, with certificate both mechanisms work correctly.

Using X.509 Certificate with UserName clientCredentialType

I am creating a WCF service that requires a proxy username and password, in order to do this I need to provide a Service Certificate for which I have supplied our company Verisign Certificate which is valid.
The problem I am having is whenever I use the following configuration I get a error message "The service certificate is not provided. Specify a service certificate in ServiceCredentials."
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="false" />
<behaviors>
<serviceBehaviors>
<behavior name="WSBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate findValue="devstage1.vcg-online.net" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="TrustedPublisher" />
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Acre.IntegrationService.CustomValidator, Acre.IntegrationService" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Acre.IntegrationService.IntegrationService" behaviorConfiguration="WSBehaviour">
<endpoint address="http://localhost/Acre.IntegrationService/IntegrationService.svc"
binding="wsHttpBinding"
bindingConfiguration="WSBinding"
contract="Acre.IntegrationService.IIntegrationService"
name="WS" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="WSBinding" allowCookies="false">
<security mode="Message">
<message clientCredentialType="UserName" negotiateServiceCredential="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
UPDATED CONFIG
I have installed the certificate in the console using mmc.exe to the following paths
Certificates(Local Computer)/Personal/Certificates/
Certificates(Local Computer)/Trusted Root Certification Authorities/Certificates/
Certificates(Local Computer)/Trusted Publishers/Certificates/
I have searched the interweb and can not find a clear solution to my problem.
Can anyone help?
I have managed to fix the issue, #Rajesh you were correct with the clientCertificate needing to be serverCertificate, that corrected the error with not finding the certificate, thanks for that. The certificate was already installed on the machine for computer user.
The problem with the key set was the certificate did not have the correct account permission set to it. I changed the permisisons to allow the IIS_USRS to have access to the certificate and now it is fixed

WCF service not accessible in Windows Server 2008

I recently built a WCF Service, and now I'm deploying it to Windows Server 2008. Right now, we don't have secure protocol turned on. But we will. I'd like to get it working either way. In the site, I've had Anonymous authentication enabled as well as Forms authentication. The reason I did this was to prevent the authentication popup on the iPad, Android and Internet Explorer. So now they just get to the Login screen. Oh and I did activate WCF in Windows features. If you're also knowledgeable about making this https ready, I'd also like to figure that out. Thanks!!
I'm getting this error when I try pasting in the *.svc PATH into the URL.
System.ServiceModel.ServiceActivationException:
The service
'/WCFServices/Accessioning/QuickDataEntryService.svc'
cannot be activated due to an
exception during compilation
Here is my web.config configuration thus far.
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
<!--<baseAddressPrefixFilters>
<add prefix="http://localhost/" />
</baseAddressPrefixFilters>-->
</serviceHostingEnvironment>
<behaviors>
<endpointBehaviors>
<behavior name="AspNetAjaxBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
</behavior>
<!-- Watch this section when adding a new WCF Service! New behaviors will be added; just delete them and use "ServiceBehavior" -->
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="ServiceBehavior" name="A.LIMS.UI.Web.WCFServices.Accessioning.QuickDataEntryService">
<endpoint behaviorConfiguration="AspNetAjaxBehavior" binding="webHttpBinding"
contract="A.LIMS.UI.Web.WCFServices.Accessioning.QuickDataEntryService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
<!--<service name="A.LIMS.UI.Web.WCFServices.Accessioning.IQuickDataEntryService"
behaviorConfiguration="ServiceBehavior">
<endpoint behaviorConfiguration="AspNetAjaxBehavior"
binding="webHttpBinding"
contract="A.LIMS.UI.Web.WCFServices.Accessioning.IQuickDataEntryService" />
</service>-->
<!-- Watch this section when adding a new WCF Service! Duplicate the "QuickDataEntryService" above for an example, but change the fully qualified name -->
</services>
</system.serviceModel>
I have no clue what caused the exception above, but here was the final verdict. There were a lot of things required for WCF and using an SSL certificate (HTTPS protocol). Pardon the formatting.. I don't like how Stack Overflow sometimes puts the code into a block and sometimes it doesn't.
The following were required for the web.config on HTTPS:
Here are some places that required the "requireSSL" attribute:
<authentication mode="Forms">
<forms loginUrl="Login.aspx" timeout="30" protection="All" requireSSL="true" />
</authentication>
<httpCookies httpOnlyCookies="false" requireSSL="true" domain="" />
Notice the "s" in "httsGetEnabled" below:
<behaviors>
<endpointBehaviors>
<behavior name="AspNetAjaxBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpsGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
Bindings (missing in non-SSL web.config):
<bindings>
<webHttpBinding>
<binding name="webBinding">
<security mode="Transport">
</security>
</binding>
</webHttpBinding>
</bindings>
Services (notice the "s" in "mexHttpsBinding"):
<services>
<service behaviorConfiguration="ServiceBehavior" name="A.LIMS.UI.Web.WCFServices.Accessioning.QuickDataEntryService">
<endpoint behaviorConfiguration="AspNetAjaxBehavior" binding="webHttpBinding" bindingConfiguration="webBinding" contract="A.LIMS.UI.Web.WCFServices.Accessioning.QuickDataEntryService" />
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
Last but not least. I'm not using .NET 4.0, but I did try .NET on a different machine. With .NET 4.0 I couldn't get the WCF services to work without having this configured to the actual URL being used. If there were two domains for the same IP, WCF only worked with the domain in this block inside the system.ServiceModel XML block in the web.config. I did not test https in the .NET 4.0, so I'm assuming the protocol on the URL would be https below:
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
<baseAddressPrefixFilters>
<add prefix="http://subdomain.domain.com/" />
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
Oh, I also had to turn on WCF on the Windows Server 2008 box. And it required a server reboot!

WCF with WSHttpBinding, Message Security, clientCredentialType="UserName" Cerificate SelfHosted Issue

I have created a Service where I need the client to pass the credentials (username and password). This behavior requires a X509 certificate, so i started for development issues with a self-signed one using makecert.exe.
Because I'm so newbie with certificates, i see that this certificate created on the IIS Server Certificates section, I need my service to be self hosted later on a windows service, for testing purposes i use a console host application and a simple winform app client.
So my question is, How do i deploy this certificate? I don't want to use IIS in anyway, I can embed the certificate where i noticed i can export as .pfx file inside the console/windows service host? And how?
I'm posting my service and client config files for help on understanding what I need.
Server Configuration:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="B2B.WCF.Service.B2BService" behaviorConfiguration="wsBehavior">
<endpoint name="WSHttpEndpointB2B"
bindingConfiguration="WSBinding"
address ="http://localhost:8768/ServB2B"
binding="wsHttpBinding"
contract="B2B.WCF.Contracts.IB2BContracts">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="wsBehavior">
<serviceMetadata httpsGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate findValue="MyServerCert" x509FindType="FindBySubjectName"
storeLocation="LocalMachine" storeName="My" />
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="B2B.WCF.Service.UserValidator, B2B.WCF.Service" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="WSBinding">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
Client Configuration:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint name="WSHttpEndpointB2B"
bindingConfiguration="WSBinding" behaviorConfiguration="wsBehavior"
address ="http://localhost:8768/ServB2B"
binding="wsHttpBinding"
contract="B2B.WCF.Contracts.IB2BContracts">
<identity>
<dns value="MyServerCert"/>
</identity>
</endpoint>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="wsBehavior">
<clientCredentials>
<clientCertificate findValue="MyServerCert" x509FindType="FindBySubjectName"
storeLocation="LocalMachine" storeName="My"/>
<serviceCertificate>
<authentication certificateValidationMode="None"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="WSBinding">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
Thanx in advance
Your certificates need to be imported into the Windows Certificate Store on the machine that is hosting your web service (i.e. "the server") and (optionally) on the machine that is using your web service (i.e. "the client", if it is a different machine).
You should use the Microsoft Management Console (MMC) to do this. First, you should set it up according to this article. Then import your certificates according to the steps in this article. Make sure you choose the correct store for the client certificate (i.e. 'Personal') and root certificate (i.e. 'Trusted Root Certification Authorities').
Your web service won't start unless it finds the correct certificates that are referenced in your configuration files. In your case, this is the "MyServerCert" certificate that you want to store in the 'Personal' store.