10

I have the following WCF client configuration:

<basicHttpBinding>
   <binding name="basicHttpOCCWS" closeTimeout="00:01:00" openTimeout="00:01:00"
                 receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
                 bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                 maxBufferSize="100000000" maxBufferPoolSize="524288"
                 maxReceivedMessageSize="100000000" messageEncoding="Text"
                 textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
      <readerQuotas maxDepth="32" maxStringContentLength="8192"
                    maxArrayLength="16384" maxBytesPerRead="4096" 
                    maxNameTableCharCount="16384" />
      <security mode="TransportCredentialOnly">
         <transport clientCredentialType="Basic" />            
      </security>
   </binding>
</basicHttpBinding>

In code, I am setting the username and password as follows:

client.ClientCredentials.UserName.UserName = _cacledUserId;
client.ClientCredentials.UserName.Password = _cachedPassword;

However, the web service running on Tomcat is returning an error:

"An authentication object was not found in the security context."

When I look at the HTTP header, it is missing credential information as shown below:

POST /occ600webservice/services/OCC_WS HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8; action=""
Host: 192.54.173.130:8080
Content-Length: 2223
Expect: 100-continue 

Why are my credentials not being sent?

TIA.

Klaus

Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
Klaus Nji
  • 18,107
  • 29
  • 105
  • 185
  • In order to properly format, you need to highlight code and xml sections, and then click on the "code" button (010 101) on the editor toolbar, or press Ctrl-K on your keyboard. Makes huge difference! – marc_s Oct 09 '09 at 16:58

2 Answers2

23

For others who run into the same problem, wrap each call to the secured web service resource like this:

var client = new WCClient(); 

using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
{
   var httpRequestProperty = new HttpRequestMessageProperty();
   httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] = 
     "Basic " + 
     Convert.ToBase64String(Encoding.ASCII.GetBytes(
            client.ClientCredentials.UserName.UserName + ":" +
            client.ClientCredentials.UserName.Password));

   OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] =
               httpRequestProperty;

   client.DoSomething();
}

see the following links:

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Klaus Nji
  • 18,107
  • 29
  • 105
  • 185
  • @e28Markaveli > I have tried this but when calling the service method(client.DoSomthing()) I will get the fallowing exception : The HTTP request is unauthorized with client authentication scheme 'Basic'. The authentication header received from the server was 'Basic realm=\"localhost\. I really need to pass these client indenification completely without security. – Banshee Feb 23 '11 at 15:34
  • 1
    This sounds like a service configuration issue. Is your service configured for Basic authentication scheme? – Klaus Nji Feb 25 '11 at 16:56
  • 6
    i had the same problem. This is the only solution that helped me. If I could vote this up 100 times, I would. – Alex J Nov 17 '11 at 02:06
  • 1
    This doesn't really answer the question. You're just manually creating the HTTP header instead of WCF doing it for you, you don't even need ClientCredentials at this point. – user247702 Apr 09 '15 at 10:18
  • 1
    Awesome this resolved my issue, but I still don't understand is this a configuration issue or a WCF bug ? – ihebiheb Jun 16 '15 at 21:29
  • Using security mode TransportCredentialsOnly and transport clientCredentialType Basic, as is often suggested, doesn't seem to work to pre-emptively send this header over http. (Maybe if the non-WCF web-service were to give a 401 unauthorised, it'd resend with credentials?) I've tried other configuration options and am now giving up and going this manual route. [Actually, just realised I was getting failures over httpS too (but couldn't intercept those headers) - maybe the WCF config just doesn't work preemptively?] – mwardm Oct 13 '16 at 16:26
  • @mwardm is correct. With 'TransportCredentialOnly', WCF does not send the credentials preemptively. .NET 2.0 .asmx web services had a PreAuthenticate option, but that seems lost. The above hack seems like the best solution. – Filip Aug 07 '17 at 16:37
3

Try changing the security element to also include the message element specifying the clientCredentialType to be UserName otherwise the transport doesn't know that you want to use the ClientCredentials.UserName object that you filled in.

<security mode="TransportCredentialOnly">
  <transport clientCredentialType="Basic" proxyCredentialType="None" />
  <message clientCredentialType="UserName"/>
</security>