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.
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());