I am having an issue with Kerberos authentication using the NetTcpBinding. At this point I can perform NTLM authentication and of course when I set the client to AllowNTML=false I get the “SecurityNegotiationException: The remote server did not satisfy the mutual authentication requirement.�span style=""> From what I can tell I have what is required in place but I must be missing something. Here are the complete details of the configuration I have put in place:
DNS Entry:
-services.dev.appdomain.com which Aliases dev. appdomain.com
SPN’s Added for the newly created ADdomain\testwcfservices domain account:
-wcfservice/services.dev.appdomain.com:20000
-wcfservice/vpaidevweb1.servermachinedomain.com:20000
-wcfservice/vpaidevweb1:20000
Domain account ADdomain\testwcfservices
-“Trust this user for delegation to any service (Kerberos only)�option marked for this user within Active Directory
-Removed from the Domain Users Group
-Only group membership is an Application users group that has very little rights in the enterprise
-On the vpaidevweb1.servermachinedomain.com server, I have added this user for now to the IIS_WPG group to get them the local rights to run/host the .NET runtime and give the user the privileges needed for Kerberos
-Note that we have no issue with Kerberos using IIS with our standard .NET web applications that are running within IIS under an account that is also in the IIS_WPG locally.
Windows Service Hosting TCP Enpoint
-Installed on vpaidevweb1.servermachinedomain.com server
-Installed to run under ADdomain\testwcfservices domain account
-When the Windows Service starts, security event logs indicate successful login with “Authentication Package: Negotiate�and Special Privileges of “SeTcbPrivilege and SeImpersonatePrivilege�for the ADdomain\testwcfservices domain account
Server Config Code Implementation:
public static ServiceHost CreateTcpServiceHost(Type serviceContract, Type serviceContractImplementation, string serviceAddress, string spn)
{
ServiceHost sh = new ServiceHost(serviceContractImplementation);
ServiceMetadataBehavior metaBehavior = new ServiceMetadataBehavior();
sh.Description.Behaviors.Add(metaBehavior);
serviceDebugBehavior.IncludeExceptionDetailInFaults = includeExceptionDetailInFaults;
NetTcpBinding netBinding = new NetTcpBinding();
EndpointIdentity ei = new SpnEndpointIdentity(spn);
EndpointAddress ea = new EndpointAddress(new Uri(serviceAddress), ei);
ServiceEndpoint se = sh.AddServiceEndpoint(serviceContract, new NetTcpBinding(), serviceAddress);
se.Address = ea;
Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
sh.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, serviceAddress + "/mex");
return sh;
}
....
public void CodeBlockinWindowsService()
{
ServiceHost sh = CreateTcpServiceHost(
typeof(ISomeContract),
typeof(SomeContractImpl),
"net.tcp://services.dev.appdomain.com:20000/Employee/IndividualManagement/2007/06/10",
"wcfservice/services.dev.appdomain.com"
Sh.Open();
);
}
}
Client Config Code Implementation:
public static Employee_IndividualManagement_v20070610.IndividualManagement CreateClient()
{
EndpointIdentity ei = new SpnEndpointIdentity("wcfservice/services.qa.pai.com");
EndpointAddress e = new EndpointAddress(new Uri("net.tcp://services.qa.pai.com:20000/Employee/IndividualManagement/2007/06/10"), ei);
NetTcpBinding binding = new NetTcpBinding();
binding.CloseTimeout = TimeSpan.Parse("00:01:00");
binding.OpenTimeout = TimeSpan.Parse("00:01:00");
binding.ReceiveTimeout = TimeSpan.Parse("00:01:00");
binding.SendTimeout = TimeSpan.Parse("00:01:00");
binding.TransactionFlow = false;
binding.TransferMode = TransferMode.Buffered;
binding.TransactionProtocol = TransactionProtocol.OleTransactions;
binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
binding.ListenBacklog = 100;
binding.MaxBufferPoolSize = 524288;
binding.MaxBufferSize = 327680;
binding.MaxConnections = 100;
binding.MaxReceivedMessageSize = 655360;
binding.ReaderQuotas.MaxDepth = 32;
binding.ReaderQuotas.MaxStringContentLength = 8192;
binding.ReaderQuotas.MaxArrayLength = 16384;
binding.ReaderQuotas.MaxBytesPerRead = 4096;
binding.ReaderQuotas.MaxNameTableCharCount = 16384;
binding.ReliableSession.Ordered = true;
binding.ReliableSession.InactivityTimeout = TimeSpan.Parse("00:10:00");
binding.ReliableSession.Enabled = false;
binding.Security.Mode = SecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
binding.Security.Transport.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign;
binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
ChannelFactory<Employee_IndividualManagement_v20070610.IndividualManagement> cf = new ChannelFactory<IndividualManagement>(binding, e);
cf.Credentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Delegation;
cf.Credentials.Windows.AllowNtlm = false;
ChannelFactory<Employee_IndividualManagement_v20070610.IndividualManagement>.CreateChannel(binding, e);
return cf.CreateChannel();
}