title: WCF configuration for SOAP plain text password authentication over SSL
body: <p>I have an application that connects via https to a SOAP-based web service that implements WS-Security.  The web service is written in Java, expects a plain text password as well as a properly set timestamp.</p>
  
  <p>After a great deal of googling and experimentation, I can't figure out how to configure my WCF client to interact with this service.  In addition to a correct answer, I would also appreciate a link to a tutorial that explains WCF and SOAP well.</p>
  
  <p>My current client's app.config looks like this:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
  &lt;configuration&gt;
      &lt;system.serviceModel&gt;
          &lt;bindings&gt;
              &lt;basicHttpBinding&gt;
                  &lt;binding name="MyServiceSoapBinding" 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"&gt;
                      &lt;readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                          maxBytesPerRead="4096" maxNameTableCharCount="16384" /&gt;
                    &lt;security mode="TransportWithMessageCredential"&gt;
                      &lt;transport clientCredentialType="None" proxyCredentialType="None"
                          realm="" /&gt;
                      &lt;message clientCredentialType="UserName" algorithmSuite="Default" /&gt;
                    &lt;/security&gt;
                    &lt;!--security mode="None"&gt;
                      &lt;transport clientCredentialType="None" proxyCredentialType="None"
                          realm="" /&gt;
                      &lt;message clientCredentialType="UserName" algorithmSuite="Default" /&gt;
                    &lt;/security--&gt;
                  &lt;/binding&gt;
              &lt;/basicHttpBinding&gt;
          &lt;/bindings&gt;
          &lt;client&gt;
              &lt;endpoint address="https://p1.my.com/tx/services/MyService"
                  binding="basicHttpBinding" bindingConfiguration="MyServiceSoapBinding"
                  contract="My.IMyService" name="MyServiceEndpointPort" /&gt;
          &lt;/client&gt;
      &lt;/system.serviceModel&gt;
  &lt;/configuration&gt;
  </code></pre>
  
  <p>and the client code looks like this:</p>
  
  <pre><code>string response;
  
  try
  {
      MyService.MyServiceClient svc = new WcfExample.MyService.MyServiceClient();
  
      svc.ClientCredentials.UserName.UserName = "myUser";
      svc.ClientCredentials.UserName.Password = "myPass";
  
      response = svc.ping();
  
      lblPingResponse.Text = response;
  }
  catch (System.ServiceModel.Security.MessageSecurityException mse)
  {
      lblPingResponse.Text = "MessageSecurityException: " + mse.Message;
  }
  catch (Exception ex)
  {
      lblPingResponse.Text = "Exception: " + ex.Message;
  }
  </code></pre>
  
  <p>This code is throwing this exception:</p>
  
  <blockquote>
    <p>MessageSecurityException "Security
    processor was unable to find a
    security header in the message. This
    might be because the message is an
    unsecured fault or because there is a
    binding mismatch between the
    communicating parties.   This can
    occur if the service is configured for
    security and the client is not using
    security."</p>
  </blockquote>
  
  <p>The WSE 3 version simply requires the following to work:</p>
  
  <pre><code>ServiceUsernameTokenManager.AddUser(userName, password);
  
  UsernameToken token = new UsernameToken(userName, password,
                  PasswordOption.SendPlainText);
  
  proxy = new _MyServiceWse();
  
  Policy policy = new Policy();
  
  policy.Assertions.Add(new UsernameOverTransportAssertion());
  policy.Assertions.Add(new RequireActionHeaderAssertion());
  proxy.SetPolicy(policy);
  
  proxy.SetClientCredential(token);
  </code></pre>
  
  <p>UPDATE:</p>
  
  <p>The request now reaches the server and a response is sent back from the server using this configuration in app.config:</p>
  
  <pre><code>&lt;security mode="TransportWithMessageCredential"&gt;
    &lt;transport clientCredentialType="None" proxyCredentialType="None" realm="" /&gt;
    &lt;message clientCredentialType="UserName" algorithmSuite="Default" /&gt;
  &lt;/security&gt; 
  </code></pre>
  
  <p>The client then throws an Exception</p>
  
  <blockquote>
    <p>"Security processor was unable to find
    a security header in the message. This
    might be because the message is an
    unsecured fault or because there is a
    binding mismatch between the
    communicating parties.   This can
    occur if the service is configured for
    security and the client is not using
    security."</p>
  </blockquote>
  
  <p>This seems to be because the client sends a Timestamp header, but the service does not return a Timestamp header.  This is probably "the right thing to do", but it's not very helpful because there are many web services deployed out there that expect a Timestamp but do not return one.</p>
  
  <p>If there is a way to convince the client to accept this situation I would love to know about it.  In the mean time, I'll look into whether I can have the web service changed to return a Timestamp.</p>