Consuming WCF service (WsHttp Binding) in NodeJs - c#

I am trying to consume a WCF service using NodeJS. I tried BasicHttpBinding with security mode="TransportWithMessageCredential". It is working fine.
But if I try to consume the service with WsHttpBinding and security mode="TransportWithMessageCredential", the following error is thrown:
"The message could not be processed. This is most likely because the
action 'http://tempuri.org/IService1/GetData' is incorrect or because
the message contains an invalid or expired security context token or
because there is a mismatch between bindings. The security context
token would be invalid if the service aborted the channel due to
inactivity. To prevent the service from aborting idle sessions
prematurely increase the Receive timeout on the service endpoint's
binding."
This is my web config
<bindings>
<wsHttpBinding>
<binding name="WsHttpBinding" maxReceivedMessageSize="104857600" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:01:00" sendTimeout="00:01:00" messageEncoding="Text" textEncoding="utf-8">
<!--Maximum size of the message which can be processed by the binding is 100 MB-->
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None"/>
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="WcfService1.Service1" behaviorConfiguration="DefaultServiceBehaviors">
<endpoint address="" binding="wsHttpBinding" contract="WcfService1.IService1" name="WsHttpEndpoint" bindingConfiguration="WsHttpBinding"/>
</service>
</services>
This is my NodeJS file
var WSHttpBinding = require('wcf.js').WSHttpBinding
, Proxy = require('wcf.js').Proxy
, binding = new WSHttpBinding(
{
SecurityMode: "TransportWithMessageCredential"
, TransportClientCredentialType:"None"
, MessageClientCredentialType: "UserName"
})
, proxy = new Proxy(binding, "https://localhost:44301/Service1.svc")
, message = '<Envelope xmlns="http://www.w3.org/2003/05/soap-envelope">'+
'<Body>'+
'<GetData xmlns="http://tempuri.org/">'+
'<value>12345</value>'+
'</GetData>'+
'</Body>'+
'</Envelope>'
proxy.ClientCredentials.Username.Username = "xyz"
proxy.ClientCredentials.Username.Password = "xyz"
proxy.send(message, "http://tempuri.org/IService1/GetData",
function(response, ctx) {
console.log(response)
});

Related

WCF Windows authentication not working with wsHttpBinding

Problem is that I cannot get windows authentication working with the wsHttpBinding.
This is the config:
<services>
<service name="WcfService1.Service1">
<endpoint address="" bindingConfiguration="testbinding" contract="WcfService1.IService1" binding="wsHttpBinding"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="testbinding">
<security mode="Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
This is the response from the server when trying to call a method:
The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate oXMwcaADCgEBomoEaGBmBgkqhkiG9xIBAgIDAH5XMFWgAwIBBaEDAgEepBEYDzIwMTcwODE2MjA1MjQwWqUFAgMK8G2mAwIBKakOGwxDT1JQLlNBQUIuU0WqGjAYoAMCAQGhETAPGw1jb3JwYXBwbDU5ODgk'.
Also there is a inner exception saying:
"The target principal name is incorrect"
I have setup a new site in IIS fresh for testing purposes with windows authentication enabled and Everything else disabled(I am not doing any ASP impersonation/double hop). Providers for windows authentication is Negotiate,Ntlm. Kernel mode authentication is enabled.
The application pool is running with a Active Directory service account.
The goal in the end is to use Kerberos for authentication but since it doesn't even work with Ntlm I have not started with the SPN and that stuff to get kerberos working yet.
It does however work if I change the application pool to be run with "ApplicationPoolIdentity" and not a AD service account?
I must have the app pool running with the AD service account.
If I change the config to:
<services>
<service name="WcfService1.Service1">
<endpoint address="" bindingConfiguration="hbinding" contract="WcfService1.IService1" binding="basicHttpsBinding"/>
</service>
</services>
<bindings>
<basicHttpsBinding>
<binding name="hbinding">
<security mode="Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpsBinding>
It works fine(keeping the AD service account as well), why is that?
I dont wanna use basicHttpsBinding
I see a difference in the client config file (using the wcftestclient) that when using wshttp it has:
<identity>
<userPrincipalName value="serviceaccount#contoso.com" />
</identity>
Does it have something to do with this? (Just guessing wildly here)
The endpoint is https,IIS 8 on Windows Server 2012R2.
A lot of it depends on how is your domain set up, but you might try different type of Client credential type:
<services>
<service name="WcfService1.Service1">
<endpoint address="" bindingConfiguration="testbinding" contract="WcfService1.IService1" binding="wsHttpBinding"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="testbinding">
<security mode="Transport">
<transport clientCredentialType="Ntlm"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
Also, with wsHttpBinding there is negotiation that takes place behind the scene. Because the guidance on that negotiation is not specifically defined it makes sense sometimes to turn it off:
<services>
<service name="WcfService1.Service1">
<endpoint address="" bindingConfiguration="testbinding" contract="WcfService1.IService1" binding="wsHttpBinding"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="testbinding">
<security mode="Transport">
<message negotiateServiceCredential="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
A Kerberos domain must exist for it to work.
On the client side the generated identity tag was causing the issue
<identity>
<userPrincipalName value="serviceaccount#contoso.com" />
</identity>
If i clear the value it works fine.
So i cleared that value in the web.config.
I can now setup kerberos and it works fine as well, gonna try setting the servicePrincipalName tag as well.

wcf https with basic auth

I am trying to consume a service over https with basic auth.
Binding:
<bindings>
<wsHttpBinding>
<binding name="apiSoap11">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</wsHttpBinding>
<client>
<endpoint address="https://url"
binding="wsHttpBinding"
bindingConfiguration="apiSoap11"
contract="api"
name="apiSoap11" />
</client>
Code
var client = new Client();
client.ClientCredentials.UserName.UserName = "username";
client.ClientCredentials.UserName.Password = "password";
var response = client.operation(request);
I am being returned a 500 error.
This request will works in SoapUi with basic auth and PasswordType ="PasswordText"
Any idea what I am missing.

C# WCF Service Result

The HTTP request is unauthorized with client authentication scheme 'Basic'. The authentication header received from the server was 'Basic realm= Default Realm '.--The HTTP request is unauthorized with client authentication scheme 'Basic'. The authentication header received from the server was 'Basic realm= Default Realm '.
Hi,
what is the meaning of the result which I mentioned above. I got this error message from one of services. It was working before I update the service reference.
You can see web.configuration belove
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="MCCI_AR000001TR_Binding">
<security mode="Transport"/>
</binding>
</basicHttpBinding>
</bindings>
<client><endpoint address="https://ws.sagliknet.saglik.gov.tr/WSMuayene" binding="basicHttpBinding" bindingConfiguration="MCCI_AR000001TR_Binding" contract="MuayeneServiceReference.MCCI_AR000001TR_PortType" name="MCCI_AR000001TR_Port"/>
</client>
</system.serviceModel>
I assume you need to set the configuration as basic credential and you need also to pass you credential prior to create a channel.
<bindings>
<basicHttpBinding>
<binding name="MCCI_AR000001TR_Binding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</basicHttpBinding>
</bindings>

webHttpBinding having issue with posting 1MB xml file

I have webHttpBinding for wcf service. Can not post large xml file (1MB) to service getting following error RequestEntityTooLarge (413) is not one of the following: OK (200), Created (201), Accepted (202), NonAuthoritativeInformation (203), NoContent (204), ResetContent (205), PartialContent (206)"} System.Exception {System.ArgumentOutOfRangeException}
Here is configuration for wcf service..
<service name="abc" >
<endpoint address="http://localhost:8741/LTLInboundService/" binding="webHttpBinding" behaviorConfiguration="WebHttpBehaviour" contract="abc" name="webHttpBinding_LTLInboundService" >
</endpoint>
</service>
<webHttpBinding>
<binding name="webHttpBinding_LTLInboundService" closeTimeout="00:10:00"
openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
allowCookies="false" bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647"
maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
transferMode="Streamed"
useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</webHttpBinding>
Here is the code that is failing..
using (HttpClient client = new HttpClient("http://localhost:8741/LTLInboundService" + "/SendCompletionReports"))
{
// Initalise a response object
HttpResponseMessage response = null;
string responseFilePath = Path.Combine(#"c:\Samir\abc.xml");
string xmlData = System.IO.File.ReadAllText(responseFilePath);
// Create a content object for the request
HttpContent content = HttpContent.Create(xmlData, Encoding.UTF8, "text/xml");
// Make the request and retrieve the response
response = client.Post("http://localhost:8741/LTLInboundService" + "/SendCompletionReports", content);
// Throw an exception if the response is not a 200 level response
response.EnsureStatusIsSuccessful();
// Retrieve the content of the response for processing
response.Content.LoadIntoBuffer();
}
It fails on response.EnsureStatusIsSuccessful(); statement.
Any idea how to fix this in development and production ?
checkout this site and pay attention to how they have this section configured under the security section
Dealing with Larger Files in Asp.NET
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483648" />
</requestFiltering>
</security>
</system.webServer>
You defined a webHttpBinding in your config file, but it's not being used by your service because you did not specify it in the bindingConfiguration attribute.
<service name="abc" >
<endpoint address="http://localhost:8741/LTLInboundService/"
binding="webHttpBinding"
behaviorConfiguration="WebHttpBehaviour" contract="abc"
name="webHttpBinding_LTLInboundService" >
</endpoint>
</service>
The name attribute is used for the endpoint configuration, but has no bearing on the binding configuration used. In your <endpoint> element add this:
bindingConfiguration="webHttpBinding_LTLInboundService"
so your defined endpoint will use the values for the binding specified, not the default.
Final endpoint would look like this:
<service name="abc" >
<endpoint address="http://localhost:8741/LTLInboundService/"
binding="webHttpBinding"
bindingConfiguration="webHttpBinding_LTLInboundService"
behaviorConfiguration="WebHttpBehaviour" contract="abc"
name="webHttpBinding_LTLInboundService" >
</endpoint>
</service>

WCF Windows Authentication, not being passed

In one of my applications I am having issues connecting and authenticating a WCF service via the windows account. To test this I have moved it into a new solution with a simple console app and the standard WCF start application in VS2010.
WCF Code, for a simple action:
[PrincipalPermission(SecurityAction.Demand, Role = "xxxx\\xxxxxx")]
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
The configuration file:
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService1">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" proxyCredentialType="Windows"/>
<message clientCredentialType="UserName" algorithmSuite="Default"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:16674/Service1.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IService1" contract="testService.IService1"
name="BasicHttpBinding_IService1" />
</client>
And the call to this:
testService.Service1Client sv = new testService.Service1Client();
sv.GetData(1);
I'm getting the standard 'Request for principal permission failed.' error although I can't see how the config file is wrong. I've looked at the service object when it is being created and the ClientCredentials.Windows and username objects are null. Can anyone help me out, am I being stupid here?
Thanks
You need to set the credentials using code, see this article
testService.Service1Client sv = new testService.Service1Client();
sv.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultCredentials;
sv.GetData(1);

Categories