Identity delegation in WCF
Further to my earlier post in an attempt to demystify Kerberos and IIS hosted WCF service (https://blogs.msdn.com/b/distributedworld/archive/2012/04/24/troubleshoot-kerberos-in-wcf.aspx) , I realized that successful delegation of client credentials to back end service/DB is also a common scenario and hence this short post. From WCF perspective, there are only three things to be done to successfully delegate client credentials :
1. First and foremost, client should allow itself to delegate. In WCF, this can be done by setting allowedImpersonationLevel="Delegation" on client side endpoint behavior
<clientCredentials>
<windows allowedImpersonationLevel="Delegation"/>
</clientCredentials>
2. Second, service should be impersonating client. It could either be done in Declarative or Imperative manner per operation. You can get more details here : https://msdn.microsoft.com/en-us/library/ms730088.aspx
3. Third, and this is important and what often confuses users. The AD (Active Directory) object used to authenticate server/service should be trusted for Delegation. Essentially, what you need to figure out is if its 'Server' or 'Service' authentication, which is used in your scenario, which in turn is consequence of combination of 'useAppPoolCredentials', 'Kernel authentication' and 'Explicit service identity' (The table in my previous blog may come handy to find this out).
So for example, if your middle tier used Kernel authentication with useAppPoolCredentials="false", the middle tier server should be trusted for delegation (irrespective of Identity middle tier service is running as). On the other hand, if you did a 'Service' authentication with custom identity, that specific identity should be trusted for delegation (you will need to create a SPN for that identity in order to enable 'Delegation' tab in AD)
<Edit> I would like to add a 4th point here. Remember that backend WCF service's client is middle tier and this client will also want the service (backend) to authenticate itself. Same principles of Kerberos authentication apply here and easiest way around this is to provide backend WCF service identity a SPN (say "MyBackendSvc/MyBackendBox") and specify same in backend service and middle tier config
<endpoint..>
<identity>
<servicePrincipalName value="MyBackendSvc/MyBackendBox"/>
</identity>
</endpoint>
Some useful tips:
- All in previous post (like klist purge) are still useful : https://blogs.msdn.com/b/distributedworld/archive/2012/04/24/troubleshoot-kerberos-in-wcf.aspx
- Following two properties to discover current process identity and caller identity come very handy while troubleshooting Identity issues.
1: // This is current process identity (will be same as caller if impersonating)
2: String user = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
3:
4: // This is caller's identity
5: WindowsIdentity callerWinIdentity = ServiceSecurityContext.Current.WindowsIdentity;