WCF Metadata on separate port and not SSL - wcf

Pretty new to complex WCF configs and have looked around, but couldn't clearly answer this.
I'm looking for a yes this is possible and ideally a sample or no, this is not possible.
Question:
Can you separate out the Metadata (WSDL) from a secure transport (SSL) service and make it plain old HTTP?
We have a WCF service that is using Transport security (SSL) for the service.
At this stage, during development we're using our own Certificates for the SSL, so we're a CA.
So the WSDL is exposed using
<serviceMetadata httpsGetEnabled="true" />
Under the service behaviours.
When you browse to the WSDL https://devserver:8010/MyService/?wsdl you get the usual, don't know the CA warning and just click IGNORE to continue on.
One of the problems I've got is that a proxy generation tool like JAX-WS just bails with a HTTP.403 Forbidden warning, even though I've put the CA certificate into the JDK/JRE keystore for cacerts.
So I was thinking, if I could separate out the Metadata then you could expose that on HTTP on a separate port and then there's no certificate issues for generating proxies.
So I tried marking the service metadata as follows:
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://devserver:8011/MyService/" />
But this doesn't work as it's now mixing up the behaviour.
Perhaps I've missed something?
Perhaps this isn't possible?
And yes, to some extent it is moot, as a production machine WOULD have a trusted CA and therefore you won't get the certificate trust warnings.
However, it's now become a question of is this possible?
All help appreciated, thanks
Hadley

You also need to specify your MEX endpoint
http://bloggingabout.net/blogs/dennis/archive/2006/11/09/WCF-Part-4-3A00-Make-your-service-visible-through-metadata.aspx
Note it will need a different binding configuration with security = None instead of transport.

Did some more trial and error and the end result which works is like this. This is shortened for brevity.
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehaviour">
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://devserver:8022/MyService/" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="basicHttp" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" />
<security mode="Transport">
</security>
</binding>
</basicHttpBinding>
<webHttpBinding>
<binding name="webHttp">
<security mode="None">
</security>
</binding>
</webHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="serviceBehaviour" name="MyService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttp"
name="httpsEndpoint" contract="IMyService" />
<host>
<baseAddresses>
<add baseAddress="https://devserver:8020/MyService/" />
</baseAddresses>
</host>
</service>

Related

Mutual SSL security mode binding configurations

I have two questions regarding the security mode regarding mutual ssl.
I have look through a few sites such as:
1.https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/transport-security-with-certificate-authentication%20
2.https://www.codeproject.com/Articles/348595/Use-Mutual-SSL-Authentication-in-WCF
In all the binding configurations. I realized that all security mode is set as 'Transport'.
<bindings>
<wsHttpBinding>
<!-- configure wsHttp binding with Transport security mode and clientCredentialType as Certificate -->
<binding>
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
In regards to this, what I want to know is if its possible to use other kind of security mode such as
'Message' or 'TransportWithMessageCredential'. If so why?
Furthermore if its possible, does the client side have to change their security mode to the same as the server side?
The Microsoft official document also offers an example of authenticating the client with message security mode with mutual certificates.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/message-security-with-mutual-certificates
What we need to do is configuring a service certificate on the server-side, a certificate on the client-side, also establishing the certificate trust relationship between the client-side and server-side.
Here is a standard configuration.
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="serviceCredentialBehavior">
<serviceCredentials>
<serviceCertificate findValue="Contoso.com"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="serviceCredentialBehavior"
name="ServiceModel.Calculator">
<endpoint address="http://localhost/Calculator"
binding="wsHttpBinding"
bindingConfiguration="InteropCertificateBinding"
name="WSHttpBinding_ICalculator"
contract="ServiceModel.ICalculator" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="InteropCertificateBinding">
<security mode="Message">
<message clientCredentialType="Certificate"
negotiateServiceCredential="false"
establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
This is also applicable to the TransportWithMessageCredential security mode. As long as the security mode is Transport security mode, we need to bind a certificate to the particular port.
Besides, the binding configuration should be coherent between the client-side and the server-side. Just like the service contract is shared between the client-side and the server-side.
Feel free to let me know if there is anything I can help with.

WCF Rest Service with optional client certificate

Is it possible to have an WCF Rest Webservice which excepts SSL Client Certificates and have the IIS SSL Setting to not set to "require SSL" and to anly "accept" client certificates and not "require" them?
I have the following config:
<system.serviceModel>
<services>
<service behaviorConfiguration="RestServiceBehaviour" name="PM.WCF.Service.PmRestService">
<endpoint address="" behaviorConfiguration="web" binding="webHttpBinding"
bindingConfiguration="StreamedRequestWebBinding" contract="PM.WCF.Service.IPmRestService" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="StreamedRequestWebBinding"
bypassProxyOnLocal="true"
useDefaultWebProxy="false"
hostNameComparisonMode="WeakWildcard"
sendTimeout="10:15:00"
openTimeout="10:15:00"
receiveTimeout="10:15:00"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647"
maxBufferPoolSize="2147483647"
transferMode="StreamedRequest">
<readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" />
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="RestServiceBehaviour">
<serviceMetadata httpsGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
My problem is the following line:
<transport clientCredentialType="Certificate"/>
If i use this setting and IIS configured to accept, but not require client certificates, I get the following error:
The SSL settings for the service 'SslRequireCert' does not match those of the IIS 'SslNegotiateCert'.
Sadly setting
<transport clientCredentialType="None"/>
Does not work either. I'm pretty sure the browser/client does send it's certificate, but OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.IsAuthenticated is False.
Is there any other way then to have two IIS Websites, one configured to require SSL and client certificates and one which does not?
Even if there is no way around it. How do I debug this in Visual Studio? Because the moment I require SSL client certificates, I can't just start the webservice. Visual Studio tries to access http://localhost/Foo.WCF.Service/debugattach.aspx and fails because of the missing client certificate.

The remote server returned an error: (413) Request Entity Too Large + WCF

May be this question is a duplicate. I have a WCF upload service through which the client uploads a particular file to the server.
I could successfully send files of size 12MB through the service.
Now I have integrated a self certified SSL certificate to the WCF Service. The same application which was working fine without SSL now returns an error saying Remote server returned an error (413) request entity too large.
how do I fix this error is this something to do with SSL ?
where am I going wrong.
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="customHttpBinding" openTimeout="00:10:00" sendTimeout="00:10:00"
maxReceivedMessageSize="10067108864"
messageEncoding="Mtom" transferMode="Streamed">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="customServiceBehavior">
<serviceMetadata httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerOrChainTrust" trustedStoreLocation="LocalMachine"/>
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="customServiceBehavior" name="FileTransferService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="customHttpBinding"
contract="IFileTransferService" />
</service>
</services>
thanks
This seems to be the ticket to fixing the 413 Request Entity too large error with WCF over HTTPS
C:\Windows\System32\inetsrv>appcmd.exe set config "Default Web Site" -section:system.webServer/serverRunTime /uploadReadAheadSize:10485760 /commit:apphost
The reason seems to be related to how IIS handles authentication of incoming requests over SSL.
Another resource: http://blogs.msdn.com/b/jiruss/archive/2007/04/13/http-413-request-entity-too-large-can-t-upload-large-files-using-iis6.aspx
I just spent most of my afternoon tracking this problem down...many other suggestions didn't help me much but this certainly did, so hopefully this will get you fixed up.

How to create a WCF service without the need of a Service Certificate?

I'm trying to create a basic webservice with WCF. It's small, and will only be used internally between two servers, so there is no need for security of any kind. Unfortunately WCF demands a certificate:
The service certificate is not provided. Specify a service certificate in ServiceCredentials.
I don't want to configure a certificate anywhere. Certificates are great for security, but also invariably come packaged with two days worth of headaches until you get them right just so, and I don't want that right now.
I'm googling all around but cannot find an answer anywhere - can you disable this feature of WCF?
Added: Almost forgot, here's my bindings 'n stuff, just in case they're useful:
<bindings>
<wsFederationHttpBinding>
<binding name="XXXServiceBinding" maxReceivedMessageSize="1073741824">
<readerQuotas maxStringContentLength="1073741824" maxArrayLength="2147483647"/>
</binding>
</wsFederationHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="XXXServiceBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483646"/>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="XXX.XXX" behaviorConfiguration="XXXServiceBehavior">
<endpoint address="xxx" contract="XXX.IXXX" binding="wsFederationHttpBinding" bindingConfiguration="XXXServiceBinding">
<identity>
<dns value="XXX Test Service"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
Added 2: Oh, right, VS2010, .NET 4.0. Windows 7, integrated VS webserver.
What does your web.config bindings section look like? Using basicHttpBinding with clientCredentialType="None" should as far as I know run without any certificates. Ie:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IServiceWS">
<security mode="None">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
</bindings>
....
If you don't want to use security why are you using WsFedarationBinding which is designed for federated security? Use BasicHttpBinding instead. It doesn't use any security by default or if all communication will be performed in the same windows domain with users and service using domain accounts you can use WsHttpBinding with default configuration - it will use Windows security without need for any certificate.
You are using wsFederationHttpBinding in the service. If it is not important to push in so much of security, you could have gone for simple HTTP binding called basicHTTP binding. Consider appropriate binding for the service.

Adding a service reference to a WCF service with webHttpBinding and security mode Transport results in an incorrect config file

I have searched and searched and I cannot find a solution. It seems like it would be relatively common to run into this... WCF REST service over https. When I add the service reference all of the proxy classes are correct and I can create the objects defined in the service, call the services, etc. However, I can't create a configured client with the proxy's client classes. I have to explicity create the bindings, behaviors, and endpoints and add them to the client. FOr example, what I should be able to do, based on all of my research is:
ServiceClient = new ServiceClient();
And be off and running. However, what I have to do is:
WebHttpBinding serviceBinding = new WebHttpBinding(WebHttpSecurityMode.Transport);
serviceBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
EndpointAddress endPointAddress
= new EndpointAddress(<endpointaddress>);
// Create Service Client
ServiceClient = new ServiceClient(serviceBinding, endPointAddress);
// Add Web Behavior to the EndPoint
WebHttpBehavior webHttpBehavior = new WebHttpBehavior();
ServiceClient.Endpoint.Behaviors.Add(webHttpBehavior);
// Set up the request to POST with a wrapped request
WebInvokeAttribute postAttribute = new WebInvokeAttribute();
postAttribute.Method = "POST";
postAttribute.BodyStyle = WebMessageBodyStyle.WrappedRequest;
ServiceClient.Endpoint.Contract.Operations.Find(<operationname>).Behaviors.Add(postAttribute);
In order to mimic the service configuration:
<behaviors>
<endpointBehaviors>
<behavior name="AspNetAjaxBehaviorXml">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="AuthenticationServicesBehavior">
<serviceMetadata httpsGetEnabled="true" policyVersion="Policy15" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="LoggingServicesBehavior">
<serviceMetadata httpsGetEnabled="true" policyVersion="Policy15" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="True" />
<bindings>
<webHttpBinding>
<binding name="WebSslBinding">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</webHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="AuthenticationServicesBehavior"
name="AuthenticationServices">
<endpoint address="authenticate" behaviorConfiguration="AspNetAjaxBehaviorXml"
binding="webHttpBinding" bindingConfiguration="WebSslBinding"
name="AuthenticationEndPoint" bindingNamespace="<mynamespace>"
contract="IService" />
</service>
The "Add Service Reference" is giving me this:
<bindings>
<customBinding>
<binding name="AuthenticationEndPoint">
<!-- WsdlImporter encountered unrecognized policy assertions in ServiceDescription 'EchoAppsServices': -->
<!-- <wsdl:binding name='AuthenticationEndPoint'> -->
<!-- <sp:HttpsToken xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">..</sp:HttpsToken> -->
<textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
messageVersion="Soap12" writeEncoding="utf-8">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</textMessageEncoding>
</binding>
</customBinding>
</bindings>
<client>
<endpoint binding="customBinding" bindingConfiguration="AuthenticationEndPoint"
contract="AuthenticationService"
name="AuthenticationEndPoint" />
</client>
I believe my inability to create a default client that works out of the box is related to the problem with WsdlImporter. I get a similar error when I use svcutil:
Warning: The following Policy Assertions were not Imported:
XPath://wsdl:definitions[#targetNamespace='<mynamespace>']/wsdl:binding[#na
me='AuthenticationEndPoint']
Assertions:
<sp:HttpsToken xmlns:sp='http://schemas.xmlsoap.org/ws/2005/07/securitypolic
y'>..</sp:HttpsToken>
I'm sure it has something to do with my self signed cert, but I can't get makecert to give me a functioning cert with a CA that doesn't cause my IIS to crash.
Environment details:
VS2008
XP 64bit
.NET 3.5
IIS6
Thanks in advance for any help...
If you want to create client proxy classes, why would you use webHttpBinding. Why not just use wsHttpBinding?
The whole point of webHttpBinding was so that you could use standard Http toolkits like HttpWebRequest and Microsoft.Http.HttpClient on the client to access the service.
Not sure if that's just a typo - but your code and config don't match.
See in your code:
serviceBinding.Security.Transport.ClientCredentialType =
HttpClientCredentialType.Windows;
but in your config:
<webHttpBinding>
<binding name="WebSslBinding">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</webHttpBinding>
In code, you set your HttpClientCredentialType to Windows (integrated Windows authentication), but in config, you set it to None.
Try changing your config to use Windows as well:
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
and try again.
If you don't get any better results : why not just update the client config manually, after the import? The WSDL importer is known to have hiccups here and there, and most often, just using your brain and manual config adaption can solve the problem. You basically just need to copy the <endpointBehaviors> and the <bindings> sections into your client side config and define a <client> section which references the appropriate endpoint - that's pretty much all.
You bring up a good point, but I started down this road to make a RESTful web service that can be called either from the client or the server. I can call it from both right now just the way it is but I have to explicitly configure the server side. This is unacceptable because this application will be deployed to multiple end users and it's easier to change a configuration file than it is to patch. I know that I could create multiple endpoints, but I would much rather only have to maintain one per service.
Thank you for your reply.