How do you pass user credentials from WebClient to a WCF REST service?

Posted by Alex on Stack Overflow See other posts from Stack Overflow or by Alex
Published on 2009-04-27T23:46:10Z Indexed on 2010/05/09 18:08 UTC
Read the original article Hit count: 724

Filed under:
|
|
|

I am trying to expose a WCT REST service and only users with valid username and password would be able to access it. The username and password are stored in a SQL database.

Here is the service contract:

public interface IDataService
{
    [OperationContract]
    [WebGet(ResponseFormat = WebMessageFormat.Json)]
    byte[] GetData(double startTime, double endTime);
}

Here is the WCF configuration:

<bindings>
  <webHttpBinding>
    <binding name="SecureBinding">
      <security mode="Transport">
        <transport clientCredentialType="Basic"/>
      </security>
    </binding>
  </webHttpBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior name="DataServiceBehavior">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceCredentials>
        <userNameAuthentication
           userNamePasswordValidationMode="Custom"
           customUserNamePasswordValidatorType=
                 "CustomValidator, WCFHost" />
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>
<services>
  <service behaviorConfiguration="DataServiceBehavior" name="DataService">
    <endpoint address="" binding="webHttpBinding"
              bindingConfiguration="SecureBinding" contract="IDataService" />
  </service>
</services>

I am accessing the service via the WebClient class within a Silverlight application. However, I have not been able to figure out how to pass the user credentials to the service. I tried various values for client.Credentials but none of them seems to trigger the code in my custom validator. I am getting the following error: The underlying connection was closed: An unexpected error occurred on a send.

Here is some sample code I have tried:

   WebClient client = new WebClient();
   client.Credentials = new NetworkCredential("name", "password", "domain");
   client.OpenReadCompleted += new OpenReadCompletedEventHandler(GetData);
   client.OpenReadAsync(new Uri(uriString));

If I set the security mode to None, the whole thing works. I also tried other clientCredentialType values and none of them worked. I also self-hosted the WCF service to eliminate the issues related to IIS trying to authenticate a user before the service gets a chance.

Any comment on what the underlying issues may be would be much appreciated. Thanks.

Update: Thanks to Mehmet's excellent suggestions. Here is the tracing configuration I had:

 <system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
              switchValue="Information, ActivityTracing"
              propagateActivity="true">
        <listeners>
          <add name="xml" />
        </listeners>
      </source>
      <source name="System.IdentityModel" switchValue="Information, 
               ActivityTracing" propagateActivity="true">
        <listeners>
          <add name="xml" />
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add name="xml"
           type="System.Diagnostics.XmlWriterTraceListener"
           initializeData="c:\Traces.svclog" />
    </sharedListeners>
  </system.diagnostics>

But I did not see any message coming from my Silverlight client. As for https vs http, I used https as follows:

string baseAddress = "https://localhost:6600/";
_webServiceHost = new WebServiceHost(typeof(DataServices), 
                new Uri(baseAddress));
_webServiceHost.Open();

However, I did not configure any SSL certificate. Is this the problem?

© Stack Overflow or respective owner

Related posts about wcf

Related posts about webhttpbinding