Skip to content

Custom Authorize Attribute that returns 403 when the user is unathorized but authenticated

When building a Web API backend for an Angular2 client recently, I was protecting endpoints using the [Authorize] attribute. After I added user roles, Chrome was popping up the below annoying pop-up asking for credentials when a user wasn’t authorized to access an endpoint.

Auth-required

The problem was that backend was responding with 401 response instead of a 403 response. Here’s how to respond with 403 so the browser doesn’t try to authenticate the user using the above pop-up.

Instead of using the built-in AuthorizeAttribute, we inherit from it and override HandleUnauthorizedRequest to respond with the forbidden 403 status code.

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
namespace <application>
{
/// <summary>
/// Custom Authorize Attribute that returns 403 when the user is unathorized but authenticated.
/// </summary>
class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(HttpActionContext ctx)
{
if (!ctx.RequestContext.Principal.Identity.IsAuthenticated)
base.HandleUnauthorizedRequest(ctx);
else
{
ctx.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden);
}
}
}
}

Usage

Just use CustomAuthorize instead of [Authorize].

TestController.cs

public class TestController : ApiController
{
...
[Route("api/test")]
[CustomAuthorize(Roles = "Admin,ChuckNorris")]
[HttpGet]
public boolean Test () {
...
}
...
}

To protect all APIs, add below line to WebApiConfig.cs. There’s no need of using the CustomAuthorizeAttribute because the annoying dialog box occurs only when not all authenticated users are authorized to access all API endpoints due to Roles.

config.Filters.Add(new AuthorizeAttribute());