How to customize error code in custom AuthenticationHandler

2k Views Asked by At

There is a customized AuthenticationHandler named CustomAuthenticationHandler which default error code is 401. But I have to response with different error code and error message in different conditions.

If the request should response 403 in some condition and current solution shows below:

public class CustomAuthenticationHandler: AuthenticationHandler<MSGraphAuthenticationOptions>
{
    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        if (xxx) 
        {        
            var response = this.httpContextAccessor.HttpContext.Response;
            response.StatusCode = StatusCodes.Status403Forbidden;
            await response.WriteAsync("test");
            return AuthenticateResult.NoResult();
        }
    }
}

The error code of the http response is 403 which is expected, but the reqeust still run into next() and it would throw error:

System.InvalidOperationException: StatusCode cannot be set because the response has already started.

at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext.ThrowResponseAlreadyStartedException(String name)

at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext.set_StatusCode(Int32 value)

at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext.Microsoft.AspNetCore.Http.Features.IHttpResponseFeature.set_StatusCode(Int32 value)

at Microsoft.AspNetCore.Http.DefaultHttpResponse.set_StatusCode(Int32 value)

at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.HandleChallengeAsync(AuthenticationProperties properties)

at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.ChallengeAsync(AuthenticationProperties properties)

at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)

at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)

at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)

at Microsoft.Management.Services.CloudPC.Api.Middlewares.MetricsMiddleware.InvokeAsync(HttpContext context, ILoggerX logger)

How can I stop the middlerware flow after await response.WriteAsync("test");?

1

There are 1 best solutions below

3
On

If your authentication fails, you should call AuthenticateResult.Fail("<your custom message here>"); so the rest of the pipeline doesn't get executed.

Anyway, 403 error message is returned when Authorization fails, not in the case of Authentication fail, so you might set your authorization policies as described here: https://learn.microsoft.com/en-us/aspnet/core/security/authorization/simple?view=aspnetcore-3.1