5

I'm designing an API intended for use by a very limited number of trusted clients, likely a server cluster. The API can be accessed only through HTTPS. To authenticate the clients, I'm considering 3 methods:

  • TLS client certificate. The certificate might be issued internally as both server and client are operated by the same organization.
  • HMAC-SHA1 over some data items: requested URL, date time,... for each request. The MAC will be put in HTTP Header. In other words, a simpler version of Amazon S3's REST authentication.
  • HTTP Basic authentication with pre-shared username & password.

To my understanding:

  • TLS certificate is the "most secured" of the three, while HTTP basic authentication is the "least secured". "Most secured" is in the sense that the method provides protection against all attacks also protected by others, and some more.
  • HMAC-SHA1 is vulnerable to replay attack, however since the communication will be secured by TLS anyway, there should be no problem.
  • HTTP basic authentication puts shared secret on the wire all the time (though still protected with TLS), so I have some (possibly unfounded) worries about it.

Are my points correct? Is there any other security issues I should be aware of?

2
  • 1
    Please remove your question on SO 1) to prevent migration still or 2) to prevent cross-site duplicates. And then you can remove your first paragraph.
    – user13695
    Nov 4, 2016 at 11:02
  • 1
    Client certs would be better IMO as they can not only protect against unauthorized usage of the API but can prevent mere access - the web server wouldn't even complete the TLS handshake without a valid cert, shielding your API from all the bots and the background noise of the internet. Nov 8, 2016 at 11:57

4 Answers 4

2

I think you summed it up well.

A few additional points beyond the technical security of these solutions:

  • TLS certificates require management, they expire, etc. You should consider whether you have the resources (can automate to some extent) certificate management. A pretty bad scenario is when IT operations just gets fed up with all the issues and disables cert validation because that way it just works. ;)

  • An HMAC-SHA1 signature implementation is also reasonably good and you can limit the time window of a replay (and as you said, in TLS it's ok). However, the implementation is more complex than the other too. If it's a larger team that will maintain the code and especially if you have to change the implementation sometimes, there is a good chance that a flaw will be introduced. The other two are much simpler in terms of source code that needs to be written.

  • HTTP Basic is very simple and may be ok with TLS, but as you said, that I would say is the least secure of the three. Many people still think it's good enough for many purposes though, it depends on what you want to protect against. TLS is considered secure against MitM attackers. I think the biggest advantage is simplicity, there is not a lot to go astray.

3

It's a no-brainer to me: TLS client-side certificates. They are the fastest, most secure, least homebrew and you say you are already using TLS libraries. They are also quite simpler than HMAC option in terms of implementation.

Don't do public key infrastructure (PKI) stuff: simply let client-side generate a self-signed cert valid for 100 years and marked as not being a CA. Trust that cert on the server. There is no reason to make PKI, YAGNI... It doesn't solve your problem, it introduces CRL or OCSP issues, SHA1 class of issues and many other side-effects. Think about a self-signed certificate as simply an RSA public key - it is one in fact.

Ensure both client and server do cache TLS sessions. This will give you blazing fast TLS connections. (You benefit this when having only server-side certs. You benefit twice when you add client-side certs.)

There is very little programming with this, this just needs implementing simple textual configuration options that pass some text (like a location of a truststore file to use). Admin staff does the rest. They are also able to test stuff themselves with openssl s_client etc.

Any future vulnerabilities can be handled administratively (for example via openssl ugprade or JDK upgrade).

The HMAC solution is a black box for admins. Any problems need to be solved by programmers.

With HTTP basic auth, you're doing a strange job. You still need to implement TLS and set up X509 certificates (for example client will most likely trust something other than the default public CAs) and you still need to manage it and upgrade it. But you do half job and for the other half you use a completely different mechanism. It does look valid, but it has a little bit of bad smell.

1
  • I totally forgot about having to implement TLS since it would use pre-existing system. It's true that TLS client certificate would be more coherent from ground up.
    – Nevill
    Nov 30, 2016 at 11:04
1

I believe your assumptions are correct as long as you have a strict policy that the client terminates the connection in case the trust chain of the server certificate cannot be verified or in case any other TLS security concern pops up. If you trust the TLS then you are safe against replay etc.

You could, however, spend a couple of thoughts on the question how quickly you can react if your authentication information is compromised. Here, switching to a shared key might be significantly easier or harder as compared to putting a client certificate on a CRL, this completely depends on your environment. Whereas TLS provides good protection for data transmission over the wire the options you describe might provide different level of comfortability/reliability/security when it comes to revoke the authentication information.

1
  • Good point regarding certificate revocation. At first I thought it should be as easy as with secret key, but it turned out it can be a lot more complicated in our system.
    – Nevill
    Nov 23, 2016 at 10:38
0

The client certificate is needed only for authentication. But you can just use a password or a cookie as usual when you login to any website. The TLS without a client cert is absolutely the same in terms of safety.

HMAC is just simply not needed if you are using TLS. This is just a cargo cult. So the only one question is about base auth. It’s also totally fine because nobody ever sees the password.

The only one important thing here: generate the password yourself and make it long enough. This is an API secret and users don’t have to memorize it. But don’t allow users to set the secret themselves because they may choose a short secret.

Show the secret only once after generation so when user gets hacked nobody can’t see the secret. In case of compromise user can just easily delete the old secret and generate a new one. If you’ll use OAuth then you may have to use bearer tokens which are just like a basic auth but without a username.

The bearer token itself can be “opaque” (i.e. random) or be a JWT which is a json with username and signature. Unless you clearly need a JWT for a stateless horizontal scalling try to avoid them and use opaque tokens. JWT tokens are big and slows down throughput. The better thing that you can do here is just use a ready Auth server like Keycloak. We don’t write own database for each project then why do we writing the auth? Keycloak may give you a dashboard and UI to generate tokens and your app can ask if the token is valid. This can be also done on API gateway layer.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .