I have an custom authentication scheme in .Net core where I want to return a specific response for some specific kinds of authentication failures (as opposed to just returning a 401). My current approach looks something like this:
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
var token = GetToken();
if (string.IsNullOrWhiteSpace(token))
{
return AuthenticateResult.NoResult();
}
var validationResult = _tokenContextProvider.Validate(); // validate
if (validationResult != TokenValidationResult.Ok)
{
await updateResponseCode(Context, validationResult);
return AuthenticateResult.Fail("Token invalid");
}
//success
var userContext = tokenContextProvider.GetUserContext();
var ticket = GetAuthenticationTicket(userContext);
return AuthenticateResult.Success(ticket);
}
private static async Task updateResponseCode(HttpContext context, TokenValidationResult validationResult)
{
if (!context.Response.HasStarted)
{
if (validationResult == TokenValidationResult.SpecialError)
{
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
var errorMessage = JsonConvert.SerializeObject(new
{
error = new
{
message = validationResult.Message
}
});
context.Response.Headers["Content-Type"] = "application/json";
await context.Response.WriteAsync(errorMessage, Encoding.UTF8);
}
}
}
This is fine and returns the response code I want. However, another bit of middleware (I'm assuming) is then trying to set the StatusCode after and resulting in some exceptions being logged.
Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext in ThrowResponseAlreadyStartedException
System.InvalidOperationException: StatusCode cannot be set because the response has already started.
I can just "ignore" the exception but I would rather find some way to do this that is supported a bit more cleanly so I don't clutter the logs with these exceptions.
Is there some other way to change the response returned after a failed authentication?
CookieAuthenticationHandler: source.dot.net/#Microsoft.AspNetCore.Authentication.Cookies/…