views:

122

answers:

2

I have a simple service and I try to set up authentication. On the client I want the user to enter there windows user account. And the WCF will use the username/password provided by the client and authenticate them against windows authentication.

Here is my server app.config

 <system.serviceModel>
    <services>
      <service name="WcfService.Service1" behaviorConfiguration="WcfService.Service1Behavior">
        <host>
          <baseAddresses>
            <add baseAddress = "http://localhost:8731/Design_Time_Addresses/WcfService/Service1/" />
          </baseAddresses>
        </host>
        <endpoint address ="" binding="wsHttpBinding" contract="WcfService.IService1">
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WcfService.Service1Behavior">
          <serviceMetadata httpGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="True" />

          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode = "Windows"/>
          </serviceCredentials>

        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

Here is my client app.config

<system.serviceModel>
    <bindings>
        <wsHttpBinding>
          <binding name="WSHttpBinding_IService1">

              <security mode = "Message">
                <message  clientCredentialType = "UserName"/>
              </security>

            </binding>
        </wsHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost:8731/Design_Time_Addresses/WcfService/Service1/"
            binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1"
            contract="ServiceReference1.IService1" name="WSHttpBinding_IService1">
            <identity>
                <dns value="localhost" />
            </identity>
        </endpoint>
    </client>
</system.serviceModel>

Here is my code on the client

ServiceReference1.Service1Client client = new WcfAuthentication.ServiceReference1.Service1Client();

client.ClientCredentials.UserName.UserName = "mywindowsusername";
client.ClientCredentials.UserName.Password = "mywindowsuserpassword";
Console.WriteLine(client.GetData(5));

But I'm always getting this exception :

{"Secure channel cannot be opened because security negotiation with the remote endpoint has failed. This may be due to absent or incorrectly specified EndpointIdentity in the EndpointAddress used to create the channel. Please verify the EndpointIdentity specified or implied by the EndpointAddress correctly identifies the remote endpoint. "} {"The request for security token has invalid or malformed elements."}

+2  A: 

I think Windows Authentication with WsHttpBinding only works with https.

See this: http://msdn.microsoft.com/en-us/library/ff650619.aspx

StephaneT
+2  A: 

It looks like you generated the service and client configuration separately (by hand). It usually is a good idea to generate the client configuration from the service using svcutil or Visual Studio's 'Add Service Reference'. This way you know that you get the client config that corresponds to the service config.

What you want is possible, but WCF doesn't allow you to transmit your username/password token in plain text when using wsHttpBinding. This means that you must either host your service using https or use a service certificate. Here's a post with some more details.

But I'm also wondering why you would want anything like this. It may be a better idea to use integrated Windows authentication. This is even the default setting for wsHttpBinding. This way you do not need your client(s) to enter their Windows username/password.

Ronald Wildenberg
Interesting, makes perfect sense that it must use a secure connection. It was just an exercise to understand the different authentication possibility offered by wcf. In the real world. It's for my mobile application, which the user will need to provide windows account credential on their mobile device. So it's using basichttpbinding and to secure the communication I'm going to go with SSL (https). So for example above using a nettcpbinding should be good correct, since I think by default it's using the Transport security which should already be encrypted with tcp.
pdiddy