I have the following infrastructure:
Computer #1, Microsoft SQL Server 2008, started under System account. There is login Master\MyLogin
(with Windows Authintification), server roles = sysadm
, database role = db_owner
.
Computer # 2, WCF service on IIS 7.0. Application and site run under account Master\IISLogin
(IISLogin@myDomain.ru)
Configuration:
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="CommonWindowsBinding" maxReceivedMessageSize="40000000">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<services>
<service behaviorConfiguration="CommonBehavior" name="MyNameSpace.AdminService">
<endpoint address="Windows" binding="netTcpBinding" bindingConfiguration="CommonWindowsBinding" name="IAdminServiceWindows" contract="MyNameSpace.IAdminService">
<identity>
<dns value="WCFServer" />
<userPrincipalName value="IISLogin@myDomain.ru"/>
</identity>
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="CommonBehavior">
<dataContractSerializer maxItemsInObjectGraph="10000000" />
<serviceMetadata httpGetEnabled="true" policyVersion="Policy15" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerTrust" />
</clientCertificate>
<serviceCertificate findValue="WCFServer" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyClassFullName, MyDllFullName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Service has method
[OperationBehavior(Impersonation = ImpersonationOption.Allowed)]
public bool HasRole(string roleName)
{
//work with database
}
It uses EF 5.0 database first. Connection string
"Data Source=Computer1; Initial Catalog=myDB; Integrated Security=True; Multipleactiveresultsets=True; Persist Security Info=True;"
Computer # 3, the client. It has the following config
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="CommonWindowsBinding" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10"
maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
maxReceivedMessageSize="40000000">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint name="Megatec.MasterTourService.Contracts.IAdminServiceWindows"
address="net.tcp://Computer2:5012/IISTest/AdminService.svc/Windows"
behaviorConfiguration="CustomBehavior"
binding="netTcpBinding"
bindingConfiguration="CommonWindowsBinding"
contract="Megatec.MasterTourService.Contracts.IAdminService">
<identity>
<dns value="WCFServer" />
</identity>
</endpoint>
</client>
<behaviors>
<behavior name="CustomBehavior">
<dataContractSerializer maxItemsInObjectGraph="10000000"/>
<clientCredentials>
<clientCertificate findValue="WCFClient" x509FindType="FindBySubjectName"
storeLocation="LocalMachine" storeName="My" />
<serviceCertificate>
<defaultCertificate findValue="WCFServer" storeLocation="LocalMachine"
x509FindType="FindBySubjectName" />
<authentication certificateValidationMode="PeerTrust"
revocationMode="NoCheck"
trustedStoreLocation="LocalMachine"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Channel has the following credentials
channelFactory.Credentials.Windows.AllowedImpersonationLevel =
System.Security.Principal.TokenImpersonationLevel.Delegation;
channelFactory.Credentials.Windows.ClientCredential =
System.Net.CredentialCache.DefaultNetworkCredentials;
It falls with db error
Login failed for user 'NT AUTHORITY\Anonymous'
So, there is some problem with WCF delegation. When I tried to use simple username/password
authentication, it worked fine - so, certificates and so on are fine.
I did Step 4 on this instruction, but it doesn't work.
Maybe something is wrong with my code or configs? How can I fix it?
UPDATE.
Tried (no result)
[OperationBehavior(Impersonation = ImpersonationOption.Allowed)] => [OperationBehavior(Impersonation = ImpersonationOption.Required)]
Tried (no result)
On the service side
ServiceSecurityContext.Current.WindowsIdentity.ImpersonationLevel = Impersonation (not Delegation!)
When I tried to change identity for IIS pool from ApplicationPoolIdentity to IISLogin@myDomain.ru, the client on the computer 3 crashed.
Unfortunatelly, Transport/TransportWithMessageCredential security mode doesn't support such work with client credentials and delegation. I've changed CommonWindowsBinding
in the following way
Server
<binding name="CommonWindowsBinding" maxReceivedMessageSize="40000000">
<security mode="Message">
<message clientCredentialType="Windows" />
</security>
</binding>
Client
<binding name="CommonWindowsBinding" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10"
maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
maxReceivedMessageSize="40000000">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<message clientCredentialType="Windows" />
</security>
</binding>