I am trying to call SOAP1.2 service using wsHttpBinding. The service accepts rejects the default Soap12WSAddressing10 message version. It only accepts SOAP12.
One suggestion I could get from the Internet search was to create the TextMessageEncodingElement in a custom binding.
How can it be either be accomplished using code or configuration ?
WSHttpBinding myBinding = new WSHttpBinding();
myBinding.Security.Mode = SecurityMode.Transport;
myBinding.Security.Transport.ClientCredentialType =
HttpClientCredentialType.Certificate;
//MessageVersion = SOAP12
On using the custom wsBinding as well, there is no suggested placeholder to specify the message version.
<wsHttpBinding>
<binding name="customWS">
<security mode="Transport">
<message clientCredentialType="Certificate"></message>
</security>
</binding>
</wsHttpBinding>
Soap12 specify the soapaction by content-type header. I think it is not implemented in net core. I use the following code.
var encoding = new TextMessageEncodingBindingElement(MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None), Encoding.UTF8);
But this is not implemented in net core.
I'm trying to consume a WS-Security enabled service with WCF. Authentication works using a UsernameToken. I'm not very knowledgeable with WCF web service clients, but I think my configuration below works for regular HTTP communication. I (mostly) used this guide to configure it. The main difference is that I used the VS2010 "Add Service Reference" UI instead of a command prompt.
My problem is that I need to do this over HTTPS. When I use <security mode="Message"> in my app.config, I believe my soap envelope contains the needed WS-Security headers. I can't tell for sure because I can't get logging to work. However, I get the following error: The provided URI scheme 'https' is invalid; expected 'http'. Parameter name: via.
Below are the contents of my app.config file, as well as a sample of my client code.
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="Omitted" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Message">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" negotiateServiceCredential="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://omitted.com/service" binding="wsHttpBinding" bindingConfiguration="Omitted" contract="Omitted.Omitted" name="Omitted" />
</client>
</system.serviceModel>
var service = new OmittedClient();
service.ClientCredentials.UserName.UserName = "username";
service.ClientCredentials.UserName.Password = "password";
var response = service.DoSomething(new DoSomethingRequest());
Thanks to 500 - Internal Server error for helping me figure it out. Here are the steps I took:
Generate a proxy using Visual Studio/WCF.
Change the security mode to TransportWithmessageCredential.
Use the following code to specify a username/password.
var client = new WebServiceClient();
client.ClientCredentials.UserName.UserName = "USERNAME";
client.ClientCredentials.UserName.Password = "PASSWORD";
If you get a response back, but WCF complains when processing it, there might be a timestamp missing from the response. If that's the case, try this to fix it.
// WCF complains about a missing timestamp (http://www.west-wind.com/weblog/posts/2007/Dec/09/Tracing-WCF-Messages)
var elements = service.Endpoint.Binding.CreateBindingElements();
elements.Find().IncludeTimestamp = false;
service.Endpoint.Binding = new CustomBinding(elements);
I have a WCF client connecting to a WCF Service hosted in IIS via WsHttpBinding with Message level security and UserName client credential type.
In the client, I specify my username and password in an instance of the generated proxy class representing the service. The one proxy instance is used for all subsequent calls, and the service authenticates these credentials in the custom validator either when I explicitly call Open() or when I make my first call on the service. The validation is only made on this initial call, and not on subsequent calls. e.g.:
var client = new MyServiceClient();
client.ClientCredentials.UserName.UserName = "username";
client.ClientCredentials.UserName.Password = "password"; client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode =
X509CertificateValidationMode.None;
client.GetStuff1(); // authentication is made here
client.GetStuff2(); // already authenticated, no further authentication. Why/How?
client.GetStuff3(); // already authenticated, no further authentication. Why/How?
How is this session maintained? How can I configure the server and/or client so that authentication is done on each call rather than the "session" that seems to exist? Is this not determined by the <reliableSession> which I have off?
The service class is defined with these attributes:
[ServiceBehavior(IncludeExceptionDetailInFaults = true, AutomaticSessionShutdown = false, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
The client's app.config is as follows:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBindingWithAuth" 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="200000000"
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="UserName" negotiateServiceCredential="true"
algorithmSuite="Default"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://testmachine/MyService.svc"
binding="wsHttpBinding" bindingConfiguration="wsHttpBindingWithAuth"
contract="NewServiceIIS.IMyService" name="wsHttpBindingWithAuth">
<identity>
<certificate encodedValue="ZZZZ" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
This was the source of my frustration and now it is a bliss for you (i.e. you dont need to supply user/pass again)!
Yes, authentication is stored in the channel. Once channel opened, the ClientCredentials cannot be changed. Channel establishes a security context which is retained within the Channel. With wsHttpBinding and message security, this is username/password which is sent to the server everytime.
This is by design. The only way to re-authenticate is to close the channel/proxy and create a new proxy.
If you wonder what establishing security context is, have a look at What are the impacts of setting establishSecurityContext="False" if i use https?
I have a example application written in Delphi using /N Software's SOAP component. This application communicates with the GeoCoder site (see geocoder.us) to get latitude and longitude from a provided address. Works ok.
Wrote a very simple WCF client to basically do the same thing but it does not work. I used Fiddler2 to see what is happening.
The Delphi application gets back basic text. My WCF application gets back content that is gzip compressed. This must be the default as I did not set this. When the response comes back there is no means to decompress the data.
I see many many web pages going into detail about setting gzip compression but nothing about disabling this.
The question is how can I get my WCF client to request from the GeoCoder site, a response in plain text (I know that compression is good etc) but in this instance I just want to see this working.
The sites WSDL is at http://rpc.geocoder.us/dist/eg/clients/GeoCoder.wsdl
My source code (its very elementary as I learning this stuff)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ServiceModel;
using GeoCodeTest.ServiceReference1;
namespace GeoCodeTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private GeocoderResult[] LocationResult = null;
private GeoCode_PortTypeClient proxy = null;
private void btnGo_Click(object sender, EventArgs e)
{
LocationResult = proxy.geocode(txtLocation.Text); // always returns a null !!!
geocoderResultBindingSource.DataSource = LocationResult;
}
private void Form1_Load(object sender, EventArgs e)
{
proxy = new GeoCode_PortTypeClient("GeoCode_Port");
}
}
}
This is the app.config file that was generated.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="GeoCode_Binding" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://rpc.geocoder.us/service/soap/" binding="basicHttpBinding"
bindingConfiguration="GeoCode_Binding" contract="ServiceReference1.GeoCode_PortType"
name="GeoCode_Port" />
</client>
</system.serviceModel>
</configuration>
Is there something I can add/remove/change to the app.config so that a WCF client request will ask for plain text like the Delphi application?
Server should compress the response only if your request contains HTTP header Accept-Encoding: gzip. Check your request with Fiddler. If this header is not present in your request, the compression is controlled by some custom mechanism.
Only WCF 4 HTTP based client sends that HTTP header because it is out of the box able to decompress the message. If it doesn't there is something wrong with the message. You can turn off this feature by defining custom binding:
<bindings>
<customBinding>
<binding name="BasicWithNoCompression">
<textMessageEncoding messageVersion="Soap11" />
<httpTransport decompressionEnabled="false" />
</binding>
</customBidning>
</bindings>
I had a quick look at this, and it is NOT the compression that is causing the issue. As already mentioned, WCF clients (v4) can decompress the data fine. In fact, if you modify the outgoing request message header and remove the "gzip, deflate" from the Accept-Encoding header the response comes back already uncompressed, however the data is still not present in the return object. There seems to be an issue with the way the client has generated its datacontract I think.
If I have some more time, I will have a closer look but it may take sometime to find out where the exact mismatch(s) occur.
I've created one WCF service and deployed it on Server. When I browse this service it gives me positive response with ?wsdl URL. Now I'm trying to test the service through WCF Test client. It shows proper metadata. But when I try to invoke any of the method from the service it shows me an exception... here are the erro details with stack trace..
The HTTP request is unauthorized with
client authentication scheme
'Anonymous'. The authentication header
received from the server was
'Negotiate,NTLM'.
Server stack trace:
at
System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(HttpWebRequest
request, HttpWebResponse response,
WebException responseException,
HttpChannelFactory factory)
The HTTP request is unauthorized with client
authentication scheme 'Anonymous'. The
authentication header received from
the server was 'Negotiate,NTLM'.
Server stack trace:
at
System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(HttpWebRequest
request, HttpWebResponse response,
WebException responseException,
HttpChannelFactory factory)
Client Bindings:
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IServiceMagicService" 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="None">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
Server Bindings:
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_SEOService" closeTimeout="00:10:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" bypassProxyOnLocal="true" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="999524288" maxReceivedMessageSize="655360000" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="900000" maxArrayLength="900000" maxBytesPerRead="900000" maxNameTableCharCount="900000" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
<security mode="None">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true" establishSecurityContext="true" />
</security>
</binding>
<binding name="WSHttpServiceMagicBinding" closeTimeout="00:10:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" bypassProxyOnLocal="true" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="999524288" maxReceivedMessageSize="655360000" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="900000" maxArrayLength="900000" maxBytesPerRead="900000" maxNameTableCharCount="900000"/>
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>
<security mode="None">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm=""/>
<message clientCredentialType="Windows" negotiateServiceCredential="true" establishSecurityContext="true"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
Client's Client Section:
<client>
<endpoint address="http://hydwebd02.solutions.com/GeoService.Saveology.com/ServiceMagicService.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServiceMagicService"
contract="IServiceMagicService" name="WSHttpBinding_IServiceMagicService" />
</client>
Server's Services Section:
<services>
<service behaviorConfiguration="GeoService.Saveology.com.CityStateServiceProviderBehavior"
name="GeoService.Saveology.com.CityStateServiceProvider">
<endpoint binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_SEOService"
contract="SEO.Common.ServiceContract.ICityStateService" />
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
contract="IMetadataExchange" />
</service>
<service behaviorConfiguration="GeoService.Saveology.com.ServiceMagicServiceProviderBehavior"
name="GeoService.Saveology.com.ServiceMagicServiceProvider">
<endpoint binding="wsHttpBinding" bindingConfiguration="WSHttpServiceMagicBinding"
contract="SEO.Common.ServiceContract.IServiceMagicService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="" contract="IMetadataExchange" />
</service>
</services>
I didn't have control over the security configuration for the service I was calling into, but got the same error. I was able to fix my client as follows.
In the config, set up the security mode:
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
In the code, set the proxy class to allow impersonation (I added a reference to a service called customer):
Customer_PortClient proxy = new Customer_PortClient();
proxy.ClientCredentials.Windows.AllowedImpersonationLevel =
System.Security.Principal.TokenImpersonationLevel.Impersonation;
I have a similar issue, have you tried:
proxy.ClientCredentials.Windows.AllowedImpersonationLevel =
System.Security.Principal.TokenImpersonationLevel.Impersonation;
Another possible solution to this error that I found. Might not have answered OP's exact question but may help others who stumble across this error message.
I was creating my Client in code using WebHttpBinding, in order to replicate the following line:
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" proxyCredentialType="Windows" />
</security>
I had to do:
var binding = new WebHttpBinding(WebHttpSecurityMode.TransportCredentialOnly);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.Windows;
as well as setting proxy.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
I had a similar problem and tried everything suggested above. Then I tried changing the clientCreditialType to Basic and everything worked fine.
<basicHttpBinding>
<binding name="BINDINGNAMEGOESHERE" >
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"></transport>
</security>
</binding>
</basicHttpBinding>
I see this isn't answered yet, this is an exact quote from here:
WSHttpBinding will try and perform an internal negotiate at the SSP layer. In order for this to be successful, you will need to allow anonymous in IIS for the VDir. WCF will then by default perfrom an SPNEGO for window credentials. Allowing anonymous at IIS layer is not allowing anyone in, it is deferring to the WCF stack.
I found this via: http://fczaja.blogspot.com/2009/10/http-request-is-unauthorized-with.html
After googling: http://www.google.tt/#hl=en&source=hp&q=+The+HTTP+request+is+unauthorized+with+client+authentication+scheme+%27Anonymous
Here's what I had to do to get this working. This means:
Custom UserNamePasswordValidator (no need for a Windows account, SQLServer or ActiveDirectory -- your UserNamePasswordValidator could have username & password hardcoded, or read it from a text file, MySQL or whatever).
https
IIS7
.net 4.0
My site is managed through DotNetPanel. It has 3 security options for virtual directories:
Allow Anonymous Access
Enable Basic Authentication
Enable Integrated Windows Authentication
Only "Allow Anonymous Access" is needed (although, that, by itself wasn't enough).
Setting
proxy.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
Didn't make a difference in my case.
However, using this binding worked:
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Windows" />
<message clientCredentialType="UserName" />
</security>
I had the same error today, after deploying our service calling an external service to the staging environment in azure. Local the service called the external service without errors, but after deployment it didn't.
In the end it turned out to be that the external service has a IP validation. The new environment in Azure has another IP and it was rejected.
So if you ever get this error calling external services
It might be an IP restriction.
I had this error too , and finally this codes worked for me in dot net core 3.1
first install svcutil in command prompt : dotnet tool install --global dotnet-svcutil
Then close command prompt and open it again.
Then create the Reference.cs in command prompt :
dotnet-svcutil http://YourService.com/SayHello.svc
(It needs an enter key and UserName and Password)
Add a folder named Connected Services to project root.
Copy Reference.cs file to Connected Services folder.
Add these 4 lines to Reference.cs after lines where creating BasicHttpBinding and setting MaxBufferSize :
result.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
result.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
result.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
result.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
Use this service in your Controller :
public async Task<string> Get()
{
try
{
var client = new EstelamClient();
client.ClientCredentials.UserName.UserName = "YourUserName";
client.ClientCredentials.UserName.Password = "YourPassword";
var res = await client.EmployeeCheckAsync("service parameters");
return res.ToString();
}
catch (Exception ex)
{
return ex.Message + " ************ stack : " + ex.StackTrace;
}
}
Do not forget install these packages in csproj :
<PackageReference Include="System.ServiceModel.Duplex" Version="4.6.*" />
<PackageReference Include="System.ServiceModel.Http" Version="4.6.*" />
<PackageReference Include="System.ServiceModel.NetTcp" Version="4.6.*" />
<PackageReference Include="System.ServiceModel.Security" Version="4.6.*" />
Just got this problem on a development machine (production works just fine). I modify my config in IIS to allow anonymous access and put my name and password as credential.
Not the best way I am sure but it works for testing purposes.
Try providing username and password in your client like below
client.ClientCredentials.UserName.UserName = #"Domain\username";
client.ClientCredentials.UserName.Password = "password";