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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.