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:
HttpInspector
, I do not receive the status 401, the status code I receive is 0program.cs
file in ASP.NET Core Web API):Screenshot of CORS configuration in Program.cs
:
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:
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:
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?
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.