TransportWithMessageCredential: Windows credentials are not being passed to WCF service - wcf

I'm having problems setting up TransportWithMessageCredential on my wcf service.
Using the wcf Configuraton Editor, I set the Mode to TransportWithMessageCredential and the transportClientCredentialType to Windows in the web.config for the service and the app.config for my executable. I installed a self signed Cert on the erver and configured IIS to use it.
When I run my test app, I receive the following error:
System.InvalidOperationException: The username is not provided. Specify username in ClientCredentials.
It appears that the Windows credentials are not being passed to the wcf service and when i check the credentialCache.defaultCredentials, they are null. Any clues and/or tips on why this is and how to fix it? Thanks in advance
server 2003 / IIS 6.0 on an active directory domain.
web.config for service
<service name="Test.DiagnosticService">
<endpoint binding="basicHttpBinding" bindingConfiguration="WindowsTransportCredentialBinding" name="ClientDiagnosticEndpoint" contract="Test.IDiagnostic" />
</service>
<basicHttpBinding>
<binding name="WindowsTransportCredentialBinding" maxBufferSize="524288"
maxReceivedMessageSize="524288">
<readerQuotas maxDepth="128" maxStringContentLength="1048576" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Windows" proxyCredentialType="Windows" />
</security>
</binding>
app.config for executable
<client>
<endpoint address="https://U-WM-3vIntegr8/test/Web/Services/Diagnostic.svc"
binding="basicHttpBinding" bindingConfiguration="ClientHttpEndpoint"
contract="Test.IDiagnostic" name="ClientDiagnosticEndpoint" />
</client>
<basicHttpBinding>
<binding name="ClientHttpEndpoint" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:02:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="4194304" maxBufferPoolSize="524288" maxReceivedMessageSize="4194304"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="1048576"
maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Windows" proxyCredentialType="Windows"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
...Called from client
public static IDiagnostic GetDiagnosticService()
{
return new ChannelFactory<IDiagnostic>("ClientDiagnosticEndpoint").CreateChannel();
}

you need to manually fill in the credentials, they will not be automatically passed in this configuration. if that's what you look for you should set clientCredentialType to "Windows" on both client and server. Right now you need to set it manually:
proxy.ClientCredentials.Username.User = ""
proxy.ClientCredentials.Username.Password = ""

Related

readerQuotas maxStringContentLength is not changing

I have tried lot but no success,
I have changed readerQuotas maxStringContentLength to 2147483647 of both my WinForms as well as WCF config files but still maxStringContentLength is set to 8192.
Can any body tell me how to change it and where to change, on WinForms or WCF service.
Client side Config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="ConnectWiseEntities" connectionString="data source=deepak;initial catalog=ConnectWise;persist security info=True;user id=sa;password=weexcel;" providerName="System.Data.EntityClient" />
</connectionStrings>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:50841/SyncFile(WCF2)/Service.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService"
contract="SynWebService.IService" name="BasicHttpBinding_IService" />
</client>
</system.serviceModel>
</configuration>
WCF Web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above 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 multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Your client config seems ok, modifiy your service config and add the corresponding behavior to the service as below.
You need to correctly setup the binding and behavior.Right click your web config and select edit WCF configuration.
for example,
<bindings>
<basicHttpBinding>
<binding name="defaultBinding">
<readerQuotas maxStringContentLength="1048576" />
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="Service1">
<endpoint address="http://localhost:56529/Service1.svc"
binding="basicHttpBinding" bindingConfiguration="defaultBinding"
contract="IWebExtractServiceIWebExtractService">
</endpoint>
</service>
</services>
You have defined the binding configuration in your service's web config, but you never tell the service to use it, so the default values for basicHttpBinding are used.
In WCF 4.0+, you have two ways to do this (Sajeethran gave one).
You can define a configuration for a binding and set it as the default configuration for the service by omitting the name attribute on the binding configuration, like this:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647" messageEncoding="Text"
textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
Since the name attribute is ommitted, any services that are using this config will use the above binding configuration for the default for requests coming over the http protocol, unless overridden in a specific endpoint element's bindingCongifuration attribute.
The second way is to define an endpoint explicitly and assign the bindingCongifuration attribute the name of the binding configuration you've defined (again as shown in Sajeetharan's answer).

CredentialCache.DefaultNetworkCredentials empty when using TransportWithMessageCredential

I'm currently trying to use TransportWithMessageCredentials and https on my wcf project. I have set both the client and the server security mode="TransportWithMessageCredential" and the clientCredentialType="Windows".
When I go to get the credentials from CredentialCache.DefaultNetworkCredentials, the username, password and domain are all empty.
Any reason why these would be empty? If they will always be empty, where would I get the credentials to pass?
How would I pass the logged in user credentials to the service without prompting them for a login?
Client binding
<basicHttpBinding>
<binding name="ClientHttpEndpoint" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:02:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="4194304" maxBufferPoolSize="524288" maxReceivedMessageSize="4194304"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
Server binding
<basicHttpBinding>
<binding name="WindowsTransportCredentialBinding" maxBufferSize="524288"maxReceivedMessageSize="524288">
<readerQuotas maxDepth="128" maxStringContentLength="1048576" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
...
<service name="Test.DiagnosticService">
<endpoint binding="basicHttpBinding" bindingConfiguration="WindowsTransportCredentialBinding" name="ClientDiagnosticEndpoint" contract="Test.IDiagnostic" />
</service>
Code to set the username and password
ChannelFactory<IDiagnostic> test = new ChannelFactory<IDiagnostic>(DIAGNOSTIC_ENDPOINT_NAME);
test.Credentials.UserName.UserName = "TestUser";
test.Credentials.UserName.Password = "User";
return test.CreateChannel();
The ICredentials instance returned by DefaultCredentials cannot be used to view the user name, password, or domain of the current security context.
http://msdn.microsoft.com/en-us/library/system.net.credentialcache.defaultcredentials%28v=vs.90%29.aspx

WCF Error: The identity check failed for the outgoing message

i am trying to consuming wcf web service and got error
The identity check failed for the outgoing message. The expected identity is 'identity(http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/spn)' for the 'http://localhost/SCVMMService/VirtualMachineManagementService.svc' target endpoint.
for consuming webservice i am using code :
Client.ClientCredentials.Windows.ClientCredential.Domain = "testlab.ourcp.com";
Client.ClientCredentials.Windows.ClientCredential.UserName = "administrator";
Client.ClientCredentials.Windows.ClientCredential.Password = "M!ndMasT23";
Client.ClientCredentials.UserName.UserName = "administrator";
Client.ClientCredentials.UserName.Password = "M!ndMasT23";
Client.Open();
WebConfig:
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IVirtualMachineManagementService" 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://localhost/SCVMMService/VirtualMachineManagementService.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IVirtualMachineManagementService" contract="ServiceReference1.IVirtualMachineManagementService" name="WSHttpBinding_IVirtualMachineManagementService">
<identity>
<servicePrincipalName value="DDC-SC-VMM02.testlab.ourcp.com\Administrator"/>
</identity>
</endpoint>
</client>
and in webService config file for identity use:
<dns value="localhost"/>
Is the WCF service you're trying to access configured to use Service Identity? If not, remove the entire identity element from the endpoint element because it's only used with the Service Indentity feature.

WSHttpBinding binding, client authentication

i am new to wcf and using wshttpbinding ,but i want to remove the user name and password form the service client (which i have to pass),
my client code is
RServiceClient serviceClient = new RServiceClient();
serviceClient.ClientCredentials.Windows.ClientCredential.UserName = "UserName";
serviceClient.ClientCredentials.Windows.ClientCredential.Password = "Password";
i dont want to pass this username and password.
my client app.config is:
<binding name="WSHttpBinding_IRService"
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>
rite now service is hosted in a web.
is there any change in service.config or client side app .config.
in my weak knowledge after googleing is that change should be the client side but i m unable to do that. :-(
note: my contract requires sessions too.
thanx in advance.
You need to change the web.config at the server side, your client web.config will be automatically updated after a refresh on the web reference.
If you do not want to use login/password, i can advice you to set up a mutual certificate authentication.
This approach is secure and interoperable with other WS stacks (eq. Java CXF, ...)
For Mutual Certification Authentication :
You will need a X.509 certificate to allow the client to be sure that the server is really who is pretend to be and an other X.509 certificate at the client-side.
Here an example of web.config, more informations at MSDN :
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="serviceCredentialBehavior">
<serviceCredentials>
<serviceCertificate findValue="Contoso.com"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="serviceCredentialBehavior"
name="ServiceModel.Calculator">
<endpoint address="http://localhost/Calculator"
binding="wsHttpBinding"
bindingConfiguration="InteropCertificateBinding"
name="WSHttpBinding_ICalculator"
contract="ServiceModel.ICalculator" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="InteropCertificateBinding">
<security mode="Message">
<message clientCredentialType="Certificate"
negotiateServiceCredential="false"
establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client />
</system.serviceModel>
</configuration>

Maximum Array Length Quota Exception in WCF

I am writing a WCF service to upload files but it throws an exceptions when byte array has more than 16384 elements.
This is the exception detail:
The formatter threw an exception while
trying to deserialize the message:
Error in deserializing body of request
message for operation
'CreateDocument'. The maximum array
length quota (16384) has been exceeded
while reading XML data. This quota may
be increased by changing the
MaxArrayLength property on the
XmlDictionaryReaderQuotas object used
when creating the XML reader. Line 1,
position 22862.
The config for both client and server sets the maximum array length quota to 2147483647.
Client Config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IDocumentLibraryService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:50764/DocumentLibraryService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IDocumentLibraryService"
contract="DocumentLibrary.IDocumentLibraryService" name="BasicHttpBinding_IDocumentLibraryService" />
</client>
Server Config:
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IDocumentLibraryService" 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="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="BasicHttpBinding_IDocumentLibraryService">
<clear />
<endpoint address="mex" binding="mexHttpBinding" name="mex" contract="Peninsula.DocumentLibrary.ServiceLayer.IDocumentLibraryService" />
<endpoint binding="basicHttpBinding" name="DocumentLibraryService" contract="Peninsula.DocumentLibrary.ServiceLayer.IDocumentLibraryService" address=""
bindingConfiguration="BasicHttpBinding_IDocumentLibraryService"/>
</service>
</services>
All I needed to do was to change Service name in web.config file to full service name with namespace:
<service name="SampleNameSpace.DocumentLibraryService">
<clear />
<endpoint address="mex" binding="mexHttpBinding" name="mex" contract="Peninsula.DocumentLibrary.ServiceLayer.IDocumentLibraryService" />
<endpoint binding="basicHttpBinding" name="DocumentLibraryService" contract="Peninsula.DocumentLibrary.ServiceLayer.IDocumentLibraryService" address=""
bindingConfiguration="BasicHttpBinding_IDocumentLibraryService"/>
</service>
This is not really an answer since your configuration seems OK. I think you just need to check these values in the code (output to trace or debug) on the service host and the proxy to make sure the same values in config are loaded into your channels.
On possibility is that another threshold is reached and the error is misleading
Now I strongly advise against using byte array to upload files especially if you use XML. These will be represented as XML arrays and the structure will be hugely bloated XML which will take 10 times more than the original file.
I would use:
WCF Streaming which works with basic binding as well and is super fast
alternatively represent the byte array as base64 string. This will take 33% more space but not 1000%
UPDATE
You can trace the binding name that was used to configure the service (use it inside any of your WCF operations):
public int MyServiceOperation()
{
Trace.WriteLine(OperationContext.Current.EndpointDispatcher.ChannelDispatcher.BindingName)
....