.Net Core 2.x Redirect to Error Page

Xiao Han picture Xiao Han · May 14, 2018 · Viewed 9.6k times · Source

I have a simple ASP.Net Core 2.0 web application and I have enabled Windows Authentication in project property by enabling Windows Authentication and disabled Anonymous Authentication.

For Authorization at Application/Site level filtering by AD security group, I have the following code in Startup.cs:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        services.AddAuthentication(IISDefaults.AuthenticationScheme);

        services.AddMvc(config =>
        {
            var policy = new AuthorizationPolicyBuilder()
                                .RequireAuthenticatedUser()
                                .RequireRole("Application - Administrator")
                                .Build();
            config.Filters.Add(new AuthorizeFilter(policy));
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseBrowserLink();
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();

        app.UseAuthentication();

        //app.UseStatusCodePagesWithRedirects("/Home/Error/{0}");
        //app.UseStatusCodePagesWithReExecute("/Home/Error", "?statusCode={0}");

        app.UseStatusCodePagesWithReExecute("/Home/Error/{0}");



        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

To handle Http 403 status code when a un-authorized user tries to access the application, it will be redirect to a custom error page. So I tried the following 3 approaches in Configure method within Startup.cs:

app.UseStatusCodePagesWithRedirects("/Home/Error/{0}");
app.UseStatusCodePagesWithReExecute("/Home/Error", "?statusCode={0}");
app.UseStatusCodePagesWithReExecute("/Home/Error/{0}");

In the HomeController, I tried both the default Error method

public IActionResult Error()
{
    return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}

and customized one to handle specific status code:

public IActionResult Error(string errCode)
{
    if (errCode == "500" || errCode == "404" || errCode == "403")
    {
        return View($"~/Views/Error/{errCode}.cshtml");
    }

    return View("~/Views/Shared/Error.cshtml");
}

And I have a simple error page 403.cshtml under /Views/Error/ folder.

But none of them works, all display this page: enter image description here

I am wondering if something I missed or forgot to implement for display a formatted error page?

Thanks in advance.

Answer

David Liang picture David Liang · May 14, 2018

I am not 100% sure but there should be 2 variations of windows authentications:

  1. The host only allows authenticated users

    • When you enable Windows Authentication and disable Anonymous Users
    • [Authorize] and [AllowAnonymous] no effect, because unauthenticated requests never reach your application
    • Hence you can't / don't need to set up global filter. You might have to setup the friendly error pages on the server?

      public class Startup
      {
          public IConfiguration Configuration { get; }
      
          public Startup(IConfiguration configuration)
          {
              Configuration = configuration;
          }
      
          public void ConfigureServices(IServiceCollection services)
          {
              services.AddMvc();
          }
      
          public void Configure(IApplicationBuilder app, IHostingEnvironment env)
          {
              if (env.IsDevelopment())
              {
                  app.UseDeveloperExceptionPage();
              }
              else
              {
                  app.UseExceptionHandler("/home/error");
              }
      
              app.UseStaticFiles();
      
              app.UseMvcWithDefaultRoutes();
          }
      }
      
  2. The host allows both anonymous and authenticated users

    • When you enable both Windows Authentication and Anonymous Users
    • [Authorize] requires additional setup on Startup.cs

      public void ConfigureServices(IServiceCollection services)
      {
          services.AddAuthentication(IISDefaults.AuthenticationScheme);
      
          services.AddMvc(config =>
          {
              var policy = new AuthorizationPolicyBuilder()
                 .RequireRole("Application - Administrator")
                 .Build();
      
              config.Filters.Add(new AuthorizeFilter(policy));
          });
      }
      
      public void Configure(IApplicationBuilder app, IHostingEnvironment env)
      {
          ...
      
          app.UseStatusCodePagesWithReExecute("/error", "?code={0}");
      
          app.UseAuthentication();
      
          app.UseMvcWithDefaultRoutes();
      }
      
    • You need to use [AllowAnonymous] on the error controller to override the [Authorize] global filter to allow anonymous requests.

      [AllowAnonymous]
      public class ErrorController : Controller
      {
          public IActionResult Index(int? code)
          {
              ...
          }
      }