markmnl
markmnl

Reputation: 11426

How to add Authentication to ASP .NET Web API with exising users?

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

Answers (1)

olif
olif

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

Related Questions