Course contentsShow
← C#
Lesson 1218 of 1,90811. Identity, Security, and ClaimsFree lesson

Authorization Failure Handling

Customize unauthorized and forbidden responses to provide secure and helpful feedback.

In this lesson, you will learn how to transition from generic security errors to user-friendly, descriptive responses when authorization fails.

When an authorization policy fails, ASP.NET Core defaults to standard HTTP status codes: 401 Unauthorized (when the user isn't logged in) or 403 Forbidden (when the user is logged in but lacks the required permissions). While secure, these default responses tell the user nothing about why they were blocked or what they should do next.

Customizing the Experience

To provide helpful feedback without leaking sensitive system information, we use an IAuthorizationMiddlewareResultHandler. This service intercepts the authorization result before it reaches the client. Instead of a blank page, you can return a structured JSON response or a custom view that guides the user.

For example, if a user tries to access a restricted resource, you can inspect the AuthorizationPolicy to provide specific context:

public class CustomAuthorizationHandler : IAuthorizationMiddlewareResultHandler
{
    private readonly AuthorizationMiddlewareResultHandler _defaultHandler = new();

    public async Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
    {
        if (authorizeResult.Forbidden)
        {
            context.Response.StatusCode = StatusCodes.Status403Forbidden;
            await context.Response.WriteAsJsonAsync(new { 
                Message = "You do not have the required clearance to view this resource.",
                ErrorCode = "INSUFFICIENT_PERMISSIONS" 
            });
            return;
        }

        await _defaultHandler.HandleAsync(next, context, policy, authorizeResult);
    }
}

Security Considerations

When customizing these responses, be careful not to reveal "existence proofs." For example, do not report that a user "does not have the 'Admin' role" if that information helps an attacker map your authorization structure. Instead, use generic but actionable messaging. By implementing a custom handler, you maintain control over the communication channel, ensuring that your application remains professional and usable even when access is denied.

Key Takeaway: Use a custom IAuthorizationMiddlewareResultHandler to translate cryptic security status codes into helpful, secure feedback that improves the user experience without compromising system integrity.