Skip to content

Windows Authentication with Kestrel can ignore Authorization due to Middleware Order #14049

@RickStrahl

Description

@RickStrahl

Scenario:

  • Using Windows Authentication with Kestrel (on Windows)
  • Results in [Authorize] can pass through as an unauthorized request
    ( in certain situations)

image

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.

Metadata

Metadata

Assignees

Labels

DoneThis issue has been fixedarea-mvcIncludes: MVC, Actions and Controllers, Localization, CORS, most templatesbugThis issue describes a behavior which is not expected - a bug.

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions