2

I have an ASP.NET Core MVC application that uses Windows Authentication to log in Users with their AD accounts. I now need to add a WebAPI component for external systems to interface with the app. However the consumers of the WebAPI need to authenticate using Bearer Tokens. My thought is to separate the application into 2 Areas - WebApp, which is the current MVC Controllers and Views; and WebAPI, which will be the REST Controllers.

Is there a way to configure one Area to use Windows Auth (IISDefaults.AuthenticationScheme) and the other Area to use Bearer Tokens?

Valuator
  • 3,262
  • 2
  • 29
  • 53
  • I don't know about Areas, but you can do this on a per Controller basis [using the `[Authorize]` attribute](https://learn.microsoft.com/en-us/aspnet/core/security/authorization/limitingidentitybyscheme?view=aspnetcore-2.2&tabs=aspnetcore2x). [This answer](https://stackoverflow.com/questions/2319157/how-can-we-set-authorization-for-a-whole-area-in-asp-net-mvc) suggests you can add it Authorize attribute to a base controller class and then inherit all controllers in that area from that base. – jmoerdyk Jan 24 '19 at 19:06

1 Answers1

4

There is always a way :)

Let's say you have an area - Area55 - with an api controller - AlienController -

Create your custom Controller Model Convention so that any controller under Area55 will be authorized by apipolicy

    public class MyAuthorizeFiltersControllerConvention : IControllerModelConvention
    {
        public void Apply(ControllerModel controller)
        {
            string apiArea;

            if (controller.RouteValues.Any() 
                && controller.RouteValues.TryGetValue("area", out apiArea) 
                && apiArea.Equals("Area55"))
            {
                controller.Filters.Add(new AuthorizeFilter("apipolicy"));
            }
            else
            {
                controller.Filters.Add(new AuthorizeFilter("defaultpolicy"));
            }
        }
    }

Then register it in startup.cs

    services.AddMvc(o =>
            {
                o.Conventions.Add(new MyAuthorizeFiltersControllerConvention());
            });

still in your startup.cs, configure the policies to use the authentication scheme that we want

    services.AddAuthorization(o =>
            {
                o.AddPolicy("defaultpolicy", b =>
                {
                    b.RequireAuthenticatedUser();
                    b.AuthenticationSchemes = new List<string> { IISDefaults.AuthenticationScheme };
                });
                o.AddPolicy("apipolicy", b =>
                {
                    b.RequireAuthenticatedUser();
                    b.AuthenticationSchemes = new List<string> { JwtBearerDefaults.AuthenticationScheme };
                });
            });

The controller might be something like this

    [Area("Area55")]
    [Route("[area]/api/[controller]")]
    [ApiController]
    public class AlienController : ControllerBase
    {
    }

That's all I guess.

Laksmono
  • 690
  • 5
  • 12