Search code examples
c#.net.net-coresoapsoap-client

C# .NET Core SOAP Client basic auth header not set


I have a client generated from a WSDL file and uses this in a .NET core 3.1 project. I can't set the Authorization header through ClientCredentials and a BasicHttp(s)Binding. I used hookbin to see my request. This is my code:

BasicHttpsBinding binding= new BasicHttpsBinding();

//for http
//binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;

binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
EndpointAddress endpoint = new EndpointAddress("https://hookb.in/...");

var soapClient = new RandomServiceClient(binding, endpoint);
soapClient.ClientCredentials.UserName.UserName = "user";
soapClient.ClientCredentials.UserName.Password = "bla";

soapClient.CallServiceMethod(new Request { Foo = "Bar" });

I already tried using other Bindings like WSHttpBinding like the Microsoft documentation suggests: https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/transport-security-with-basic-authentication

What am i doing wrong?


Solution

  • Thanks to: https://stackoverflow.com/a/60714907/9124424 I found a solution, but i still wonder why the code in my question does not work

    So you need to add an IClientMessageInspector and an IEndpointBehavior

        public class AddHttpHeaderMessageEndpointBehavior : IEndpointBehavior
        {
            private readonly IClientMessageInspector _httpHeaderMessageInspector;
    
            public AddHttpHeaderMessageEndpointBehavior(Dictionary<string, string> headers)
            {
                _httpHeaderMessageInspector = new HttpHeaderMessageInspector(headers);
            }
    
            public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
            {
    
            }
    
            public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
            {
                clientRuntime.ClientMessageInspectors.Add(_httpHeaderMessageInspector);
            }
    
            public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
            {
    
            }
    
            public void Validate(ServiceEndpoint endpoint)
            {
    
            }
        }
        
        public class HttpHeaderMessageInspector : IClientMessageInspector
        {
            private readonly Dictionary<string, string> _headers;
    
            public HttpHeaderMessageInspector(Dictionary<string, string> headers)
            {
                _headers = headers;
            }
    
            public void AfterReceiveReply(ref Message reply, object correlationState)
            {
    
            }
    
            public object BeforeSendRequest(ref Message request, IClientChannel channel)
            {
                if (request.Properties.Count == 0 || request.Properties[HttpRequestMessageProperty.Name] == null)
                {
                    request.Properties.Add(HttpRequestMessageProperty.Name, new HttpRequestMessageProperty());
                }
                var headersCollection = ((HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name]).Headers;
    
                foreach (var header in _headers) headersCollection[header.Key] = header.Value;
    
                return null;
            }
        }
    

    And then you can add this IEndpointBehavior to the Endpoint in the client instance

    BasicHttpsBinding binding= new BasicHttpsBinding();
    
    //for http
    //binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
    
    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
    EndpointAddress endpoint = new EndpointAddress("https://hookb.in/...");
    
    var soapClient = new RandomServiceClient(binding, endpoint);
    var headers = new Dictionary<string, string>
                    {
                        {"Authorization", $"Basic --INSERT TOKEN--"}
                    }));
    var behavior = new AddHttpHeaderMessageEndpointBehavior(headers);
    soapClient.Endpoint.EndpointBehaviors.Add(behavior);
    soapClient.CallServiceMethod(new Request { Foo = "Bar" });