My application uses Net 5.0 Microsoft.AspNetCore.ApiAuthorization.IdentityServer and IdentityServer4. If Windows Authentication is enabled in IIS, it issues an NTLM challenge to acquire a WindowsPrincipal from the HttpContext.User as described in the IdentityServer documentation: https://docs.identityserver.io/en/latest/topics/windows.html. My implementation is very similar though not exactly the same - it falls back to an in-app sign-in form, if Windows Authentication is not enabled in IIS.
This works fine as long as Anonymous Authentication is enabled in IIS, but not if Anonymous Authentication is disabled. To be precise:
- Anonymous and Windows Authentication enabled: This works, user is signed in using username recovered from the WindowsPrincipal
- Anonymous Authentication only enabled: This works, user signs in via the sign in form
- Windows Authentication only enabled: This does not work, and this is what my question is about
Firstly, when Windows Authentication is enabled, there is this difference:
If Anonymous Authentication is disabled, there is an automatic negotiation taking place for all requests. This means that the browser and IIS automatically handles the NTLM challenge and negotiation. As a result, the HttpContext of the initial request arriving in the application already has an authenticated Windows Principal assigned to the HttpContext.User.Identity
If Anonymous Authentication is enabled, then this automatic negotiation does not take place and the application needs to handle the NTLM negotiation itself to get the authenticated WindowsPrincipal (as indeed described in the IdentityServer4 documentation in the link above)
The above is my understanding, please correct me if I am wrong.
Regardless of alternative 1 or 2, the application looks up the name of the WindowsPrincipal in IdentityServer (the Net 5.0 SignInManager) and - if found - does an automatic signin. This works, there is a correct redirect to the IdentityServer callback, and subsequently a redirect to the return url with a Token with all the necessary claims - all honky-dory.
The problem appears when the application running in the browser then makes a request to the IdentityServer userinfo endpoint. Again, no problem if Anonymous Authentication is enabled. But if Anonymous Authentication is disabled, then this request triggers a Windows Authentication 401 challenge causing the browser to prompt for (windows) credentials.
This challenge persists and does not accept any valid Windows credentials. Cancelling the challenge results in a 401, with the response header asking for a NTLM negotiation:
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
Importantly, this request to the userinfo does contain a valid bearer token, so the user has been authenticated and a valid token has been issued. It seems like the userinfo endpoint in IdentityServer4 requires Anonymous Authentication to be enabled.
Is there any way out of this? Or is it impossible to use IdentityServer4 in IIS without Anonymous Authentication?