Wcf – Basic HTTP Authentication over HTTPS with WCF

basic-authenticationhttpswcf

I’m calling a web service via WCF (w/ .NET 4.0) that requires basic HTTP authentication (with username and password.) over HTTPS. While, I think I’ve got everything setup correctly, I’m getting a 401 error whenever I make the call to the service. I monitored the HTTP traffic and noticed that WCF seems to be ignoring that I told it to use an authorization header with the username and password, as none is sent in the request. Here’s my configuration below. Any ideas? Thanks!

   <system.serviceModel>
         <bindings>
                <basicHttpBinding>
                       <binding name="BasicAuthSecured">
                             <security mode="Transport">
                                    <transport clientCredentialType="Basic" />
                             </security>
                       </binding>
                       </basicHttpBinding>
                </bindings>
         <client>
                <endpoint address="https://REMOVED FOR CONFIDENTIALITY"
            binding="basicHttpBinding" bindingConfiguration="BasicAuthSecured"
            contract="Five9.WsAdmin" name="WsAdminPort" />
         </client>
         <behaviors>
                <serviceBehaviors>
                       <behavior name="">
                             <serviceMetadata httpsGetEnabled="true"/>
                             <serviceDebug includeExceptionDetailInFaults="true"/>
                       </behavior>
                </serviceBehaviors>
         </behaviors>
   </system.serviceModel>

And here’s my code:

        var five_9_client = new WsAdminClient();

        five_9_client.ClientCredentials.UserName.UserName = “REMOVED FOR CONFIDENTIALITY";
        five_9_client.ClientCredentials.UserName.Password = "REMOVED FOR CONFIDENTIALITY";

        var call_log_response = five_9_client.getCallLogReport(call_log); //Bombing out here

I’m getting this exception:

{"The HTTP request is unauthorized with client authentication scheme 'Basic'. The authentication header received from the server was ''."}

With inner exception:

{"The remote server returned an error: (401) Unauthorized."}

With stack trace:

at System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(HttpWebRequest request, HttpWebResponse response, WebException responseException, HttpChannelFactory factory)
at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory factory, WebException responseException, ChannelBinding channelBinding)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Best Answer

Found the solution: basically, the problem was that the header had to be attached to the current request, like so:

      var base_64_encoded_credentials =
            BasicHTTPAuthenticationEncoder.base_64_encode_credentials(
                client.ClientCredentials.UserName.UserName, client.ClientCredentials.UserName.Password);

        HttpRequestMessageProperty request = new HttpRequestMessageProperty();
        request.Headers[System.Net.HttpRequestHeader.Authorization] = "Basic " + base_64_encoded_credentials;

        OperationContextScope clientScope = new OperationContextScope(five_9_client.InnerChannel);
        OperationContext.Current.OutgoingMessageProperties.Add(HttpRequestMessageProperty.Name, request);
Related Topic