Open Yustos opened 4 years ago
The 404 is the exception handler trying to redirect to /Home/Error
which doesn't seem to exist in this app.
The actual exception reported in the logs is:
System.InvalidOperationException: An anonymous request was received in between authentication handshake requests.
at Microsoft.AspNetCore.Authentication.Negotiate.NegotiateHandler.HandleRequestAsync()
at Microsoft.AspNetCore.Authentication.Negotiate.NegotiateHandler.HandleRequestAsync()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
Which matches https://github.com/dotnet/aspnetcore/issues/20100 (closed as stale). There wasn't enough information before to debug it, but it looks like we have more now...
When you're doing this authentication are you using the machine's fully qualified active directory name? Using an alternate name isn't going to work unless you've set up proper SPNs.
From the logs: Request 1) Anonymous, authorization failed, Challenge 401 Negotiate Request 2) Authorization: Negotiate (kerberos(?) blob), incomplete handshake, 401 Negotiate (blob) Request 3) Authorization: Negotiate (blob), incomplete handshake, 401 Negotiate (blob) Request 4) Anonymous, exception as shown above.
So the main issue seems to be that the server thinks auth is still in progress but the client has given up. This is likely a misconfiguration related to SPNs or similar. It's odd that the client would send another anonymous request after three consecutive 401s.
@blowdart any idea how to get the associated schannel events to get a more specific explanation here?
Note Http.Sys may have worked because it uses kernel mode authentication which means SPNs are configured on the machine account. With Kestrel it's using user mode which means the SPNs must be configured on the user account instead.
Hi, Chris! "When you're doing this authentication are you using the machine's fully qualified active directory name?" - yes. In client browser i used full server name http://example.com:5000/ and have auth error. When i use browser on server - all urls variants works fine: http://localhost:5000, http://example:5000 and http://example.com:5000.
For clear - 404 is strange, but not a root trouble. Problem is authentication.
Postman failed on auth without any additional potential requests (like js, css, favico and other).
To reduce any browser specific network activity i tried powershell:
PS C:\Users\Yustos> $url = "http://example.com:5000"
PS C:\Users\Yustos> $wc = New-Object System.Net.WebClient
PS C:\Users\Yustos> $wc.UseDefaultCredentials = $true
PS C:\Users\Yustos> $response = $wc.DownloadString($url)
Exception calling "DownloadString" with "1" argument(s): "The remote server returned an error: (401) Unauthorized."
At line:1 char:1
+ $response = $wc.DownloadString($url)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
And here is server log: auth_log_by_powershell.txt
Will fiddler logs help you? Thank you for advice!
PS: i tried to apply setspn, but failed:
>setspn -S HTTP/example.com Yustos
Checking domain DC=---,DC=---
Registering ServicePrincipalNames for CN=Yustos,OU=Computers,OU=Clients,DC=---,DC=---
HTTP/example.com
Failed to assign SPN on account 'CN=Yustos,OU=Computers,OU=Clients,DC=---,DC=---',
error 0x2098/8344 -> Insufficient access rights to perform the operation.
I suppose this is not important.
Okay, i am collected fiddler logs for powershell with UseDefaultCredentials calls (HTTP-bodies excluded, tokens shortened). Success with HTTP.SYS: success_http_sys.txt
Fail with Kestrel negotiate: fail_kestrel_negotiate.txt
I am not an Active Directory administrator, so setspn unpermitted. And i believe, that i should not ask administrator to register SPN for every test scenario or dynamically generated urls. So my way is HTTP.SYS or other authentication mechanism.
Last thing is error code. In the attached failure-logs was 400 error after series of handshakes. But sometimes returned error 404 without any handshake: Here details for 404:
GET http://example.com:5000/ HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; ru-RU) WindowsPowerShell/5.1.18362.628
Host: example.com:5000
HTTP/1.1 404 Not Found
Date: Sun, 05 Apr 2020 07:29:13 GMT
Server: Kestrel
Content-Length: 0
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Looks like is one-after-one 400, 404, 400, 404...
Well, confirm, please, that setspn is the strong requirement for Negotiate and close issue. Thank you!
Can you share the server logs for the 400 scenario?
Yes, SPNs are a strong requirement for Negotiate/Kerberos. When you run on the same machine it always defaults to NTLM which does not have the same SPN requirements. When it runs with HttpSys from a separate machine it's using kernel mode auth and the machine account which already has SPNs configured by default. When it's using Kestrel and user-mode auth from a remote machine it can't find any SPNs in the user account, tries to fall back to NTLM, but then gives up after a few round trips (not sure why yet).
@JunTaoLuo this would be a good situation for you to repro with your current setup.
The 404 is likely the same redirect to /home/error
as before. The server logs would show that.
I did test again and this was my false - 400/404 problem is valid when i use fiddler as proxy to client-side requests sniffing. This command will produce 400/404 errors:
Invoke-WebRequest -Uri "http://example.com:5000" -UseDefaultCredentials -Proxy http://localhost:8888
But this is stable 401:
Invoke-WebRequest -Uri "http://example.com:5000" -UseDefaultCredentials
Invoke-WebRequest : The remote server returned an error: (401) Unauthorized.
At line:1 char:1
+ Invoke-WebRequest -Uri "http://example.com:5000" -UseDefaultCredent ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebExc
eption
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
Here is server log for 401 without proxy (single call): server.txt
Anyway, i can not use Kestrel negotiate with SPN's. I want to use dynamic subdomains and i have no opportunity to dynamically register SPN's in Active Directory. For my case HTTP.SYS and IIS works fine :(
Chris, thank you for explanation about SPN! I'm sorry for your time.
FYI, the 401s we were seeing seem to be caused by the missing SPNs. I am able to reproduce the 401 errors on my local VMs when the SPNs are not configured and I am able to run your repro project successfully when I do have the SPN configured correctly. I think all the questions here have been resolved, please let us know if you have any other issues @Yustos
@JunTaoLuo did you ever see the InvalidOperationException?
Triage: @JunTaoLuo is going to take a quick look at a few other clients (Legacy Edge/Edgium, etc.) to see if we can repro the InvalidOperationException. We do require an SPN though so I don't think there's much we can do about that. Using HttpSys is probably a better option in this scenario.
@JunTaoLuo was able to identify that Edge Chromium does indeed produce this error when SPNs aren't configured. We're forwarding the details on to that team for further investigation.
Error in Windows Authentication using Kestrel still reproduce (package Microsoft.AspNetCore.Authentication.Negotiate, guide https://docs.microsoft.com/ru-ru/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.1&tabs=visual-studio#kestrel). Same error in related issue. But i collected logs and prepare example to reproduce bug.
Example in branch: https://github.com/Yustos/AspNetCoreSubdomain/commits/auth_trouble Reproduce steps:
You can see error 404 in browser and this topic error in log. Or you can try postman get query with NTLM auth - there will be 401 error and same error in server log.
In the fiddler all three negotiate requests exists, bug without success: № Result Protocol Host URL Body Caching Content-Type Process Comments Custom
7 401 HTTP example.com:5000 / 0 postman:119596
8 401 HTTP example.com:5000 / 0 postman:119596
9 401 HTTP example.com:5000 / 0 postman:119596
There is connection log, as you ask:
auth_log.txt
Remark: i replaced server name to
example.com
and username from domain to Yustos in attached log.At last, i was tried HTTP.SYS auth (see commented code in example branch https://github.com/Yustos/AspNetCoreSubdomain/commit/d39dd1f729c34d7ea36f4e807303b1c7687c34a2) - it work fine.
I followed auth example prepare by this guide on windows (client and server): https://docs.microsoft.com/ru-ru/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.1&tabs=visual-studio#kestrel Except setspn command: https://docs.microsoft.com/ru-ru/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.1&tabs=visual-studio#windows-environment-configuration