Skip to content

ASP.NET core 2.2.4 impersonation not working with SocketsHttpHandler #29351

Closed
@Cynthia-Jiang

Description

@Cynthia-Jiang

environment:
DC: windows server 2012R2
server1: windows server 2016, ASP.NET core 2.2.4 web API on IIS with windows authentication enabled
server2: windows server 2012R2, ASP.NET core 2.2 web api on IIS with windows authentication enabled
client: any browsers
client -> server1 -> server2.
the ASP.NET core app in server1 will impersonate the authenticated user then call server 2 web api.
i have configured app pools on both servers to use service account, and have configured SPN accordingly, added delegation setting for the service account of server1.

sample code of how i do impersonate:

var windowsIdentity = (WindowsIdentity)this.HttpContext.User.Identity;

await (WindowsIdentity.RunImpersonated(windowsIdentity.AccessToken, async () =>
{
	
    using (HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, "http://winsvr12r2-1.jiangya1.lab:4000/api/values"))
    {
		
        string user_name = WindowsIdentity.GetCurrent().Name;
        
		try
        {
			
            var response = await _client.SendAsync(requestMessage);
            
			var responseString = await response.Content.ReadAsStringAsync();
            
			result = ($"Called API as: {WindowsIdentity.GetCurrent().Name}.\n\n" +
                               $"{responseString}\n");
        
		}
        
		catch (Exception ex)
        {
        
			result = ex.ToString();
        }
    }
}));
return result;

expected scenario: the impersonation process would succeed,and server2 gets requests from the initial credential.
real scenario: server1 would throw following exception:

System.Net.Http.HttpRequestException: This is usually a temporary error during hostname resolution and means that the local server did not receive a response from an authoritative server ---> System.Net.Sockets.SocketException: This is usually a temporary error during hostname resolution and means that the local server did not receive a response from an authoritative server
   at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask`1 creationTask)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.AuthenticationHelper.SendWithAuthAsync(HttpRequestMessage request, Uri authUri, ICredentials credentials, Boolean preAuthenticate, Boolean isProxyAuth, Boolean doRequestAuth, HttpConnectionPool pool, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at WebApplication2.Controllers.PassThroughController.<>c__DisplayClass5_0.<<Get>b__0>d.MoveNext() in C:\Users\jiangya\source\repos\WebApplication2\WebApplication2\Controllers\PassThroughController.cs:line 92

further troubleshooting:
while doing debugging, i found that if i turn off SocketsHttpHandler following this
and use HTTPClientHandler, the issue will get resolved. which seems indicate that ASP.NET core impersonation is not working with SocketsHttpHandler.
i also attached full callstack here:
working-callstack.txt
non-working-callstack.txt

I understand the new socket handler is designed to eliminate platform dependencies, however can you suggest how to make it work with impersonation?

non-working callstack with SocketsHttpHandler:

0:030> !\\**********\shared\Microsoft.NETCore.App\2.2.4\sos.clrstack
OS Thread Id: 0xe00 (30)
        Child SP               IP Call Site
000000d9e19fbf78 00007ffca5a60160   Interop+Winsock.GetAddrInfoExW(System.String, System.String, Int32, IntPtr, System.Net.Sockets.AddressInfoEx ByRef, System.Net.Sockets.AddressInfoEx* ByRef, IntPtr, System.Threading.NativeOverlapped ByRef, LPLOOKUPSERVICE_COMPLETION_ROUTINE, IntPtr ByRef)
000000d9e19fbf78 00007ffc343c65a4   Interop+Winsock.GetAddrInfoExW(System.String, System.String, Int32, IntPtr, System.Net.Sockets.AddressInfoEx ByRef, System.Net.Sockets.AddressInfoEx* ByRef, IntPtr, System.Threading.NativeOverlapped ByRef, LPLOOKUPSERVICE_COMPLETION_ROUTINE, IntPtr ByRef)
000000d9e19fbf20 00007ffc343c65a4 DomainBoundILStubClass.IL_STUB_PInvoke(System.String, System.String, Int32, IntPtr, System.Net.Sockets.AddressInfoEx ByRef, System.Net.Sockets.AddressInfoEx* ByRef, IntPtr, System.Threading.NativeOverlapped ByRef, LPLOOKUPSERVICE_COMPLETION_ROUTINE, IntPtr ByRef)
000000d9e19fc040 00007ffc8aaafba8 System.Net.NameResolutionPal.GetAddrInfoAsync(System.Net.DnsResolveAsyncResult)  
000000d9e19fc110 00007ffc8aaac27b System.Net.Dns.HostResolutionBeginHelper(System.String, Boolean, Boolean, System.AsyncCallback, System.Object)  
000000d9e19fc190 00007ffc8aaacea8 System.Net.Dns.BeginGetHostAddresses(System.String, System.AsyncCallback, System.Object)  
000000d9e19fc1e0 00007ffc8ab1bcc2 System.Net.Sockets.MultipleConnectAsync.StartConnectAsync(System.Net.Sockets.SocketAsyncEventArgs, System.Net.DnsEndPoint)  
000000d9e19fc250 00007ffc8ab08f23 System.Net.Sockets.Socket.ConnectAsync(System.Net.Sockets.SocketType, System.Net.Sockets.ProtocolType, System.Net.Sockets.SocketAsyncEventArgs)  
000000d9e19fc2b0 00007ffc343c5d98 System.Net.Http.ConnectHelper+d__2.MoveNext()  
000000d9e19fc3a0 00007ffc343c5759 System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start 
000000d9e19fc410 00007ffc8a95726e System.Net.Http.ConnectHelper.ConnectAsync(System.String, Int32, System.Threading.CancellationToken)
000000d9e19fc4d0 00007ffc8a95afae System.Net.Http.HttpConnectionPool+d__44.MoveNext()  
000000d9e19fc6e0 00007ffc343c51e9 System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start 
000000d9e19fc750 00007ffc8a95950e System.Net.Http.HttpConnectionPool.CreateConnectionAsync(System.Net.Http.HttpRequestMessage, System.Threading.CancellationToken)
000000d9e19fc850 00007ffc343c4d29 System.Net.Http.HttpConnectionPool.GetConnectionAsync(System.Net.Http.HttpRequestMessage, System.Threading.CancellationToken)  
000000d9e19fc9f0 00007ffc8a95a662 System.Net.Http.HttpConnectionPool+d__39.MoveNext()  
000000d9e19fcaf0 00007ffc343c3ff9 System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start 
000000d9e19fcb60 00007ffc8a959225 System.Net.Http.HttpConnectionPool.SendWithRetryAsync(System.Net.Http.HttpRequestMessage, Boolean, System.Threading.CancellationToken)
000000d9e19fcc00 00007ffc8a9593ee System.Net.Http.HttpConnectionPool.SendWithProxyAuthAsync(System.Net.Http.HttpRequestMessage, Boolean, System.Threading.CancellationToken)  
000000d9e19fcc60 00007ffc8a9457a2 System.Net.Http.AuthenticationHelper+d__16.MoveNext()  
000000d9e19fcd60 00007ffc343c3cf9 System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start 
000000d9e19fcdd0 00007ffc8a9443fb System.Net.Http.AuthenticationHelper.SendWithAuthAsync(System.Net.Http.HttpRequestMessage, System.Uri, System.Net.ICredentials, Boolean, Boolean, Boolean, System.Net.Http.HttpConnectionPool, System.Threading.CancellationToken)
000000d9e19fce90 00007ffc8a95946c System.Net.Http.HttpConnectionPool.SendAsync(System.Net.Http.HttpRequestMessage, Boolean, System.Threading.CancellationToken)  
000000d9e19fcef0 00007ffc8a95c79c System.Net.Http.HttpConnectionPoolManager.SendAsyncCore(System.Net.Http.HttpRequestMessage, System.Uri, Boolean, Boolean, System.Threading.CancellationToken)  
000000d9e19fcfd0 00007ffc8a95c93a System.Net.Http.HttpConnectionPoolManager.SendAsync(System.Net.Http.HttpRequestMessage, Boolean, System.Threading.CancellationToken)  
000000d9e19fd030 00007ffc8a958cea System.Net.Http.HttpAuthenticatedConnectionHandler.SendAsync(System.Net.Http.HttpRequestMessage, System.Threading.CancellationToken)  
000000d9e19fd060 00007ffc8a95f388 System.Net.Http.RedirectHandler+d__4.MoveNext()  
000000d9e19fd100 00007ffc343c2729 System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start 
000000d9e19fd170 00007ffc8a95efba System.Net.Http.RedirectHandler.SendAsync(System.Net.Http.HttpRequestMessage, System.Threading.CancellationToken)
000000d9e19fd1f0 00007ffc8a95ead2 System.Net.Http.SocketsHttpHandler.SendAsync(System.Net.Http.HttpRequestMessage, System.Threading.CancellationToken)  
000000d9e19fd240 00007ffc8a93a259 System.Net.Http.HttpClientHandler.SendAsync(System.Net.Http.HttpRequestMessage, System.Threading.CancellationToken)  
000000d9e19fd290 00007ffc8a93ce42 System.Net.Http.HttpMessageInvoker.SendAsync(System.Net.Http.HttpRequestMessage, System.Threading.CancellationToken)  
000000d9e19fd2e0 00007ffc8a936954 System.Net.Http.HttpClient.SendAsync(System.Net.Http.HttpRequestMessage, System.Net.Http.HttpCompletionOption, System.Threading.CancellationToken)  
000000d9e19fd350 00007ffc343bf2fd Error: Failed to load C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.4\coreclr.dll
WebApplication2.Controllers.PassThroughController+c__DisplayClass5_0+b__0>d.MoveNext()
000000d9e19fd3c0 00007ffc343bf109 System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start 
000000d9e19fd430 00007ffc343bf098 WebApplication2.Controllers.PassThroughController+c__DisplayClass5_0.b__0()
000000d9e19fd4a0 00007ffc8ba09446 System.Security.Principal.WindowsIdentity+c__DisplayClass60_0`1 .b__0()
000000d9e19fd4d0 00007ffc8ba09517 System.Security.Principal.WindowsIdentity+c__DisplayClass64_0.b__0(System.Object)  
000000d9e19fd510 00007ffc8d3c2019 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)  
000000d9e19fd590 00007ffc8ba07993 System.Security.Principal.WindowsIdentity.RunImpersonatedInternal(Microsoft.Win32.SafeHandles.SafeAccessTokenHandle, System.Action)  
000000d9e19fd5e0 00007ffc8ba077df System.Security.Principal.WindowsIdentity.RunImpersonated 
000000d9e19fd630 00007ffc343be842 WebApplication2.Controllers.PassThroughController+d__5.MoveNext()
000000d9e19fd690 00007ffc343be5d9 System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start 
000000d9e19fd700 00007ffc343be558 WebApplication2.Controllers.PassThroughController.Get()

working callstack with HttpClientHandler:

0:014> k
Child-SP          RetAddr           Call Site
00 000000b3`80a7e140 00007ffc`a5a5ec39 
ws2_32!WinsockThreadpool_CreateWorkContext+0x9b   
01 000000b3`80a7e180 00007ffc`a5a59684 ws2_32!WinsockThreadpool_SubmitWork+0x45   
02 000000b3`80a7e1d0 00007ffc`a5a58009 ws2_32!NSQUERY::LookupServiceNextAsync+0x154   
03 000000b3`80a7e250 00007ffc`a5a56b67 ws2_32!WSALookupServiceNextAsyncW+0x169   
04 000000b3`80a7e2b0 00007ffc`a5a57070 ws2_32!NSSUBJOB::LookupAsyncAndHandleResultsQDNS4F+0xb7   
05 000000b3`80a7e340 00007ffc`a5a5717e ws2_32!NSSUBJOB::TrySubmitQDNS4F+0x6c   
06 000000b3`80a7e390 00007ffc`a5a56814 ws2_32!NSSUBJOB::TrySubmit+0x8e   
07 000000b3`80a7e3f0 00007ffc`a5a55f06 ws2_32!NSJOB::SubmitChild+0x44   
08 000000b3`80a7e440 00007ffc`a5a56329 ws2_32!NSJOB::ForEachChild+0xd6   
09 (Inline Function) --------`-------- ws2_32!NSJOB::ForEachChild+0x12   
0a 000000b3`80a7e490 00007ffc`a5a57201 ws2_32!NSJOB::TrySubmit+0x89   
0b 000000b3`80a7e4f0 00007ffc`a5a56814 ws2_32!NSSUBJOB::TrySubmit+0x111   
0c 000000b3`80a7e550 00007ffc`a5a55f06 ws2_32!NSJOB::SubmitChild+0x44   
0d 000000b3`80a7e5a0 00007ffc`a5a56329 ws2_32!NSJOB::ForEachChild+0xd6   
0e (Inline Function) --------`-------- ws2_32!NSJOB::ForEachChild+0x12   
0f 000000b3`80a7e5f0 00007ffc`a5a55913 ws2_32!NSJOB::TrySubmit+0x89   
10 000000b3`80a7e650 00007ffc`a5a6145c ws2_32!NSMASTERJOB::TrySubmit+0x53   
11 000000b3`80a7e690 00007ffc`99109ac1 ws2_32!GetAddrInfoExW+0x12fc   
12 000000b3`80a7e8d0 00007ffc`991099d1 webio!WapDnsResolveGeneric+0xd9   
13 000000b3`80a7e9c0 00007ffc`99108e3e webio!WapStartDnsIoContext+0x31   
14 000000b3`80a7e9f0 00007ffc`99108a6e webio!WaStartDnsQuery+0x21e   
15 000000b3`80a7eab0 00007ffc`99108fa4 webio!WapTcpStartDnsQuery+0x38e   
16 000000b3`80a7eb40 00007ffc`991090b7 webio!WaTcpConnectRequest+0x54   
17 000000b3`80a7eb90 00007ffc`99102f44 webio!WapHttpConnect+0x107   
18 000000b3`80a7ec20 00007ffc`99102da8 webio!WaQueueHttpRequest+0x144   
19 (Inline Function) --------`-------- webio!WapStartQueueRequest+0x1c   
1a (Inline Function) --------`-------- webio!WapGetConnectionCompletionRoutine+0x5c   
1b 000000b3`80a7ecc0 00007ffc`99102c88 webio!WapStartGetConnection+0xf8   
1c 000000b3`80a7ed10 00007ffc`99102b16 webio!WapStartGetEndpoints+0x44   
1d 000000b3`80a7ed40 00007ffc`99105008 webio!WapAsynchronousSendHttpRequest+0x266   
1e (Inline Function) --------`-------- webio!WapSendHttpRequest+0x2f   
1f 000000b3`80a7ee20 00007ffc`9f001c65 webio!WebSendHttpRequest+0x38   
20 (Inline Function) --------`-------- winhttp!WEBIO_SENDER::SendRequest+0x21d   
21 000000b3`80a7ee80 00007ffc`9f007528 winhttp!WEBIO_REQUEST::SendRequest+0x415   
22 000000b3`80a7ef70 00007ffc`9f007b60 winhttp!HTTP_USER_REQUEST::_SysSendRequest+0x1028   
23 000000b3`80a7f170 00007ffc`9f00783b winhttp!HTTP_USER_REQUEST::_SendRequestWithDrainComplete+0x2d0   
24 000000b3`80a7f200 00007ffc`9f0023fb winhttp!HTTP_USER_REQUEST::_SendRequestWithProxyInitialized+0x6b   
25 000000b3`80a7f230 00007ffc`9efe3a57 winhttp!HTTP_USER_REQUEST::OnProxyResolvedOnSend+0xbf   
26 000000b3`80a7f280 00007ffc`9efe3710 winhttp!UserRequestProxyCompletion::OnProxyResolved+0x27   
27 000000b3`80a7f2b0 00007ffc`9efe351e winhttp!WxProxyManager::WxProxyFailoverCompletionRoutine+0x90   
28 000000b3`80a7f2e0 00007ffc`a60dec59 winhttp!RefCountWorkItemThread+0x1e   
29 000000b3`80a7f310 00007ffc`a60c328a ntdll!RtlpTpWorkCallback+0x129   
2a 000000b3`80a7f3f0 00007ffc`a4e98364 ntdll!TppWorkerThread+0x4aa   
2b 000000b3`80a7f7f0 00007ffc`a60f7091 KERNEL32!BaseThreadInitThunk+0x14   
2c 000000b3`80a7f820 00000000`00000000 ntdll!RtlUserThreadStart+0x21   

Metadata

Metadata

Assignees

Labels

blockedIssue/PR is blocked on something - see commentsbug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions