I created a WCF Service, using http Basic Authentication and SSL. (Temporary certificate in IIS atm)
Here is the relevant configuration.
<services>
<service name="MyNamespace.MyService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttps"
name="MyEndPoint" contract="MyNamespace.IMyService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<!-- These will be false when deployed -->
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<!-- This doesn't do anything in IIS -->
<behavior name="CustomUsernameValidatorBehavior">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="MyNamespace.CustomUserNameValidator" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="basicHttps">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
</bindings>
Due to the fact I am hosting in IIS, I can't use my customUsernameValidator, and IIS Basic authentication tries the username and password against Windows.
I created a new user, disabled logon locally, and put it in a new group (without rights). The only purpose of the user is to ensure they are allowed to access the service, nothing else. The service will be online, not internal e.g. in an Intranet etc.
My question boils down to this, is there security risks/implications due to the fact I am using a real windows user? What can be done to secure this service/IIS if so?
Should something be done to prevent 'phishing' of information, could they for example try different usernames and passwords to find credentials?
Btw this is a working binding (minus some other endpoints etc.) for WCF using Http Basic Authentication in IIS and SSL. It requires IIS has Basic Authentication installed, as well as a Windows User to authenticate against. I would prefer not to authenticate against a Windows user.
IIS 5.0 and below version has IP address disclosure vulnerability if Basic Authentication (with no realm defined) is used.
Please have a look at this site:
http://www.juniper.net/security/auto/vulnerabilities/vuln1499.html
Related
I am trying to use https & http for the website. The website has .svc files which act as REST service and called from JavaScript.
My Config:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="AjaxBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MyServiceBehaviour">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
<service behaviorConfiguration="MyServiceBehaviour" name="MyService.Lookups">
<endpoint address="" behaviorConfiguration="AjaxBehavior"
binding="webHttpBinding" bindingConfiguration="httpWebBinding" contract="MyService.Lookups" >
</endpoint>
<endpoint address="" behaviorConfiguration="AjaxBehavior"
binding="webHttpBinding" bindingConfiguration="httpsWebBinding" contract="MyService.Lookups" >
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="httpsWebBinding">
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" />
</security>
</binding>
<binding name="httpWebBinding">
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None" />
</security>
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>
Browsing https://myserver/services/Lookups.svc/Hello gives
Could not find a base address that matches scheme http for the endpoint with binding WebHttpBinding. Registered base address schemes are [https]
Browsing http://myserver/services/Lookups.svc/Hello gives
Could not find a base address that matches scheme https for the endpoint with binding WebHttpBinding. Registered base address schemes are [http]
If I remove any one endpoint it works. Example removing endpoint configured with bindingConfiguration="httpWebBinding" works for HTTPS ,
How can I make it work with HTTP and HTTPS? As of now, I can able to use either http or https by removing one endpoint.
Referred How can I combine the WCF services config for both http and https in one web.config? and How do you setup HTTP and HTTPS WCF 4 RESTful services?
Note: In IIS, it is two web sites one listen on http and another on
https. Both sharing same code in physical folder
UPDATE: As of now, I removed endpoints and it works. But my concern is removing endpoing configured with behaviourConfiguration doesnt look great solution to me.
This works for both http & https
<services>
<service behaviorConfiguration="MyServiceBehaviour" name="MyService.Lookups">
</service>
</services>
I've recreated your scenario and used your web.config to configure endpoints for my test service. Your configuration is ok and works correctly. The part that don't works for you is probably your https configuration in IIS. Make sure you have enabled https access to your service. If you test it with IISExpress from Visual Studio then left click on your project and in the properties window (View -> Properties Window ) select for SSL Enabled = True.
As #Lesmian pointed out in his answer, the issue is in your IIS configuration.
More specifically in:
Note: In IIS, it is two web sites one listen on http and another on https. Both sharing same code in physical folder
The reason is that IIS can not handle endpoints on a schema which it does not support.
You have two sites, and one of them has HTTP binding but does not has HTTPS, and the other has HTTPS but not HTTP.
So when you browse to http:// URL, IIS directs you to the (surprise!) http-enabled site, reads web.config, sees that it registers https endpoint (which is not supported by the site) and throws the exception telling that there is no https scheme support on the http-enabled-only site.
When you browse to the https:// URL the situation is similar - IIS does not allow you to use http endpoint on the https-enabled-only site.
To handle the issue you better use a single site with two bindings.
Another (and more complex) option would be using different web.configs for sites: set up separate sites (pointed to separate folders) and use the publishing and web.config transforming tools of the Visual Studio
Add This Code.
<protocolMapping>
<add scheme="http" binding="webHttpBinding" bindingConfiguration="httpWebBinding"/>
<add scheme="https" binding="webHttpBinding" bindingConfiguration="httpsWebBinding"/>
</protocolMapping>
I dont't know this query is still active or not but as i checked Please
Add binding="mexHttpsBinding" also
with binding="mexHttpBinding" with different endpoint
This helps me.
We are having a problem with WCF - we are getting the error below when trying to connect. There are tons of suggestions for various configurations, having tried them all we could use some help.
We are using HTTPS for transport security, using a real SSL certificate that we got from GoDaddy. It seems to be installed and working properly when we browse to web pages on the site. With no authentication, we can connect properly to our WCF service.
For authentication, we are using client certificates that we created ourselves. These client certificates were working fine before we switched to HTTPS, when we were using message security with a self-signed server certificate (which was a pain because we had to get the clients to install the server certificate).
Error
The HTTP request was forbidden with client authentication scheme 'Anonymous'.
Inner exception: The remote server returned an error: (403) Forbidden
Server configuration file
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="NewBinding0">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="WcfService1.Service1">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="NewBinding0" contract="WcfService1.IService1" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerTrust" />
</clientCertificate>
<serviceCertificate findValue="....." x509FindType="FindByThumbprint" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add scheme="https" binding="wsHttpBinding" bindingConfiguration="NewBinding0" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Client configuration file
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="NewBehavior0">
<clientCredentials>
<clientCertificate findValue="customuser1"
storeName="TrustedPeople" x509FindType="FindBySubjectName" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="NewBinding0">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://www.insertoursitename.com/WcfService1/Service1.svc"
behaviorConfiguration="NewBehavior0" binding="wsHttpBinding"
bindingConfiguration="NewBinding0" contract="ServiceReference1.IService1"
name="wsHttpBinding_IService1" />
</client>
</system.serviceModel>
My problem was very similar to yours, and i'll describe my scenario before answering the question.
Created a simple WCF service (using custom binding, but that's irrelevant).
Created a self-signed RootCA using makecert, and generated two certs tempCertServer.cer used for SSL encryption, configure IIS to require https, etc.
--> Tested this part, worked ok from the Browser from a different computer.
The second cert tempCertClient.cer was used as a client-cert to be presented to IIS, configure IIS to Require client-cert, etc. --> Tested this part from a browser (best to use IE since you can easily clear SSL state). I get a prompt to choose a client cert, but never connects, the error is exactly the same as per the question:
"The HTTP request was forbidden with client authentication scheme 'Anonymous'. Inner exception: The remote server returned an error: (403) Forbidden."
Replaced tempCertClient with a proper cert (from a known CA), there was no issue, connection was established and WCF page shown; No matter what i tried with the self-signed client cert, always getting above error.
Wasted a whole day++ trying various settings, reading blogs on registry changes, placing the cert server-side under different cert stores, changing config file settings, etc, with no resolution.
The answer was very simple, inspect the LocalComputer\Trusted Root Certification Authorities server-side, and remove any NON-ROOT CA's (i.e. those that should not be there, IssuedTo NOT EQUALS IssuedBy)
The client-cert itself did not need to be installed on the server, only a Root CA that can validate it has to be installed in LocalComputer\Trusted Root Certification Authorities server-side.
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.
Few days ago I had quite a headache with authentication problems when using Windows authentication between client and wcf web service. The error I was getting was "The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was "NTLM". None of the solutions on stack worked because most of them were related to old methods.
THE ANSWER: The problem was all of the posts for such an issue were related to older kerberos and IIS issues where proxy credentials or AllowNTLM properties were helping. My case was different. What I have discovered after hours of picking worms from the ground was that somewhat IIS installation did not include Negotiate provider under IIS Windows authentication providers list. So I had to add it and move up. My WCF service started to authenticate as expected. Here is the screenshot how it should look if you are using Windows authentication with Anonymous auth OFF.
You need to right click on Windows authentication and choose providers menu item.
Hope this helps to save some time.
I have upgraded my older version of WCF to WCF 4 with below changes, hope you can also make the similar changes.
1. Web.config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="Demo_BasicHttp">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="InheritedFromHost"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="DemoServices.CalculatorService.ServiceImplementation.CalculatorService" behaviorConfiguration="Demo_ServiceBehavior">
<endpoint address="" binding="basicHttpBinding"
bindingConfiguration="Demo_BasicHttp" contract="DemoServices.CalculatorService.ServiceContracts.ICalculatorServiceContract">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Demo_ServiceBehavior">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" 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"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add scheme="http" binding="basicHttpBinding" bindingConfiguration="Demo_BasicHttp"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
2. App.config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_ICalculatorServiceContract" maxBufferSize="2147483647" maxBufferPoolSize="33554432" maxReceivedMessageSize="2147483647" closeTimeout="00:10:00" sendTimeout="00:10:00" receiveTimeout="00:10:00">
<readerQuotas maxArrayLength="2147483647" maxBytesPerRead="4096" />
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" proxyCredentialType="None" realm="" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:24357/CalculatorService.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ICalculatorServiceContract" contract="ICalculatorServiceContract" name="Demo_BasicHttp" />
</client>
</system.serviceModel>
Not this exact problem, but this is the top result when googling for almost the exact same error:
If you see this problem calling a WCF Service hosted on the same machine, you may need to populate the BackConnectionHostNames registry key
In regedit, locate and then click the following registry subkey: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0
Right-click MSV1_0, point to New, and then click Multi-String Value.
In the Name column, type BackConnectionHostNames, and then press ENTER.
Right-click BackConnectionHostNames, and then click Modify.
In the Value data box, type the CNAME or the DNS alias, that is used for the local shares on the computer, and then click OK.
Type each host name on a separate line.
See Calling WCF service hosted in IIS on the same machine as client throws authentication error for details.
For me the solution was besides using "Ntlm" as credential type:
XxxSoapClient xxxClient = new XxxSoapClient();
ApplyCredentials(userName, password, xxxClient.ClientCredentials);
private static void ApplyCredentials(string userName, string password, ClientCredentials clientCredentials)
{
clientCredentials.UserName.UserName = userName;
clientCredentials.UserName.Password = password;
clientCredentials.Windows.ClientCredential.UserName = userName;
clientCredentials.Windows.ClientCredential.Password = password;
clientCredentials.Windows.AllowNtlm = true;
clientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
}
The solution for me was to set the AppPool from using the AppPoolIdentity to the NetworkService identity.
I had the same problem, to solve it set specific user from domain in iis -> action sidebar->Basic Settings -> Connect as... -> specific user
I have WCF services hosted on a console application and a web application accessing its operations. I have searched for WCF security and in most cases the web services were hosted on IIS. What points should I follow in order to implement WCF transport layer security in my case?
What I want is
Using username and password to execute WCF operations
Use SSL to encrypt data.
If my WCF services are hosted on a console application. Are there any IIS configurations that I should make?
If you want to expose WCF service over HTTP you can use BasicHttpBinding with custom configuration:
<bindings>
<basicHttpBinding>
<binding name="secured">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="userName" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="securedService">
<serviceMetadata httpsGetEnabled="true" />
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Namespace.Type, assembly" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Namespace.Type" behaviorConfiguration="securedService">
<host>
<baseAddresses>
<!-- some url -->
<baseAddress baseAddress="https://localhost:8088/Service" />
</baseAddresses>
</host>
<endpoint address="" contract="Namespace.Type" binding="basicHttpBinding" bindingConfiguration="secured" />
<endpoint address="mex" contract="IMetadataExchange" binding="mexHttpsBinding" />
</service>
</services>
This will create SOAP 1.1 service using HTTPS and UserName token profile for transporting credentials in the message. It will also expose metadata (WSDL) over HTTPS and user name and password will be validated by custom validator. Default validation validates windows accounts but it can also be reconfigured to use ASP.NET membership provider.
The last thing you need to do is allowing HTTPS on used port (8088 in the example). For this you need a certificate with private key installed in certificate store on the machine (should be in My / Personal store in LocalMachine). You can create self signed certificate for test purposes.
Once you have a certificate you must assign the certificate to the port by using netsh. You should also allow application to listen on the port by using netsh otherwise your console application will have to run as admin (UAC - Windows Vista, 7, 2008, 2008 R2).
If your WCF Services are hosted in a console app, IIS has nothing to do with them, so you don't need to configure IIS or anything.
In order to have transport-layer security, you can use WsHttp or NetTcp binding in combination with SSL.
Have a look at http://www.dotnetspark.com/kb/1502-security-wcf--transport-level.aspx, http://www.packtpub.com/article/microsoft-wcf-security and http://dotnetrobert.com/?q=node/140.