I followed http://bitoftech.net/2014/12/15/secure-asp-net-web-api-using-api-key-authentication-hmac-authentication/ to do a custom authentication filter.
Everything is working correctly but I cannot get the server to say anything upon a 401. It correctly gives the www-authenicate
header and status code 401 but no content/body.
I tried using AuthenticationFailureResult
the from http://www.asp.net/web-api/overview/security/authentication-filters but did not help. I converted my AuthenticateAsync
to async
and ignored the await
warning.
This is my current work around, the code in comments is what I -wish- I could do, that is mostly have it use whatever formatter
//request.CreateResponse(HttpStatusCode.Unauthorized, new { Error = true, Message = "Token is invalid" });
HttpContext.Current.Response.ContentType = "application/json";
HttpContext.Current.Response.Write("{ \"Error\" = true, \"Message\" = \"Token is invalid\" }");
context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], request);
In order to create a Custom Authentication filter in MVC, you need to create a class by implementing the IAuthenticationFilter Interface. This IAuthenticationFilter interface has 2 methods. Following is the class definition of the IAuthenticationFilter interface.
Web API provides a built-in authorization filter, AuthorizeAttribute. This filter checks whether the user is authenticated. If not, it returns HTTP status code 401 (Unauthorized), without invoking the action. You can apply the filter globally, at the controller level, or at the level of individual actions.
To access the web API method, we have to pass the user credentials in the request header. If we do not pass the user credentials in the request header, then the server returns 401 (unauthorized) status code indicating the server supports Basic Authentication.
The authentication and authorization mechanism in such a site is simple. After the user logs into the website, a single database holding user information verifies their identity. A session is created on the server, and all subsequent requests use the session to identify the user without another login required.
There two options to do this: quick but brute and longer but more elegant
A. Modify HttpResponse directly:
HttpContext.Current.Response.StatusCode = 401;
HttpContext.Current.Response.Write("some content");
B. Implement IHttpActionResult
and set a Content
property of a HttpResponseMessage
in that class:
public class AuthenticationFailureResult : IHttpActionResult
{
public AuthenticationFailureResult(object jsonContent, HttpRequestMessage request)
{
JsonContent = jsonContent;
Request = request;
}
public HttpRequestMessage Request { get; private set; }
public Object JsonContent { get; private set; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(Execute());
}
private HttpResponseMessage Execute()
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
response.RequestMessage = Request;
response.Content = new ObjectContent(JsonContent.GetType(), JsonContent, new JsonMediaTypeFormatter());
return response;
}
}
Then you'll be able to use it like this:
context.ErrorResult = new AuthenticationFailureResult(new { Error = true, Message = "Token is invalid" }, request);
Note: If you want to use anonymous types for JsonContent
make sure that AuthenticationFailureResult
implemented in the same library.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With