Reputation: 11426
How can I best add authentication to my API? I would like to take advantage of existing infrastructure such as the Authorize
attribute.
(This question: User Authentication in ASP.NET Web API does not answer my question because the only two ways it proposes for authentication are Forms Authentication and Windows Integrated Authentication - neither of which I can use).
Upvotes: 0
Views: 645
Reputation: 3299
I like to have custom authentication mechanisms in a message handler. Since I don't know the requirements regarding level of security it is impossible to say what kind of mechanism you should use. If you are using SSL then basic authentication could be enough.
A simple handler for basic authentication with custom user store can look like this:
public class BasicAuthMessageHandler : DelegatingHandler
{
private const string ResponseHeader = "WWW-Authenticate";
private const string ResponseHeaderValue = "Basic";
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
AuthenticationHeaderValue authValue = request.Headers.Authorization;
if (authValue != null && !String.IsNullOrWhiteSpace(authValue.Parameter))
{
Credentials parsedCredentials = ParseAuthorizationHeader(authValue.Parameter);
if (parsedCredentials != null)
{
//Here check the provided credentials against your custom user store
if(parsedCredentials.Username == "Username" && parsedCredentials.Password == "Pass")
{
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(parsedCredentials.Username), null);
}
}
}
return base.SendAsync(request, cancellationToken)
.ContinueWith(task =>
{
var response = task.Result;
if (response.StatusCode == HttpStatusCode.Unauthorized
&& !response.Headers.Contains(ResponseHeader))
{
response.Headers.Add(ResponseHeader, ResponseHeaderValue);
}
return response;
});
}
private Credentials ParseAuthorizationHeader(string authHeader)
{
string[] credentials = Encoding.ASCII.GetString(Convert
.FromBase64String(authHeader))
.Split(
new[] { ':' });
return new Credentials()
{
Username = credentials[0],
Password = credentials[1],
};
}
}
public class Credentials
{
public string Username {get;set;}
public string Password {get;set;}
}
You then apply the message handler in your global app configuration
protected void Application_Start()
{
GlobalConfiguration.Configuration.MessageHandlers
.Add(new BasicAuthMessageHandler());
}
Note that the provided sample is just an example.
Upvotes: 1