0
  • I have users stored in our own custom database.
  • I have developed a ASP .NET Web 2 API
  • I do NOT have an existing Web site and clients are not using a browser (so cannot use Forms Authentication)
  • I need to use the existing users so cannot use ASP .NET's Identity which uses it's own tables?

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).

Community
  • 1
  • 1
markmnl
  • 11,116
  • 8
  • 73
  • 109
  • You can set Authorize on web-api based on any condition, but how do u intend to preserve the authentication if u have no browser, a cookie or ouath token needs to be sent so the api know's the request is legit and authrized ? – fuzzybear Jul 24 '14 at 01:00
  • I have no browser but it is HTTP so I can include tokens in the headers, even if I were not using HTTP I could include it my requests. – markmnl Jul 24 '14 at 01:04
  • easier to include the cookie it's send in the header, unless u know how to configure Ouath ? but with no browser hmmm ouath might be your only option – fuzzybear Jul 24 '14 at 01:10
  • Use // do some condition check then set FormsAuthentication.SetAuthCookie(userAccount, true); // set to false if you do no want to create a persistent cookie, if you include the cookie in your header it should work – fuzzybear Jul 24 '14 at 01:15

1 Answers1

1

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.

olif
  • 3,221
  • 2
  • 25
  • 23