I've got a small WCF service in intranet and I need to implement authentication in it. This service communicates with different Java clients over http (uses basicHttpBinding). I've tried to configure binding like so
<basicHttpBinding>
<binding>
<security mode="None">
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
And added service behaviour
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="LocalTasks.Services.Validators.IntegrationUserNameValidator,LocalTasks.Services"/>
</serviceCredentials>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
But calls to this service do not hit my custom UserNamePassword validator.
I've also tried the same variant but with security mode set to Message and added a certificate. In this case validator worked fine.
How to configure service to authenticate users via basicHttpBinding without any message or transport security?
You cannot do that. You need either message or transport security, in order to have the credentials encrypted when they travel from the client to the server.
You really should use Message or Transport security.
You could also use TransportCredentialOnly, which will not require an SSL certificate, but that is recommended for testing only.
<basicHttpBinding>
<binding name="Authentication" >
<security mode="TransportCredentialOnly" >
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
Related
I'm a beginner with WCF services. Trying to implement a Certificated based authentication on a WCF service and facing an issue. The service expects a specific Certificate from the calling client. The server throws an authentication error if the client is not passing any certificate. But at the same time, the service call is passing authentication with any certificates provided by the client(The service suppose to authenticate if the client provides a specific certificate).
Following is the code snippet of server config :
Service Config :
<bindings>
<wsHttpBinding>
<binding name="MyWsHttpBinding" maxReceivedMessageSize="2147483647" receiveTimeout="00:30:00">
<readerQuotas maxStringContentLength="2147483647" maxBytesPerRead="2147483647" maxDepth="2147483647" maxArrayLength="2147483647"/>
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None"/>
<message clientCredentialType="Certificate" algorithmSuite="Default"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="ChainTrust" />
</clientCertificate>
<serviceCertificate findValue="e616ebcd940951794736624acc6484802018c8d4" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
</serviceCredentials>
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="true"/>
<CustomBehaviorExtensionElement/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="MyEndpointBehavior">
<MySchemaValidator validateRequest="True" validateReply="False">
<schemas>
<add location="App_Data\model-service.xsd"/>
</schemas>
</MySchemaValidator>
</behavior>
</endpointBehaviors>
<services>
<service name="MyService" behaviorConfiguration="MyServiceBehavior">
<endpoint binding="wsHttpBinding" bindingConfiguration="MyWsHttpBinding" contract="MyExchangeService" behaviorConfiguration="MyEndpointBehavior" bindingNamespace="http://www.mycompany.com/exchange/"/>
<endpoint contract="IMetadataExchange" binding="mexHttpsBinding" address="mex" name="mex"/>
</service>
</services>
The cause of the problem is the security mode you use is transport, so only the following code works:
<transport clientCredentialType="None" proxyCredentialType="None"/>
The following message settings have no effect:
<message clientCredentialType="Certificate" algorithmSuite="Default"/>
Change the value in transport to certificate, you can also download the wcf demo on the official website, there are examples of related certificate verification, and there are tutorials corresponding to the demo.
I see that the certificate validation mode used in your code is ChainTrust.
<clientCertificate>
<authentication certificateValidationMode="ChainTrust" />
</clientCertificate>
As mentioned in Microsoft Docs, using ChainTrust means -
The certificate is valid if the chain builds to a certification authority in the trusted root store
Meaning, the client need not send certificate with the exact same thumbprint as mentioned in your service web.config. Infact, any certificate whose Root / Intermediate Certification Authority is present in your VM's Trusted Root Store will pass validation.
To make sure that the client is able to use only a specific certificate to authenticate to your service, change ChainTrust to PeerTrust and add the certificate to the trusted people store on your VM's Certificate Store (certmgr).
<authentication certificateValidationMode="PeerTrust" />
References:
MS Docs - Working with certificates in WCF
Authentication element in web.config
More info on Certificate Chain of Trust
I have been reading the WCF configuration documentation and would like a confirmation on a limitation that I've encountered.
I have a client that expects the following binding configuration:
<bindings>
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
On the server side I have implemented a custom user name and password validator because we don't use Windows or domain accounts for clients. I followed this guide: https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-use-a-custom-user-name-and-password-validator, but they and other examples I've seen use wsHttpBinding or add message security.
The server endpoints and behaviors look something like this:
<services>
<service name="MyWcfService.Service" behaviorConfiguration="MyBehavior">
<endpoint
address=""
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding"
contract="MyWcfService.IService"/>
<endpoint
address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceCredentials>
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="MyValidator, MyWcfService"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
When hosting the service in IIS with basic authentication enabled the custom validator is not hit, IIS tries to validate the provided credentials against Windows accounts and fails with this message if the user account doesn't exist:
The HTTP request is unauthorized with client authentication scheme 'Basic'.
So is it impossible to have a custom credential validator for a service hosted in IIS with basicHttpBinding, Transport security mode, and Basic transport client credential type? Is there no way to override the basic Windows authentication that IIS does?
We should use UserName authentication instead of the Basic authentication, subsequently, we could have a custom credential validator for that service.
<basicHttpBinding>
<binding name="mybinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
<serviceCredentials>
<userNameAuthentication customUserNamePasswordValidatorType="WcfService3.CustUserNamePasswordVal,WcfService3" userNamePasswordValidationMode="Custom"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
For details,
How to add user/pass authentication in WCF
Feel free to let me know if there is anything I can help with.
So far it looks like it's not possible to use a custom credential validator with this binding configuration.
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="Basic"/>
</security>
</binding>
If I have an issued SSL certificate from a trusted CA, do I still have to import the SSL certificate to the client machine when connecting to a WCF service over net.tcp?
When I was using wsdualhttpbinding I could simply connect via https. Now I switched to net.tcp and added
<bindings>
<netTcpBinding>
<binding name="InsecureTcp" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="Certificate"/>
</security>
</binding>
</netTcpBinding>
</bindings>
to the web.config file.
I can access the WSDL-file via https but when I try to connect from my client I get the following error:
Additional information: The client certificate is not provided. Specify a client certificate in ClientCredentials.
I have tried to add a custom behavior to the client config file:
<behaviors>
<endpointBehaviors>
<behavior name="CustomBehavior">
<clientCredentials>
<clientCertificate findValue="example.com" x509FindType="FindBySubjectName"
storeLocation="LocalMachine" storeName="My" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
But this only works in combination with importing the certificate to my local cert store...
I hope I get your point - you don't want to use client certificates for authentication? Then modify <security mode="TransportWithMessageCredential">
<message clientCredentialType="Certificate"/>
</security>
the clientCredentialType to one of the following:
http://msdn.microsoft.com/en-us/library/system.servicemodel.httpclientcredentialtype(v=vs.110).aspx
You can use multiple authentication mechanisms, if you want:
http://msdn.microsoft.com/de-de/library/ms731316(v=vs.110).aspx
I am using WCF service with Transport mode. I need to make this service secure using Certificates.
I followed the steps given in the below link and got it working in my local
http://www.codeproject.com/Articles/36683/simple-steps-to-enable-X-certificates-on-WCF
The issues i am facing now are:-
In the above mentioned steps, i had the service running locally as well as my client application that calls the service, running locally. Now for my QA deployment i have the service hosted on one server and my Client application on another server.
I dont have visual studio commant prompt in both these servers to create the certificates using makecert.
My service will be in https.
I will be using some third party to get the certificates for my production, but now i am not able to figure out how to get this working for my QA environment.
I have tried creating a Certificate to Act as Root Certificate Authority and installed it in both the servers. In this approach also i am stuck as to how will i create my client and server certificates under this root authority.
Kindly let me know how can i get this working.
Thanks in advance.
Finally got it working. I had to create certificates using makecert in my local and then had to import them in my QA environment (will be using certificates from a trusted third party for my production environment). My requirement was to make my service secure and not allow unauthorised clients to consume it.
My service web-config.
Changes in the binding
<bindings>
<basicHttpBinding>
<binding name="basicHttpEndpointBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpBinding>
</bindings
Changes in behavior.
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="ChainTrust" revocationMode="NoCheck" />
</clientCertificate>
</serviceCredentials>
My Client web-config.
Changes in binding
<binding name="">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" />
</security>
</binding>
Add behavior
<behaviors>
<endpointBehaviors>
<behavior name="CustomBehavior">
<clientCredentials>
<clientCertificate findValue="RootCATest"
x509FindType="FindByIssuerName"
storeLocation="LocalMachine"
storeName="My"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
Attach this behavior to the endpoint
behaviorConfiguration="CustomBehavior"
Our azure web application already uses https port 443 with our site certificate, we have a WCF service within this webrole that has an https endpoint using our cert to authenticate (1-way ssl), this same service needs an additional https endpoint supporting 2-way auth using our cert and the third party's cert. We have uploaded the cert, updated the service definition file, and added an endpoint that we are hoping will work, but in testing we are getting the error: The SSL settings for the service 'SslRequireCert' does not match those of the IIS 'None'.
so the endpoint that does work is: https://environemnt.application.com/Services/Service.svc
the endpoint that generates the error: https://environment.application.com/Services/Service.svc/twa
The key requirement is that it is https, port 443, at the above new endpoint, without altering the SSL behavior of the rest of the role, I have seen entries to change the IIS configuration or use the role editor to add an Https Input endpoint, but as we already have an Https Input endpoint on port 443 using our site cert I don't want to alter/affect the whole role.
If it is helpful the service is a WCF Service which consumes an Mtom encoded soap 1.2 message
here are the new values that we have entered, what else do I need?
<behaviors>
<serviceBehaviors>
<behavior name="SSLServiceBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="OneWayAuthEndpointBehavior">
</behavior>
<behavior name="TwoWayAuthEndpointBehavior">
<endpointDiscovery enabled="true"></endpointDiscovery>
<clientCredentials>
<clientCertificate findValue="thumprint..." storeLocation="LocalMachine" storeName="CertificateAuthority" x509FindType="FindByThumbprint" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="SSLServiceBehavior" name="Service">
<endpoint address="" behaviorConfiguration="OneWayAuthEndpointBehavior"binding="wsHttpBinding" bindingConfiguration="HttpsMtomOneWay" contract="ITestService" />
<endpoint address="twa" behaviorConfiguration="TwoWayAuthEndpointBehavior" binding="wsHttpBinding" bindingConfiguration="HttpsMtomTwoWay" contract="ITestService"/>
</services>
<bindings>
<wsHttpBinding>
<binding name="HttpsMtomOneWay" messageEncoding="Mtom">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
<binding name="HttpsMtomTwoWay" messageEncoding="Mtom">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
thank you much
Fixed through these steps:
Added serviceCredentials.serviceCertificate (cert details for our cert) to the service behavior
Eliminated Endpoint behavior definitions
Changed the HttpsMtomTwoWay binding to securityMode=Message
Now the message handlers handle the authentication exchange and external cert validation, then pass on to the transport endpoint, and we did not need to mess with the site wide SSL or endpoint settings. Tested and verified with numerous 3rd parties.