A
Aleksey Malyshev
Guest
I need to build a Windows service/client using https protocol. The user should be authenticated on the server using username/password, provided on the client side. I use Transport level protection with TLS encryption. The service is self-hosted (no IIS). Documentation is very vague and most description just repeats the name of the variable with no explanations. Also I was not able to find a functioning example.
My code is distributed across multiple functions. For simplicity reasons, below are some code snippets that I think relevant to the question. Feel free to ask for more details.
Server:
private static Binding CreateWebHttpBinding()
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var binding = new WebHttpBinding(WebHttpSecurityMode.Transport)
{
ReaderQuotas = _readerQuotas,
MaxReceivedMessageSize = 2147483647,
OpenTimeout = TimeSpan.MaxValue,
CloseTimeout = TimeSpan.MaxValue,
SendTimeout = TimeSpan.MaxValue,
ReceiveTimeout = TimeSpan.MaxValue,
TransferMode = TransferMode.Buffered
};
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
// I have no idea what Windows actually means - is it the client Windows system or the server Windows?
return binding;
}
var address = new Uri[] { new Uri($"https://localhost:443/MyApp/{serviceName}.svc") };
var host = new ServiceHost(serviceType, address);
var endpoint = host.AddServiceEndpoint(serviceContract, CreateWebHttpBinding(), "");
endpoint.Behaviors.Add(new WebHttpBehavior { DefaultBodyStyle = WebMessageBodyStyle.Wrapped });
host.Open();
Client:
endpointAddress = $"https://{middlewareHost}:443/MyApp/{serviceName}.svc";
binding = CreateWebHttpBinding(); // same as for the server side
var channelFactory = new ChannelFactory<T>(binding, new EndpointAddress(new Uri(endpointAddress)));
if (channelFactory.Credentials != null)
{
channelFactory.Credentials.Windows.ClientCredential =
new NetworkCredential(userName, userPassword);
channelFactory.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
// Here is another totally mysterious setting ^
}
ClientCredentials clientCredentials = null;
foreach (var b in channelFactory.Endpoint.Behaviors)
{
clientCredentials = b as ClientCredentials;
if (clientCredentials != null)
{
break;
}
}
if (clientCredentials == null)
{
clientCredentials = new ClientCredentials();
channelFactory.Endpoint.Behaviors.Add(clientCredentials);
}
clientCredentials.UserName.UserName = userName;
clientCredentials.UserName.Password = userPassword;
channelFactory.Endpoint.Behaviors.Add(new WebHttpBehavior { DefaultBodyStyle = WebMessageBodyStyle.Wrapped });
channelFactory.CreateChannel()
I am working on it for two weeks and completely lost. When I try to use http and port 80 (Transport Security None), I get connected, but no authentication happens, when I use https and port 443 the client's request gets rejected with "An existing connection was forcibly closed by the remote host". It does not reach my server. I guess it is rejected by Windows system, but with absence of IIS I don't know - how to find a clue. There are so many settings with little or no documentation and no examples. Please help.
And yes, I enabled http 80 and https 443 ports on the server side.
Continue reading...
My code is distributed across multiple functions. For simplicity reasons, below are some code snippets that I think relevant to the question. Feel free to ask for more details.
Server:
private static Binding CreateWebHttpBinding()
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var binding = new WebHttpBinding(WebHttpSecurityMode.Transport)
{
ReaderQuotas = _readerQuotas,
MaxReceivedMessageSize = 2147483647,
OpenTimeout = TimeSpan.MaxValue,
CloseTimeout = TimeSpan.MaxValue,
SendTimeout = TimeSpan.MaxValue,
ReceiveTimeout = TimeSpan.MaxValue,
TransferMode = TransferMode.Buffered
};
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
// I have no idea what Windows actually means - is it the client Windows system or the server Windows?
return binding;
}
var address = new Uri[] { new Uri($"https://localhost:443/MyApp/{serviceName}.svc") };
var host = new ServiceHost(serviceType, address);
var endpoint = host.AddServiceEndpoint(serviceContract, CreateWebHttpBinding(), "");
endpoint.Behaviors.Add(new WebHttpBehavior { DefaultBodyStyle = WebMessageBodyStyle.Wrapped });
host.Open();
Client:
endpointAddress = $"https://{middlewareHost}:443/MyApp/{serviceName}.svc";
binding = CreateWebHttpBinding(); // same as for the server side
var channelFactory = new ChannelFactory<T>(binding, new EndpointAddress(new Uri(endpointAddress)));
if (channelFactory.Credentials != null)
{
channelFactory.Credentials.Windows.ClientCredential =
new NetworkCredential(userName, userPassword);
channelFactory.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
// Here is another totally mysterious setting ^
}
ClientCredentials clientCredentials = null;
foreach (var b in channelFactory.Endpoint.Behaviors)
{
clientCredentials = b as ClientCredentials;
if (clientCredentials != null)
{
break;
}
}
if (clientCredentials == null)
{
clientCredentials = new ClientCredentials();
channelFactory.Endpoint.Behaviors.Add(clientCredentials);
}
clientCredentials.UserName.UserName = userName;
clientCredentials.UserName.Password = userPassword;
channelFactory.Endpoint.Behaviors.Add(new WebHttpBehavior { DefaultBodyStyle = WebMessageBodyStyle.Wrapped });
channelFactory.CreateChannel()
I am working on it for two weeks and completely lost. When I try to use http and port 80 (Transport Security None), I get connected, but no authentication happens, when I use https and port 443 the client's request gets rejected with "An existing connection was forcibly closed by the remote host". It does not reach my server. I guess it is rejected by Windows system, but with absence of IIS I don't know - how to find a clue. There are so many settings with little or no documentation and no examples. Please help.
And yes, I enabled http 80 and https 443 ports on the server side.
Continue reading...