angularasp.net-corecorsasp.net-core-webapiangular-httpclient

ASP.NET Core 6 Web API : custom authentication handler and Angular HttpInterceptor [receive Status code =0 for 401 Unauthorized Response]


I have written a custom authentication handler in .NET Core. The custom handler works fine. If a user is unauthorized, it returns http 401 Unauthorized.

In the UI, I use an Angular HttpInspector to receive the unauthorized response sent from the API.

I faced two problems:

  1. In the HttpInspector, I do not receive the status 401, the status code I receive is 0
  2. For any authenticate user (status code 200 Ok), I do not receive any CORS problem. but for unauthorized response I am getting CORS problem (I also configured the Cors policy in the program.cs file in ASP.NET Core Web API):

enter image description here

Screenshot of CORS configuration in Program.cs:

enter image description here

Here is the code for custom authentication handler:

public class CustomAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
        string failReason;

        // Constructor to initialize base
        public CustomAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) :base(options,logger, encoder, clock)
        {
        }
    
        protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!Request.Headers.ContainsKey("Authorization"))
            {
                failReason = "Himadri You failed";
                return AuthenticateResult.Fail(failReason);
            }
    
            string strAuthorization = Request.Headers["Authorization"];

            if (string.IsNullOrEmpty(strAuthorization)) 
            {
                return AuthenticateResult.Fail("Unauthorized");
            }
    
            try
            {
                var handler = new JwtSecurityTokenHandler();
                string token = strAuthorization.Substring("bearer".Length).Trim();
                var tokenS = handler.ReadToken(token) as JwtSecurityToken;
                //var id = tokenS.Claims.First(claim => claim.Type == "nameid").Value;
    
                var claim = new List<Claim>
                                {
                                    new Claim(ClaimTypes.Name, "himadri")
                                };
                var identity = new ClaimsIdentity(claim, Scheme.Name);
                var principal = new GenericPrincipal(identity, null);
                var ticket = new AuthenticationTicket(principal, Scheme.Name);

                return AuthenticateResult.Success(ticket);
            }
            catch (Exception ex)
            {
                return AuthenticateResult.Fail(ex.Message);
            }
       }
    
       protected override Task HandleChallengeAsync(AuthenticationProperties properties)
       {
            //Response.StatusCode = 401;
    
            if (failReason != null)
            {
                Response.StatusCode = 401;
                Response.Headers.Append("access-control-expose-headers", "WWW-Authenticate");
                   
                Response.Headers.Append("WWW-Authenticate", failReason);
                Response.WriteAsync(failReason);
              
                Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = failReason;
            }
            return Task.CompletedTask;
        }
}

If I call the API from Postman, it shows the status code and header perfectly:

enter image description here

But if call the API from my Angular application [in a HTTPInterceptor], then for unauthenticated user, I get status code = 0 and CORS problem occurs, but for authenticated user data is returned properly, status code = 200 and no CORS problem.

[Please refer to the 1st and 2nd screenshot]

Screenshot of HTTPInterecptor:

enter image description here

What am I missing here? Without receiving proper status code and header, how can I display proper message for unauthenticated/unauthorized users?

How can I receive proper status code and headers in Angular application from .NET Core custom authentication middleware?


Solution

  • Based on OP's confiramtion, putting app.UseCors(); before app.UseAuthentication(); can solved the issue, because CORS middleware should be called before authentication middleware. See middlware order here.