WCF service and custom CA - c#

I've created my custom Certificate Authority (CA) using openssl. Then I've created certificated using the previous one and the request from IIS. So now I have chain of certificates. Then I've bound the second one to my WCF service and every thing is fine. Then on client I've installed my CA certificate in Trusted Root Certification Authority to make it able to recognize my custom certificate.
My WCF service currently run on simple http connection.
Server side:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="SyncWcfServices.MainServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="ExtendedMaxSize" maxReceivedMessageSize="2147483647">
<security mode="None">
<transport clientCredentialType="None"></transport>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="SyncWcfServices.MainService" behaviorConfiguration="SyncWcfServices.MainServiceBehavior">
<endpoint address="/syncService.svc" binding="wsHttpBinding" bindingConfiguration="ExtendedMaxSize" contract="SyncWcfServices.IMainService"></endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Client side:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IMainService" maxReceivedMessageSize="2147483647" sendTimeout="00:10:00">
<security mode="None" />
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/SyncService/SyncService.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IMainService"
contract="SyncServiceReference.IMainService" name="WSHttpBinding_IMainService" />
</client>
</system.serviceModel>
So, I need to change this settings to support SSL connection. I've read a lot of post how to do it but there always using 2-way certification check that mean server must check client certificate and client must check server certificate. But I only want client to check server certificate using CA that I installed. And server will check with ordinary credentials (username, password) as it was before. I think that I have to change the security mode to Transport in both sides and server mex endpoint to mexHttpsBinding but what should I do next? Please help to resolve it.
Thanks you all!

Finally I found the correct way! So server side:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="SyncWcfServices.MainServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate
findValue = "*.mydomain.com"
storeLocation = "LocalMachine"
storeName = "My"
x509FindType = "FindBySubjectName"
/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="ExtendedMaxSize" maxReceivedMessageSize="2147483647">
<security mode="Transport">
<transport clientCredentialType="None"></transport>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="SyncWcfServices.MainService" behaviorConfiguration="SyncWcfServices.MainServiceBehavior">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="ExtendedMaxSize" contract="SyncWcfServices.IMainService"></endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"></endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8095/Design_Time_Addresses/SyncWcfServices/MainService/" />
</baseAddresses>
</host>
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Client Side:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name = "ServiceCertificate">
<clientCredentials>
<serviceCertificate>
<authentication certificateValidationMode = "ChainTrust"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="ExtendedMaxSize" maxReceivedMessageSize="2147483647">
<security mode="Transport">
<transport clientCredentialType="None"></transport>
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://localhost/SyncService/SyncService.svc"
binding="wsHttpBinding" bindingConfiguration="ExtendedMaxSize"
behaviorConfiguration = "ServiceCertificate"
contract="SyncServiceReference.IMainService" name="WSHttpBinding_IMainService">
</endpoint>
</client>
</system.serviceModel>
Hope it will help someone!
Also please look at "Programming WCF Services" (4th edition) book by Juval Lowy & Michael Montgomery. It's a great book!

Related

WCF-TransportWithMessageCredential The HTTP request is unauthorized with client authentication scheme 'Anonymous'

I'm trying to configure WCF authentication with UserName but without success, I have tried a a lot of solution that I found already, but nothing seem to work for me.
The HTTP request is unauthorized with client authentication scheme
'Anonymous'. The authentication header received from the server was
'Negotiate,NTLM,Basic realm="localhost"'.
Server setting
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="basicHttpBindingConfiguration">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" negotiateServiceCredential="false" />
<transport clientCredentialType="None" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="Namespace.Service" behaviorConfiguration="wsHttpBehavior">
<endpoint binding="wsHttpBinding" bindingConfiguration="basicHttpBindingConfiguration" name="Soap" bindingNamespace="/WebServices" contract="Namespace.IService">
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" name="mex" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="wsHttpBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="UserNamePasswordValidator, WebApplication" />
<!--<serviceCertificate findValue="ServiceModelSamples-HTTPS-Server" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />-->
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
On the client side
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="Soap">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://localhost:85/WebServices/Service.svc"
binding="wsHttpBinding" bindingConfiguration="Soap" contract="ServiceReference1.IService"
name="Soap" />
</client>
</system.serviceModel>
Here is my IIS config
Most of solution that I found use Windows Transport, I need Authentication only through Username.
I check this :
https://blog.sandervanlooveren.be/posts/securing-a-wcf-service-with-username-and-password/
https://learn.microsoft.com/en-us/dotnet/framework/wcf/samples/ws-transport-with-message-credential
I have tried security mode="Message" and security mode="TransportWithMessageCredential" without success
My client code look like :
// Instantiate the proxy
var proxy = new ServiceClient();
proxy.ClientCredentials.UserName.UserName = "username";
proxy.ClientCredentials.UserName.Password = "password";
Please can anyone check my config and tell what I'm setting wrong ?
Edit:
This is a Service inside an ASP.Net MVC5 App, Can this also be a problem ?
There might be something amiss with the customUserNamePasswordValidatorType property string.It is usually in the following form
customUserNamePasswordValidatorType="Namespace.MyCustUserNamePasswordVal,Namespace"
Can you access the WSDL of hosting service? Also, turning on the anonymous authentication is enough, unnecessary to enable others authentication.
Here is my configuration, I used simplified configuration which be supported in WCF4.5, wish it is useful to you.
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceCredentials>
<userNameAuthentication customUserNamePasswordValidatorType="WcfService1.CustUserNamePasswordVal,WcfService1" userNamePasswordValidationMode="Custom"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding>
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<protocolMapping>
<add binding="wsHttpBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Feel free to let me know If there is anything I can help with.

WCF - HTTPS - Transport security works but message security throws exception on application startup

I have a WCF self hosted server (a console application which registers the wcf contract with castle ioc container AsWcfService). I need it to work securely over https.
When I configure the server to use wsHttpBinding with security mode=Transport and clientCredentialsType=None, everthing works fine.
The configurations looks as follows:
Transport Security Configuration
<behaviors>
<serviceBehaviors>
<behavior name="secureBehavior">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" httpsHelpPageEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="secureBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" sendTimeout="01:00:00">
<security mode="Transport" >
<transport clientCredentialType="None"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="service" behaviorConfiguration="secureBehavior">
<endpoint binding="wsHttpBinding" bindingConfiguration="secureBinding" contract="Contract.Service" />
<host>
<baseAddresses>
<add baseAddress="https://domain-name:port-number/"/>
</baseAddresses>
</host>
</service>
</services>
The above works fine.
Message Security Configuration
<behaviors>
<serviceBehaviors>
<behavior name="secureBehavior">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" httpsHelpPageEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="secureBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" sendTimeout="01:00:00">
<security mode="Message" >
<message clientCredentialType="None"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="service" behaviorConfiguration="secureBehavior">
<endpoint binding="wsHttpBinding" bindingConfiguration="secureBinding" contract="Contract.Service" />
<host>
<baseAddresses>
<add baseAddress="https://domain-name:port-number/"/>
</baseAddresses>
</host>
</service>
</services>
With message security configuration, however, when I try to start the server I get the following exception:
Could not find a base address that matches scheme http for the
endpoint with binding WSHttpBinding. Registered base address schemes
are [https]. System.InvalidOperationException: Could not find a base
address that matches scheme http for the endpoint with binding
WSHttpBinding. Registered base address schemes are [https].
I can't find the reason for this error anywhere I look.
An explanation would be highly appreciated.

How to pass Username Credential WCF through Castle Windsor

I have a problem to pass username and password through Castle Windsor register by using custom WCF authentication.
I have a Web service configuration like below :
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsSecureBinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="defaultProfile" name="GS1.CSSM.XMLGenerate.WebService.Implementation.XMLGenerateService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsSecureBinding" name="wsSecureService" contract="GS1.CSSM.XMLGenerate.WebService.Interface.IXMLGenerateService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="defaultProfile">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="GS1.CSSM.XMLGenerate.WebService.ServiceAuthenticator, GS1.CSSM.XMLGenerate.WebService"/>
</serviceCredentials>
</behavior>
<behavior name="noAuthentication">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<!--<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>-->
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
This is the Container Setup :
var container = new WindsorContainer();
container.AddFacility()
.Register(
Component.For<IXMLGenerateService>()
.ImplementedBy<XMLGenerateServiceClient>()
.AsWcfClient(
new DefaultClientModel
{
Endpoint =
WcfEndpoint.FromConfiguration("wsSecureService")
}.Credentials(new UserNameCredentials("zul", "password"))));
And this is client config file :
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsSecureService">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://localhost:44302/Service/XMLGenerateService.svc" binding="wsHttpBinding" bindingConfiguration="wsSecureService" contract="XMLGenerateService.IXMLGenerateService" name="wsSecureService" />
</client>
</system.serviceModel>
I got this error "Additional information: The username is not provided. Specify username in ClientCredentials." once I tried to call method from the service.
Any ideas?
I will answer it by myself :)
here it is how i resolved that issue
container.Kernel.AddFacility<WcfFacility>()
.Register(Component.For<IXMLGenerateService>()
.AsWcfClient(new DefaultClientModel
{
Endpoint = WcfEndpoint.FromConfiguration("wsSecureService")
}.Credentials(new UserNameCredentials("zul", "password"))));
_smXMLGenerateService = container.Resolve<IXMLGenerateService>();
Hopefully, it can help anyone with the same issue.

WCF service is working on dev server but on production it is not woking

I have a .net client and I am consuming the WCF service and able to do that sucessfully. but when i try to post that on our production I am not able to consume the same service. Below is my web.config :
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyBehavior">
<useRequestHeadersForMetadataAddress></useRequestHeadersForMetadataAddress>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="TestProject.Implementations.AuthenticateUser,TestProject"/>
<serviceCertificate findValue="localhost" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="TestProject.Implementations.ServiceCustom" behaviorConfiguration="MyBehavior">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="SampleServiceBinding" contract="TestProject.Interfaces.IServiceCustom"></endpoint>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex"></endpoint>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="SampleServiceBinding">
<security mode ="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
and also I want to make my service HTTPS enabled.
I get below errormessage:
There was no endpoint listening at http://url.com that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
This error clearly suggest that the WCF service you are trying to access is not clearly hosted, or the address you are using to connect to is not pointing to the service, make sure by using the address in a browser you are able to access that service.
If you are able to access the service , check your client application web.config and find out the end point details for that service. If the endpoint url is mismatched you may get this error.
I fixed the error and below is the web config code:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyBehavior">
<useRequestHeadersForMetadataAddress></useRequestHeadersForMetadataAddress>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="TestProject.Implementations.AuthenticateUser,TestProject"/>
<serviceCertificate findValue="localhost" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="TestProject.Implementations.Test" behaviorConfiguration="MyBehavior">
<endpoint address="http://rul" binding="wsHttpBinding" bindingConfiguration="SampleServiceBinding" contract="TestProject.Interfaces.Test"></endpoint>
<endpoint address="https:url" binding="wsHttpBinding" bindingConfiguration="SampleServiceBindingHttps" contract="TestProject.Interfaces.ITest"></endpoint>
<endpoint contract="IMetadataExchange" binding="mexHttpsBinding" address="mex"></endpoint>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="SampleServiceBinding">
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
<binding name="SampleServiceBindingHttps">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
I changed the security mode to TransportWithMessageCredential mode and change few config like binding = "mexHttpsBinding"

SSL On REST Endpoint in C#?

I have SSL working for my SOAP endpoint.
But as soon as I enable my REST endpoint, it throws a fit:
Could not find a base address that matches scheme http for the endpoint with binding WebHttpBinding. Registered base address schemes are [https].
My app.config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="IIncreasedBufferSize" maxBufferSize="1024000"
maxReceivedMessageSize="1024000">
<readerQuotas maxArrayLength="1024000" />
<security mode ="Transport">
<transport clientCredentialType= "None" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="WCFBehaviourSSL"
name="IWCF.IService">
<endpoint name="soap" address="soap" binding="basicHttpBinding" bindingConfiguration="IIncreasedBufferSize"
contract="IWCF.IServices">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint name="rest"
address="rest"
binding="webHttpBinding"
contract="IWCF.IServices"
behaviorConfiguration="REST" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/WcfServiceLibrary2/Service1/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="REST">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="WCFBehaviourSSL">
<serviceMetadata httpGetEnabled="False" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
I found this question: REST WCF Service Over SSL
But rest assured, None of the answers provided are of use.
I have certificates, and it does work with SSL using the SOAP end point. (when rest endpoint is commented out).
I was missing a WebHTTPBinding, that uses Transport security:
<webHttpBinding>
<binding name ="REST SSL">
<security mode ="Transport">
<transport clientCredentialType= "None" />
</security>
</binding>
</webHttpBinding>
. . .
<endpoint name="rest"
address="rest"
binding="webHttpBinding"
contract="IWCF.IServices"
behaviorConfiguration="REST"
bindingConfiguration="REST SSL"/>

Categories