WCF double impersonation?

My setup is a bit complicated, so let me figure it out first.

We have a WCF web service that receives data from different sources through several different APIs and returns this data to the client. The requested security is that this is done over HTTPS (working). The IIS standard is that for the application pool you should use the basic IIS network service account and use .net impersonation.

My problem is that the web service should always be started under the AD process ID regardless of who calls it, but also needs to check which AD groups the caller works in to determine which features are available. Now I can configure my web.config to use this kind of work so that it always runs like Blah, but then I don’t know how to make it issue / check the caller to find out what functions they have.

** edit: forgot to mention that the calling client should be able to skip UN / PASS instead of its Windows token. The wcf service should check its valid AD UN and PASS, and also ask which groups it is in.

+4
source share
1 answer

It looks like you want HostingEnvironment.Impersonate

Example:

 using (var imp = HostingEnvironment.Impersonate()) { // code now executes in the context of the authenticated user, // rather than the service account } 

This works fantastically, unfortunately, the standard here is not to use application pools, since managing passwords is easier for them if you update them in each command by placing them in web.config

Well, that seems counter-intuitive, but I came across the worst politicians in my time, so I can hardly judge.;)

As I mentioned in my comment, there are Impersonate overloads that allow you to impersonate an arbitrary account. To do this, you must get the Windows authentication token for this user, and this is not trivial, and not, as far as I know, what you can do 100% in managed code. You will have to use an unmanaged code, and you will need to find out the username and password of the account you issued in your application. This is much less secure than just setting up an account as an application pool identifier if you ever want to argue the point with your BTW network architect. Just some ammo for you.

Anyway, here is an example of the code that I adapted from the internet:

 #region native imports. public const int Logon_LogonTypeInteractive = 2; public const int Logon_ProviderDefault = 0; public const int Duplicate_ImpersonationLevelImpersonate = 2; [DllImport("advapi32.dll")] public static extern bool LogonUser(string lpszUserName, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern bool DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken); [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern bool RevertToSelf(); [DllImport("kernel32.dll", CharSet=CharSet.Auto)] public static extern bool CloseHandle(IntPtr handle); #endregion native imports. #region elsewhere... public IntPtr GetWindowsTokenForImpersonation(string username, string password, string domain) { IntPtr loginToken = IntPtr.Zero; IntPtr workingToken = IntPtr.Zero; bool success if(!RevertToSelf()) { return IntPtr.Zero; // failed to eliminate any existing impersonations. This block may not be necessary depending on your code } if(!LogonUserA(username, domain, password, Logon_LogonTypeInteractive, Logon_ProviderDefault, ref loginToken)) { return IntPtr.Zero; // failed to log in the user } if(!DuplicateToken(loginToken, Duplicate_ImpersonationLevelImpersonate, ref workingToken) { if(loginToken != IntPtr.Zero) { CloseHandle(loginToken); } return IntPtr.Zero; // failed to get a working impersonation token } CloseHandle(loginToken); return workingToken; // NOTE: You must dispose this token manually using CloseHandle after impersonation is complete. } #endregion elsewhere #region where you want to impersonate var token = GetWindowsTokenForImpersonation(username, password, domain); if(token != IntPtr.Zero) { using(var imp = HostingEnvironment.Impersonate(token)) { // code here executes under impersonation } CloseHandle(token); } #endregion 
+3
source

Source: https://habr.com/ru/post/1402711/


All Articles