Configure a WCF service with 2 endpoints with different binding configurations - wcf

I created a WCF service with WsHttpBinding, with 2 binding configurations (this is the requirement for 2 different client). One client wanted the service to have Message security mode with clientCredential as "Windows" and the other client wanted the service to have Transport security mode with ClientCredentialType as "Certificate". I am able to browse my Client2 service but unable to browse my client1.
Here is my web.config with 2 bindings:
<system.serviceModel>
<services>
<service name="TestService.TestService" behaviorConfiguration="mexBehavior">
<endpoint address="Client1" binding="wsHttpBinding" contract="TestService.ITestService" bindingConfiguration="TestService_Client1_ITestService" >
<identity>
<dns value="" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="Client2" binding="wsHttpBinding" contract="TestService.ITestService" bindingConfiguration="TestService_Client2_ITestService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="mexBehavior">
<useRequestHeadersForMetadataAddress />
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="TestService_Client1_ITestService">
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
</binding>
<binding name="TestService_Client2_ITestService">
<security mode="Transport">
<!--<transport clientCredentialType="None" />-->
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
Below are the settings I did in IIS:
1) Created a new website "TestService"
2) In Bindings:
a) added https with port: 444 and selected the appropriate certificate
b) added http with port: 90
3) In IIS TestService Feature View-->SSL Settings-->Require SSL (enabled), Accept and apply
4) Authentications-->Forms Authentication, Windows, Anonymous Enabled
Please suggest me what changes should I make to the config or IIS so that I have both the end points working...
Also, I named by endpoints as Client1 and Client2 assuming I should be able to browse them as
a) http://localhost:90/TestService.svc/Client1
b) https://localhost:444/TestService.svc/Client2
Currently, I am able to browse my service (client2) with
https://localhost:444/TestService.svc/
If I add Client2 at the end, it is not working. I am not sure if my endpoint address names are even working or not.
Thanks

After doing some research, I got both the end points to work.. In the IIS steps,
3) In IIS TestService Feature View-->SSL Settings-->Uncheck Require SSL (UnCheck this), but check (Accept) and Select Apply
This did the trick for me and I was able to get it work for both the end points.
Also, in my question I had a misunderstanding of being able to browse both the endpoints:
a) http://localhost:90/TestService.svc/Client1
b) https://localhost:444/TestService.svc/Client2
In reality, we will not be able to browse, this notation is useful while creating the client, which can instantiated either with the Endpoint Name or based on Endpoint configuration

Related

Unable to add service reference

I am unable to connect to a WCF service hosted on our dev server but I am able to browse to it.
I am just trying to add a service reference via Visual Studio and when I click on Go, it gives me the following error.
An error occurred while receiving the HTTP response to http://...Service.svc. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.
My other colleagues are able to add the service reference and connect to this service with no issues, which makes it harder for me to understand the cause of this issue.
Web.config - system.serviceModel:
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding" maxReceivedMessageSize="2147483646">
<readerQuotas maxStringContentLength="2147483646" />
<security mode="None">
<!-- **WARNING** Changes to the security binding must also be made in client binding code -->
<transport clientCredentialType="None" proxyCredentialType="None" />
<message clientCredentialType="None" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="X.X.X.RepositoryService" behaviorConfiguration="repositoryServiceBehavior">
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding"
contract="X.X.X.ICatalogServiceContract" />
<!-- ** NOTE Metadata not supported SSL at this time **-->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="repositoryServiceBehavior">
<serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
<dataContractSerializer maxItemsInObjectGraph="2147483646"/>
</behavior>
</serviceBehaviors>
</behaviors>

WCF Services need to be HTTPS only but only work on HTTP

I have some WCF services that have been working for a while now on HTTP.
I'm moving them to deployment server now and they need to be HTTPS only.
I got the certificate and when I initially set the up they worked over both HTTP and HTTPS.
...at this point I wanted to drop the non-secure access to the services.
So I'm trying to make amendments to my web.config to make this happen:
Service Behaviours:
<serviceBehaviors>
<behavior name="MetaEnabledBahavior">
<serviceMetadata httpsGetEnabled="true"/>
</behavior>
</serviceBehaviors>
Service Endpoints:
<service name="Services.BookingService" behaviorConfiguration="MetaEnabledBahavior">
<!-- Service Endpoints -->
<clear/>
<endpoint address="https://website.com/services/BookingService.svc" binding="wsHttpBinding"
bindingConfiguration="TransportSecurity" contract="Services.IBookingService"/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
Bindings:
<bindings>
<wsHttpBinding>
<binding name="TransportSecurity" maxReceivedMessageSize="2000000">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
What I have ended up with at the moment is my HTTP services are still accessible, but the HTTPS access just sends a blank page.
I need HTTP to return an error/page must be viewed by secure channel and HTTPS to be the ones that work only.
How do I fix this?
Smithy try replacing your endpoint with the following:
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="TransportSecurity" contract="Services.IBookingService"></endpoint>
And your binding with a basicHttpBinding
<basicHttpBinding>
<binding name="TransportSecurity" maxReceivedMessageSize="2000000">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
Hope this helps.
In the <protocolMapping> section of Web.Config, add a <remove scheme="http" /> element.

WCF SSL endpoint address is not HTTPS

Im trying to host my SSL WCF service locally on my PC (IIS 7) and for some reason i cant connect to it. What i need is to use SSL and send in credntials to authenticate the user before calling some function.
When i connect to it, i get There was no endpoint listening at https://[computer name]/YYY.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
the inner message is The remote server returned an error: (404) Not Found.
What i have noticed is that when i access the WSDL (hosted over https) the endpoint address is not http*S* and i think that is why my service is probably failing.
here is part of my WSDL
<wsdl:service name="WSNAME">
<wsdl:port name="WSHttpBinding_INams" binding="tns:WSHttpBinding_INams">
<soap12:address location="http://[computer name]/YYY.svc" />
<wsa10:EndpointReference>
<wsa10:Address>http://[computer name]/YYY.svc</wsa10:Address>
<Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
<Spn>host/[computername]</Spn>
</Identity>
</wsa10:EndpointReference>
This is my service config file
<service behaviorConfiguration="test" name="NewServiceType">
<endpoint address="https://[computer name]/YYY.svc" binding="wsHttpBinding"
bindingConfiguration="WsBinding" name="WS" contract="Authentication2.INams" />
<endpoint address="mex" binding="mexHttpBinding" name="MX" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://[computer name]/XXX.svc" />
</baseAddresses>
</host>
can anyone point out what am i doing wrong?
my web.config
<system.serviceModel>
<protocolMapping>
<remove scheme="http" />
<add scheme="http" binding="wsHttpBinding" />
</protocolMapping>
<bindings>
<wsHttpBinding>
<binding name="wsbinding">
<security mode="TransportWithMessageCredential">
<transport proxyCredentialType="Basic" />
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="NewServiceType">
<endpoint address="/WS" binding="wsHttpBinding"
bindingConfiguration="wsbinding" name="WS" contract="Authentication3.IService1" />
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
name="MX" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"
httpsGetUrl="https://[computerName]/Service1.svc" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="false" />
FOUND IT !!
WCF service returns 404 over https but not http
the problem is that my service element name was what the editor adds by default "MyNewService" or whatever the default name is. You HAVE to use the fully qualified name..
<services>
<service name="[Namespace].[service class name]">
This cost me over 2 long days of constant work and research. If this works for you, please vote that guys answer up - NO ONE has ever mentioned this point .. i couldnt because im still new
Your endpoint has a bindingConfiguration attribute defined of WsBinding. There should be a section of the web.config that defines this configuration, including the security mode to be used (presumably transport or transportWithMessageCredential if you want to use SSL).
For example:
<bindings>
<wsHttpBinding>
<binding name="WsBinding">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</wsHttpBinding>
</bindings>
Additionally you'll need to configure IIS with a binding listening on 443, referencing an appropriately named SSL certificate.
For a credential type of windows:
This corresponds to integrated Windows authentication in IIS. When set
to this value, the server is also expected to exist on a Windows
domain that uses the Kerberos protocol as its domain controller.
More details on this on the MSDN WCF transport security page
Alternatively you can use TransportWithMessageCredential. This uses SSL to encrypt the connection, and the credentials are passed in the message itself (effectively username and password in the SOAP header). In that case your binding configuration looks more like:
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Username" />
</security>
You then need to define a password validator behavior on the service to check the user and password. Here's some more info on that: http://msdn.microsoft.com/en-us/library/aa354508.aspx

How can I use WCF with the basichttpbinding only , SSL and Basic Authentication in IIS?

Is it possible to setup a WCF service with SSL and Basic Authentication in IIS using only the BasicHttpBinding-binding?
(I can’t use the wsHttpBinding-binding)
The site is hosted on IIS 7, with the following authentication set up:
Anonymous access: OFF
Basic authentication: ON
Integrated Windows authentication: OFF
Service Config:
<services>
<service name="NameSpace.SomeService">
<host>
<baseAddresses>
<add baseAddress="https://hostname/SomeService/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<endpoint address="" binding="basicHttpBinding"
bindingNamespace="http://hostname/SomeMethodName/1"
contract="NameSpace.ISomeInterfaceService"
name="Default"
/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
<exceptionShielding/>
</behavior>
</serviceBehaviors>
</behaviors>
I tried 2 types of bindings with two different errors:
1. IIS Error:
'Could not find a base address that matches scheme http for the endpoint with binding BasicHttpBinding. Registered base address schemes are [https].
<bindings>
<basicHttpBinding>
<binding>
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
2. IIS Error:
Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service.
<bindings>
<basicHttpBinding>
<binding>
<security mode="Transport">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
Does anyone know how to configure this correctly? (if is it possible?)
After some digging and asking some questions to a few colleagues, we finally solved the problem.
Important to understand is there are 2 aspects of security in this case. The IIS security and the WCF security.
IIS security: Enable SSL & enable Basic Authentication. Disable Anonymous Authentication.
(Of course, create a windows account/group and set the permissions on your application in IIS.)
WCF security: Because the binding is only a BasicHttpBinding, the service doesn't require to valid anything. IIS is responsible for this.
The binding configuration of the service:
<bindings>
<basicHttpBinding>
<binding>
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
And finally, to resolve the first error, we deleted the mex Endpoint. This endpoint requires a HTTP binding.
Deleted:
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>

WCF and Kerberos Authentication

I have followed numerous msdn articles and the codeplex guidance but cannot get WCF to work with Kerberos authentication and delegation and would appreciate a little help.
Setup
I have the WCF service in an IIS website on a remote machine
IIS 6.0 on Windows 2003 R2 - SP 2
The SPN for the machine has been added (http/myserver && http/myserver:8080)
An AD account has been created for the IIS app pool
The AD account has the setting, allow delegation (for Kerberos), set to true
I am using Brian Booth's debug site on 8080 and the site passes all requirements for Kerberos delegation. The debug IIS site has anonymous authentication off, and Integrated Windows authentication on.
I have mirrored these settings to the site hosting the WCF service.
Web Service - Web Config (Original)
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WsHttpBindingConfig">
<security>
<message negotiateServiceCredential="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="ServiceBehavior" name="Service">
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="WsHttpBindingConfig"
contract="IService">
<identity>
<servicePrincipalName value="http/myserver" />
<dns value="" />
</identity>
</endpoint>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceAuthorization
impersonateCallerForAllOperations="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Web Service - Web Method
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public string GetCurrentUserName()
{
string name = WindowsIdentity.GetCurrent().Name;
return name;
}
Client App - App Config
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService"
... />
...
<security mode="Message">
<transport clientCredentialType="Windows"
proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows"
negotiateServiceCredential="true"
algorithmSuite="Default"
establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://myserver/Service.svc"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IService"
contract="KerberosService.IService"
name="WSHttpBinding_IService">
<identity>
<servicePrincipalName value="http/myserver" />
</identity>
</endpoint>
</client>
</system.serviceModel>
Application Error
The following error occurs when my test application, a WinForms app, tries to call the web method:
"The HTTP request is unauthorized with
client authentication scheme
'Anonymous'. The authentication header
received from the server was
'Negotiate,NTLM'."
Event Log
The following error is in the event log:
Exception:
System.ServiceModel.ServiceActivationException:
The service '/Service.svc' cannot be
activated due to an exception during
compilation. The exception message
is: Security settings for this service
require 'Anonymous' Authentication but
it is not enabled for the IIS
application that hosts this service.
Which I don't understand. The whole point of this service is to not allow anonymous authentication, every user/request must be authenticated using Kerberos tickets, then passing them through to other machines.
How should I configure this WCF service for Kerberos authentication and delegation?
Revision 1
After reading this SO question I removed the metadata endpoint. This has not resolved the issue.
Revision 2
After more researching I found a few posts suggesting to change wsHttpBinding to basicHttpBinding. The modification to that portion of the web.config has been included below, and the service endpoint has been updated to refer to that binding.
Web Service - Web Config (Revised)
<basicHttpBinding>
<binding name="basicBindingConfig">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"
proxyCredentialType="Windows"
realm="" />
</security>
</binding>
</basicHttpBinding>
Client App - App Config (Revised)
<!-- ... -->
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"
proxyCredentialType="Windows"
realm="" />
<message clientCredentialType="UserName"
algorithmSuite="Default" />
</security>
<!-- ... -->
Error (Revised)
The current error looks like it contains a Kerberos authentication header.
The HTTP request is unauthorized with
client authentication scheme
'Negotiate'. The authentication header
received from the server was
'Negotiate SOMEHUGESCARYKEYHERE
For me the current setup does work:
On the Server:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBindingConf" useDefaultWebProxy="true"/>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="returnFaults" name="Epze.BusinessLayer.ZeitManager">
<endpoint binding="wsHttpBinding" bindingConfiguration="wsHttpBindingConf" contract="Epze.Contract.IZeitManager"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="returnFaults">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceAuthorization impersonateCallerForAllOperations="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Set the following attribute on all methods for the WCF:
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
On the Client:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IZeitManager" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm=""/>
<message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" establishSecurityContext="true"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="Delegation">
<clientCredentials>
<windows allowedImpersonationLevel="Delegation" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="http://server.mydomain.net/ePZEsvc/ZeitManager.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IZeitManager"
contract="External.Epze.IZeitManager" name="WSHttpBinding_IZeitManager" behaviorConfiguration="Delegation">
<identity>
<servicePrincipalName value="HOST/localhost"/>
</identity>
</endpoint>
</client>
</system.serviceModel>
HTH, Sven
Something that I notice: the client and server config don't seem to agree on security mode.
In the original section, you have <security>..... in the web.config (omitted the mode="message"), and <security mode="Message"> on the client side.
After your edit, it seems that the client side is unchanged, but the server (web.config) now contains <security mode="TransportCredentialOnly">.
The question really is: can you guarantee that there's only ever going to be one network leg between the client and the server being called? I.e. is this behind a corporate firewall? In that case, I would recommend netTcp binding with <security mode="Transport"> on both ends.
If that's not the case, then you're ok with either wsHttpBinding (which supports more security and reliability features, but is slower and "heavier") or basicHttpBinding. In that case, you would have to use <security mode="Message"> on both ends, and authenticate the service with a certificate (so that the service and client have a common "secret" which to use for encryption).
I would try to leave out the impersonation parts out for the beginning and just get the basic communication and mutual authentication between service and client up and running first - once that's in place, you can start adding the impersonation bits to it, and you can always fall back on a known configuration which works.
David Sackstein has a great series of blog posts explaining the five security scenarios that industry guru Juval Lowy has identified (in his Programming WCF book - the WCF Bible) as the most common and most useful - in order to limit the number of possible combinations of parameters you might want to tweak. One of them is a "Internet" scenario which would probably apply here, if your service is outward facing.
Marc
You need to specify a behaviorConfiguration in your client config. SVCUtil does not auto generate. This resolved my issue and I am now successfully using Kerberos. It was a mission though!
<client>
<endpoint address="..."
binding="customBinding" bindingConfiguration="..."
contract="..." name="..." behaviorConfiguration="ImpersonationBehavior" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="ImpersonationBehavior">
<clientCredentials>
<windows allowedImpersonationLevel="Impersonation"/> </clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
You should try your initial configuration and make sure to set the IIS to be anonymous and windows authentication at the same time.The reason is when you are using wsHttpBinding default security is message security and there is no transport security defined unless you want to do https. SO Clr states that it needs anonymous authentication turned-on on the IIS.