skip to Main Content

Consider a controller endpoint like this:

[HttpGet]
public IActionResult Get()
{
    var resource = _myService.GetSomeResource();
    return Ok(resource);
}

The GetSomeResource() method performs validation on the identity of the caller, like this:

public SomeResourceModel GetSomeResource()
{
  _securityVerifier.VerifyCallerHasAccess();

  // do stuff to get resource

  return resource;
}

Within the VerifyCallerHasAccess() method, let’s pretend that the caller does NOT have access to the resource they requested. So, we throw an exception. Something like:

    throw new SecurityException($"User does not have access to this resource");

With all that said, what I want is for the ASP.NET controller to automatically return a 403 when an exception of that type is encountered. By default, it’s just returning a 500. Is it possible to register http response codes to specific types of exceptions? If so, how?

(Note, I know I can wrap my endpoint code in a try/catch, but I don’t want to have to manually do this)


Edit for some clarity: My endpoint is already using .NET’s authorization system. The security verification in question deals with getting the user’s identity and checking against an external security service that they have the appropriate access rights to a given security resource.

3

Answers


  1. You could use some middleware in the request pipeline:

    public class ErrorHandlingMiddleware
    {
        readonly RequestDelegate _next;
        
        public ErrorHandlingMiddleware(RequestDelegate next)
        {
            _next = next;
        }
    
        public async Task Invoke(HttpContext context)
        {
            try
            {
                await _next(context);
            }
            catch (SecurityException ex)
            {
                context.Response.StatusCode = 403;
            }
            catch (Exception ex)
            {
                context.Response.StatusCode = 500;
                await context.Response.WriteAsync(ex.Message);
            }
        }
    }
    

    and then register that in Program.cs:

    app.UseMiddleware<ErrorHandlingMiddleware>();
    
    Login or Signup to reply.
  2. You can write an exception filter (see https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-7.0) or if you want to standardize your responses as well, take a look at Hellang.Middleware.ProblemDetails

    Login or Signup to reply.
  3. If you could modify VerifyCallerHasAccess() method,you could return (or set some property) true or false instead of throw an exception

    in controller,you could try as below:

    if (result)            
    {                
    return Ok();            
    }            
    else            
    {                
    return Problem(detail: "User does not have access to the resource", statusCode: 403);                
    // you could also try return Forbind() to return a 403 with out  the detail
    //check the controllerbase class and you would find more methods related            
        }
    

    if you insist on throw exception, then put

    var resource = _myService.GetSomeResource();
    return Ok(resource)
    

    into try catch block ,return 403 with Forbind() method or other methods you would find in controllerbase class

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search