Scenario: You have a client application, with a user logged on with a domain user ( kerberos credentilas ). The application calls a BizTalk Server 2004 orchestration ( a business process ) that calls a Back End Web Service. The Web Service needs to know who is the logged user to take a decision on which task it has to execute.
Solution: Extract from the input message the OriginatorSID context property (that contains the LogonUser string ) then impersonate it using a helper component :for example with an expression shape like this: bizImpHelper.Impersonate(IncomingMessage(Microsoft.BizTalk.XLANGs.BTXEngine.OriginatorSID));This is the helper class that does the impersonation: [Serializable]public class BizTalkImpersonationHelper{ private BizTalkImpersonationContext bizImpCtxt; public BizTalkImpersonationHelper() {} public void Impersonate( string logonUser ) { int slash = logonUser.IndexOf("\\"); if( slash > 0 ){ string domain = logonUser.Substring(0,slash); string user = logonUser.Substring(slash+1); logonUser = user + "@" + domain; } bizImpCtxt = new BizTalkImpersonationContext(); bizImpCtxt.Impersonate(logonUser); } public void UnDo() { if( bizImpCtxt != null ) bizImpCtxt.Undo(); }}[Serializable]internal class BizTalkImpersonationContext{ private System.Security.Principal.WindowsIdentity identity; [ThreadStatic] static WindowsImpersonationContext wic ; internal void Impersonate( string logonUser ) { if( wic != null ) wic.Undo(); identity = new System.Security.Principal.WindowsIdentity(logonUser); wic = ((System.Security.Principal.WindowsIdentity)identity).Impersonate(); } internal void Undo() { if( wic != null) wic.Undo(); }} Declare the WindowsImpersonationContext thread static, to avoid collisions between different running orchestrations.In the orchestration you should define a scope to: 1. Impersonate the caller2. Send the message and receive the response3. Undo the impersonation to restablish the biztalk service security contextIn the exception handlerUndo the impersonation
Note that the BizTalk host has to run under a domain account, that you have to create a service principal name for that account, and configure it to be trusted for delegation to the specified service
A better approach maybe is to encapsulate that logic inside a pipeline component, that you can apply to any send port that needs to flow credentials.