1

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?

Community
  • 1
  • 1
Gigi
  • 28,163
  • 29
  • 106
  • 188
  • Basic ist cheap and extremely fast, database lookup is extremely fast, if you do it right. – Michael-O Apr 03 '14 at 15:45
  • Yeah, but it's a big waste to do it 100,000 times when you can do it once for every user session. – Gigi Apr 03 '14 at 16:45

1 Answers1

3

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.

brianpeiris
  • 10,735
  • 1
  • 31
  • 44
rdegges
  • 32,786
  • 20
  • 85
  • 109
  • 2
    I find the part about the initial request hard to believe... if that were the case, I think no HTTPS traffic would be safe. Isn't the SSL handshake meant to safeguard against those kinds of attachs? Also, can you elaborate on the API key (what is it and how is it used)? – Gigi Apr 03 '14 at 16:49
  • Initial requests can most definitely be man-in-the-middle'd -- this is the largest reason why SSL by itself is NOT safe -- this is also one of the things that HSTS headers are supposed to help with (but this only applies to websites, not APIs). Re API keys: imagine the API key being a username, and the API secret being a password. You can use these variables to encrypt your API request before it is transmitted to the server, making it possible to send secured data across the wire. – rdegges Apr 04 '14 at 16:57
  • 2
    Initial requests are secured with the certificate and validation against the CA public cert. Unless the client has been compromised and had it's CA public key store manipulated, then even the initial request is secure. This is not what HTST is for. HTST is to prevent downgrade attacks where an attacker mim's and redirects to HTTP. When you have a client calling an API, generally redirects are meaningless and you explicitly use HTTPS for every request. – AaronLS Dec 13 '18 at 05:27