I\'m implementing a RESTful web service using ASP.Net Web Api. I have concluded to use Basic authentication + SSL to do the authentication part. What is the best/correct way
Have a look here for a good basic authentication implementation
http://leastprivilege.com/2013/04/22/web-api-security-basic-authentication-with-thinktecture-identitymodel-authenticationhandler/
there is more to read about it at: https://github.com/thinktecture/Thinktecture.IdentityModel.45/wiki
Jamie Kurtze provides a good explanation of using Basic Authentication here ASP.NET Web API REST Security Basics
From my understanding, if you want your requests to be stateless then each request will require the Authentication field to be set
Jamie Kurtze wraps the necessary code in a class derived from DelegateHandler, while Rick Strahl checks if the call is valid using a Filter. You can read more at his blog post on this topic at A WebAPI Basic Authentication Authorization Filter
Use basic authentication for the initial (sign in) request by adding a [BasicHttpAuthorize]
attribute to the appropriate controllers/methods. Specify the Users and Roles with the attribute if desired. Define BasicHttpAuthorizeAttribute
as a specialized AuthorizeAttribute like this:
public class BasicHttpAuthorizeAttribute : AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext actionContext)
{
if (Thread.CurrentPrincipal.Identity.Name.Length == 0) { // If an identity has not already been established by other means:
AuthenticationHeaderValue auth = actionContext.Request.Headers.Authorization;
if (string.Compare(auth.Scheme, "Basic", StringComparison.OrdinalIgnoreCase) == 0) {
string credentials = UTF8Encoding.UTF8.GetString(Convert.FromBase64String(auth.Parameter));
int separatorIndex = credentials.IndexOf(':');
if (separatorIndex >= 0) {
string userName = credentials.Substring(0, separatorIndex);
string password = credentials.Substring(separatorIndex + 1);
if (Membership.ValidateUser(userName, password))
Thread.CurrentPrincipal = actionContext.ControllerContext.RequestContext.Principal = new GenericPrincipal(new GenericIdentity(userName, "Basic"), System.Web.Security.Roles.Provider.GetRolesForUser(userName));
}
}
}
return base.IsAuthorized(actionContext);
}
}
Have the initial response include an API key for the user. Use the API key for subsequent calls. That way, the client's authentication remains valid even if the user changes username or password. However, when changing password, give the user an option to "disconnect clients", which you implement by deleting the API key on the server.