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?
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" });