Ignore Certificate Error in a Web Service? - c#

Is there a way of ignoring SSL certificate errors?
I have developed a web service which until now has been running locally using http, however it has been moved externally and needs to communicate via https. The certificate for testing purposes is self-signed and therefore not trusted and I am getting the error The provided URI scheme 'https' is invalid; expected 'http'.
Web.config
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="RemoteSoap" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://mydomainwebservice:8444/Test.asmx" binding="basicHttpBinding"
bindingConfiguration="RemoteSoap" contract="RemoteService.RemoteSoap"
name="RemoteSoap" />
</client>
</system.serviceModel>
If I add the following security element I then get the following error The remote certificate is invalid according to the validation procedure. which seems to be caused by The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
Can someone kindly advise as to ignore these errors?

Try editing the config values in the .config
<configuration>
<system.net>
<settings>
<servicePointManager
checkCertificateName="false"
checkCertificateRevocationList="false"
/>
</settings>
</system.net>
</configuration>

Related

Debug local WCF service with Basic Authentication always returns 401 - Unauthorized

I have a problem accessing a .Net WCF Service that uses Basic authentication. The server's web.config file has the service configured as such:
<services>
<service behaviorConfiguration="serviceBehavior" name="api.GlobalService">
<endpoint address="" behaviorConfiguration="restBehavior" binding="basicHttpBinding"
bindingConfiguration="Basic" contract="api.IGlobalService" />
</service>
</services>
with the binding:
<bindings>
<basicHttpBinding>
<binding name="Basic">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
In my IIS Express config file I enabled basic authentication as such:
<basicAuthentication enabled="true" />
I am running it in debug mode, on localhost, and I don't want a custom basic authentication, I want it to authenticate against Windows credentials. I access the server directly, from the browser, and enter my windows credentials when prompted, or from Postman using basic authentication and credentials, however I always get a 401. I am not authorized to access a server I run on my own machine with my own credentials. Any help on what I'm doing wrong?
You can try the following, in the application that consumes the WCF Service
WCFServiececlient.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
WCFServiececlient.ChannelFactory.Credentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;

WCF service with transport level security - Service unavailable

I have service with transport level security when I have changed http to https , i am unable to expose operation contract as it is showing site can't be reached in browser itself.
Below is my config file
<wsHttpBinding>
<binding name="transport">
<security mode="Transport">
<transport clientCredentialType="None">
</transport>
</security>
</binding>
</wsHttpBinding>
<service name="WcfService1.Service1">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="transport" contract="WcfService1.IService1"></endpoint>
</service>
My service is hosted via IISExpress where Project URL is as below
https://localhost:49500/
And also SSL is enabled with SSL URL which is different from http URL.
I have tried many possible way as stated in SO but couldn't able to find solution for this.
Please help!

C# SOAP Client use TLS instead of SSL 3.0

I have a C# application which is using Travelport Universal API interfaces through SOAP communication.
In C# I used the wsdls for generating the SOAP client.
I have this config settings for HTTPS connection (this was generated by Visual Studio from WSDL):
<system.serviceModel>
<bindings>
<basicHttpsBinding>
<binding name="AirLowFareSearchBinding" maxBufferSize="2097152" maxReceivedMessageSize="2097152">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpsBinding>
</bindings>
<client>
<endpoint address="https://emea.universal-api.travelport.com/B2BGateway/connect/uAPI/AirService" binding="basicHttpsBinding" bindingConfiguration="AirLowFareSearchBinding" contract="AirServiceReference.AirLowFareSearchPortType" name="AirLowFareSearchPort" />
</client>
About this SSL3.0 vulnerability Travelport want to disabling SSL3, and I could use just over TLS.
My question is what should I change on this config, or should I change anything for TLS connection on https instead of SSL3.
In you code before calling to the service:
system.Net.ServicePointManager.SecurityProtocol=SecurityProtocolType.Tls12;
Here is a blog post Here

Intranet - web to remote wcf CredentialCache.DefaultNetworkCredentials not working

I have a ASP.NET MVC intranet application hosted in IIS that added WCF service reference the WCF resides in another computer and also expect windows authentication.
In my web this code is working great:
proxy = new MyProxyClient("configurationName", "remoteAddress");
proxy.ClientCredentials.Windows.ClientCredential.UserName = "myUserName";
proxy.ClientCredentials.Windows.ClientCredential.Password = "MyPassword";
proxy.SomeMethod(); //work great
but if I want the credential not to be hardcoded like this I am using: CredentialCache.DefaultNetworkCredentials like this:
proxy = new MyProxyClient("configurationName", "remoteAddress");
proxy.ClientCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
proxy.SomeMethod(); //not working throw exception
the above code throw SecurityNegotiationException with message: The caller was not authenticated by the service.
and the inner exception is: The request for security token could not be satisfied because authentication failed.
How can I pass the credential of the current user to the WCF service without hardcoded user name and password?
If your organization uses regular Windows authentication (NTLM) you can't do what you want due to "one-hop" restriction: credentials passed from user's computer to your server use "one-hop" (from direct login to one external computer) and such credentials can't be used to authenticate other servers from the first one.
More information can be found using following search term:ntlm one hop,i.e. Why NTLM fails and Kerberos works.
Standard solution:
Kerberos (often requires significant effort to get approval to enable/configure)
Use some other form of authentication than Windows. Consider if OAuth is possible. Don't go basic auth.
Switch WCF service to claims based authentication.
If WCF service can it can trust caller to verify incoming credentials more approaches are possible:
Run code under particular account that signs in locally on server and have permissions to call the service. The easiest approach is what shown in your post, but storing domain passwords (or any passwords) in plain text is not secure. One can also run process account under special credentials that have access to the remote service and temporary revert impersonation after verifying user credentials.
You can also configure WCF service to require client certificate and use such certificate when calling the WCF service. This way WCF service can verify if caller is known.
In the web.config (client and server), in the <system.serviceModel> section add/modify a binding to look something like this:
<basicHttpBinding>
<binding name="MyBasicBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
And, add this to client side web.config <system.web> section:
<identity impersonate="true" />
<authentication mode="Windows" />
The two changes will make the end-user the current user of the web request which will then be sent in the WCF message.
The user can then be retrieved on the server side like this:
ServiceSecurityContext.Current.WindowsIdentity
Please make sure the following configuration is there in service web.config.
<system.serviceModel>
<services>
<service name="MyWcf.Service1" behaviorConfiguration="MySvcBehavior">
<endpoint address="" binding="wsHttpBinding" contract="MyWcf.IService1" bindingConfiguration="MyWsHttpBinding"></endpoint>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="MyWsHttpBinding">
<security mode="Message">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</wsHttpBinding>
<basicHttpBinding>
<binding name="MyBasicBinding">
<security mode="Message">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="MySvcBehavior">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="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>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
And in your client configuration file following should be there.
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService1">
<security>
<transport clientCredentialType="Windows" />
<message clientCredentialType="Windows" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/MyWcf/Service1.svc" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IService1" contract="MyWCFService.IService1"
name="WSHttpBinding_IService1">
</endpoint>
</client>
</system.serviceModel>
I tried by passing System.Net.CredentialCache.DefaultNetworkCredentials using above configuration and working fine for me. If it's not working for you then put debug point on line which passing credential and watch that System.Net.CredentialCache.DefaultNetworkCredentials Domain, UserName & Password values are blank or not. If Blank then it should work.
I assume that if you're looking within your CredentialCache.DefaultNetworkCredentials attribut you won't see the credential information.
From Microsoft website : The authentication informations return by the DefaultNetworkCredentials property will be only available for NTLM, Negotiate or Kerberos authentication.
To get your credential you need to implement this authentication.
You can use it by using impersonation wihtin your intranet application.
Impersonation allow your intranet application to be executed by the user of this one.
More information here :http://technet.microsoft.com/en-us/library/cc961980.aspx

Sporadic exceptions calling a web service that is load balanced

I have a web service that I am running on three load balanced web servers and I am getting sporadic errors. Now, I admit that the load balanced part may be a bit of a red herring, but when I test with only 1 web server I cannot reproduce the error. If I test with all three web servers I can get the error (but it is not 100% of the time, more like 50%). All testing is done through the load balancer, we just tell the load balancer how many servers we want to farm.
The code is simple single request code. That is, there is no state. A request is made and a response is returned. The web service code is c# .NET 4 running on IIS 7.5. The client code is both a web site and a desktop app.
I get one of two exceptions:
System.ServiceModel.Security.MessageSecurityException:
An unsecured or incorrectly secured
fault was received from the other
party. See the inner FaultException
for the fault code and detail. --->
System.ServiceModel.FaultException:
The security context token is expired
or is not valid. The message was not
processed.
Or I get:
System.ServiceModel.Security.SecurityNegotiationException:
Secure channel cannot be opened
because security negotiation with the
remote endpoint has failed. This may
be due to absent or incorrectly
specified EndpointIdentity in the
EndpointAddress used to create the
channel. Please verify the
EndpointIdentity specified or implied
by the EndpointAddress correctly
identifies the remote endpoint. --->
System.ServiceModel.FaultException:
The request for security token has
invalid or malformed elements.
As you can see from the following snips from my .config files, I am not using security as this is strictly an internal web service. (names have been changed to protect the innocent--namely me).
Server Side:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- Service Side web.config -->
...
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<services>
<service behaviorConfiguration="InternalUseOnly.InternalUseOnlyServiceBehavior" name="InternalUseOnly.InternalUseOnlyService">
<endpoint address="" bindingNamespace="http://somecompany.com/webservices" binding="wsHttpBinding" contract="InternalUseOnly.IInternalUseOnlyService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="InternalUseOnly.InternalUseOnlyServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
...
</configuration>
Client side
<?xml version="1.0" encoding="UTF-8"?>
<!-- Client Side web.config -->
<configuration>
...
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IInternalUseOnlyService" 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" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://intranet.somecompany.com/InternalUseOnly/InternalUseOnlyService.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IInternalUseOnlyService" contract="InternalUseOnlyService.IInternalUseOnlyService" name="WSHttpBinding_IInternalUseOnlyService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
...
</configuration>
Thoughts anyone?
Additional information: After reviewing the answers below I have tried two things, both without success.
The most obvious change (which I did not notice at first) was to change one of properties on the client to allow cookies <system.serviceModel><bindings><wsHttpBinding><binding name="blah, blah, blah" ... other properties... allowCookies="true" /> It defaults to false. Further, our load balancer uses cookies to keep affinity. But, it did not make a difference (no clue why yet).
Next, I tried various security options in the client side app.config file. This included both <security mode="None" /> and a more elaborate:
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None" />
<message clientCredentialType="None" establishSecurityContext="false" negotiateServiceCredential="false"/>
</security>
although the settings in the last one was just a guess on my part. I did not make any server side changes to the app.config as I don't know what to change and, sadly, I can only test with production as we only have 1 dev web server, not three.
I am going to go out on a limb here and guess that the security involved is the Message security specified on the client side:
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" />
</security>
If you are creating a client and connecting, the negotiated windows credential token may be cached. If you don't have sticky sessions enabled, the token might be passed back to the wrong server and will fail. My guess is that its always on the second call?
It is an NTLM problem caused by using load balancers without sticky sessions. To correct the problem you need to configure session affinity (sticky session). If you don't you will get a failure because part of the NTLM handshake happened on one server and the other part happens on another server.
While Chris and Jeff have help get me on the track to an answer, what actually solved it for me was this article i found from Microsoft on Load Balancing Web Services. In short, what we had to do to resolve this for our web farm was to switch from the default wsHttpBinding to basicHttpBinding. This was not difficult, but was an all-or-nothing move. The main web service and every client had to be reconfigured at the same time or it would break.
While wsHttpBinding does have a property of allowCooikes that could be set to true, it apparently does not use them until after the connection is made, at which point the request could jump servers on the first request and thus fail.

Categories

Resources