3

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?

2 Answers 2

5

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" });
Sign up to request clarification or add additional context in comments.

Comments

1

For me Stutje's solution works perfect, except:

  • needed to remove binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;, otherwise it asking to set credentials directly.
  • set binding.Security.Mode = BasicHttpSecurityMode.Transport; to use https

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.