none
TransportCredentialOnly Security Mode not working with WCF REST service. RRS feed

  • Question

  • Hello,

    I am deploying a WCF REST service as a Windows service and am trying to use the TransportCredentialOnly security mode with clientCredentialType of Windows.  The markup in app.config looks like:

          <webHttpBinding>

            <binding name="RESTService">

              <security mode="TransportCredentialOnly">

                <transport clientCredentialType="Windows"/>

              </security>

            </binding>

          </webHttpBinding>

    My client is using HttpWebRequest.  I understand that by specifying default credentials for the request it uses my domain credentials.  That is:

    request.Credentials = CredentialCache.DefaultCredentials;

    or

    request.UseDefaultCredentials = true;

    If I run the client and server on the same system it works fine.  However, if I put the server on a different system in my domain I get a 401 Unauthorized error.

    I also tried specifying my credentials explicitly:

    NetworkCredential myCred = new NetworkCredential("<username>", "<password>", "<domain>");

    CredentialCache myCache = new CredentialCache();

    myCache.Add(new Uri("http://<remotehost>:5656"), "Windows", myCred);

    request.Credentials = myCache;

    But still receive the 401 error.

    If I specify security mode as “none” it works fine.  I have already eliminated the firewall as a possible cause.

    Everything I read online indicates this should work.  For now I am going with security mode of none but I really need to resolve this before deploying into a production environment.  Any help is greatly appreciated.

    The full app.config for the service is here:

    <?xml version="1.0"?>
    <configuration>
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
      </startup>
      <system.serviceModel>
        <bindings>
          <webHttpBinding>
            <binding name="RESTService">
              <!-- <security mode="None"/> -->
              <security mode="TransportCredentialOnly">
                <transport clientCredentialType="Windows"/>
              </security>
            </binding>
          </webHttpBinding>
        </bindings>
        <services>
          <service name="RESTService.ServiceImpl">
            <!--<endpoint
              address="http://localhost:1234/"
              contract="RESTService.IService"
              binding="webHttpBinding"
              behaviorConfiguration="web"
              bindingConfiguration="RESTService"/>-->
            <endpoint
              address="http://remotehost:5656/"
              contract="RESTService.IService"
              binding="webHttpBinding"
              behaviorConfiguration="web"
              bindingConfiguration="RESTService"/>
          </service>
        </services>
        <behaviors>
          <endpointBehaviors>
            <behavior name="web">
              <webHttp/>
            </behavior>
          </endpointBehaviors>
        </behaviors>
      </system.serviceModel>
    </configuration>
    

    The service is defined as:

    using System;
    using System.ServiceModel;
    using System.ServiceModel.Web;
    
    namespace RESTService
    {
        [ServiceContract]
        interface IService
        {
            // Services
            #region Users
            [WebGet(UriTemplate = "/Hello/{name}")]
            [OperationContract(Name = "Hello")]
            string Hello(string name);
            #endregion // Services
        }
    }
    

    And the client is:

    using System;
    using System.IO;
    using System.Net;
    using System.Runtime.Serialization;
    using System.Text;
    
    namespace Client
    {
        class Program
        {
            static void Main()
            {
                //string localhost = "localhost";
                string remotehost = "bevtest1.electrotek.com";
                string reply = null;
                StringBuilder sb = new StringBuilder();
    
                // TEST 1:  Client and server on same system.
                //sb.AppendFormat("http://{0}:{1}/Hello/{2}", localhost, 1234, "Bill");
    
                // TEST 2:  Client and server on different systems on same domain.
                sb.AppendFormat("http://{0}:{1}/Hello/{2}", remotehost, 5656, "Bill");
    
                try
                {
                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(sb.ToString());
    
                    // Set credentials to use for this request - Windows authentication.
    
                    // TEST 1:  Client and server running on same system.  Both these
                    // methods of specifying default credentials work.
                    //request.Credentials = CredentialCache.DefaultCredentials;
                    request.UseDefaultCredentials = true;
    
                    // TEST 2:  Neither setting credentials to UseDefault as above NOR specifying the
                    // credentials explicitly as shown here works when the client and server are
                    // on different systems on the same domain.
                    NetworkCredential myCred = new NetworkCredential("<username>", "<password>", "<domain>");
                    CredentialCache myCache = new CredentialCache();
                    myCache.Add(new Uri("http://<remotehost>:5656"), "Windows", myCred);
                    request.Credentials = myCache;
    
                    request.Accept = "application/xml";
                    request.Method = "GET";
    
                    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                    {
                        if (response.StatusCode == HttpStatusCode.OK && response.ContentLength > 0)
                        {
                            Stream strm = response.GetResponseStream();
    
                            DataContractSerializer ds = new DataContractSerializer(typeof(string));
                            reply = (string)ds.ReadObject(strm);
                            if (!String.IsNullOrEmpty(reply))
                            {
                                Console.WriteLine(reply);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Caught exception: {0}.", ex.Message);
                }
    
                Console.WriteLine("Press a key to quit");
                Console.ReadKey();
            }
        }
    }
    

    • Moved by Fred Bao Wednesday, August 27, 2014 2:33 AM
    Monday, August 25, 2014 3:06 PM

Answers

All replies