-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Description
Scenario:
- Using Windows Authentication with Kestrel (on Windows)
- Results in [Authorize] can pass through as an unauthorized request
( in certain situations)
I ended up with this scenario after using IIS Express which worked fine to produce a Windows Identity object. Switching to Kestrel (on Windows) I got the result above.
There are two problems here:
- Context.User.Identity returns ClaimsIdentity instead of WindowsIdentity
- Context.User.Identiy.IsAuthenticated is false inside of a controller with
[Authorize]
After a Twitter discussion with Damien and Barry it turns out that this specific scenario was caused by a specific middleware order, but only on Kestrel. The same code below works when using IIS Express.
In ConfigureServices():
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();In Configure():
app.UseAuthentication();
app.UseAuthorization();
app.UseCors("CorsPolicy");
// THIS IS THE PROBLEM - has to happen BEFORE .UseAuthorization
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});Note .UseRouting() comes after .UseAuthorization() and .UseAuthentication() and that's what's apparently causing the non-authorization on the controller.
Switching the configuration code to:
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCors("CorsPolicy");
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});makes the problem go away. WIth this in place both IIS Express and Kestrel now work with Windows Auth and produce a proper WindowsIdentity.
Expected Behavior
That the middleware order needs to be a certain way is understandable if confusing and non-discoverable, although it would be nice if there was some way to notify via error or warning if the order is not viable (if possible).
The more serious problem though is that the [Authorize] attribute on the controller in the failure scenario fails to block the request completely. Instead it passes through the request as if there was no authorization present at all. This should fail.
