Gigi
Gigi

Reputation: 29461

Web API: Basic Authentication or HMAC over SSL?

I would like to secure a .NET Web API service. I will be using SSL, but I also need to restrict the Web API calls that each user can call depending on the user's permissions.

From what I've read, REST/HTTP is supposed to be stateless, so technically you shouldn't be able to maintain any session state, but there are some ways around that.

One is to use basic authentication. The credentials are sent with every request. While this may be okay security-wise because they're being transmitted over SSL anyway, it really isn't practical given that it would require a lot of overhead to re-authenticate against the database every time. (A possibility might be to cache them in memory, but I doubt that's the best way.)

Another could be to use an HMAC (example implementation) to control access to API calls. There is a comment in this article that says:

Just to be clear to people that are implementing this on their HTTPS services: YOU DON'T NEED TO IMPLEMENT HMAC ON SSL!!! It's a waste of time and waste of complexity for absolutely no reason. DON'T DO IT. Use Basic Auth and be done with it.

I don't agree with this for the reasons mentioned above (it is more practical to authenticate once and control using HMAC than authenticate every time).

Is it a good and effective practice to use an HMAC to provide security to Web API calls when working over SSL, or are there any points that I am missing?

Upvotes: 1

Views: 3828

Answers (1)

rdegges
rdegges

Reputation: 33844

The answer depends on how much you care about security.

What is this API being used for? If security is a big concern, Basic Authentication is NOT a sufficiently good choice -- even if you're using SSL.

Even if you're using SSL, an attacker who can control or get access to your initial request can pretend to be the desired HTTPS web service, and intercept your traffic easily (then get a hold of your API credentials).

A much better solution is to do several things:

  • Use an API key and secret.
  • Generate a unique ID with each request.
  • Generate a timestamp with each request.
  • Encrypt the body of your request against your API key secret.
  • Put the encrypted output into the HTTP_AUTHORIZATION header in the form: API_KEY_ID:<encrypted_output>
  • On the server side, decrypt the payload.
  • Compare the timestamp -- if the request was sent more than a second before -- drop it (this prevents timing attacks).
  • Compare the unique id -- if this request was already executed -- drop it (this prevents replay attacks).

The above strategies make it impossible for attackers to gain access to your API credentials, even if they are able to successfully man-in-the-middle your API calls.

Upvotes: 3

Related Questions