31

I want to make sure requests can't be forged and sent on to my server. In order to do this I need to generate an API key per user on my system. The purpose of the key will be to sign requests on the client side & validate them on the server.

The question is, what are API keys generally made up of? Are they just a cryptographically secure random number (similar to a password salt)? Or is there some logic behind them e.g. should they be made up of data specific to the user.

In my system each user already has a unique ID (GUID) which isn't publically exposed, could I use this as my "key" or should an API key differ from a users ID?

1 Answer 1

24

It depends on how much you want to separate roles.

Basic system: your "signature" is a MAC. The "API key" is a secret value with is shared between the server and the user. Normal MAC algorithms like HMAC can use arbitrary sequences of bits as key, so a key is easily generated by using /dev/urandom (Linux, *BSD, MacOS X), calling CryptGenRandom() (Win32) or using java.security.SecureRandom (Java).

Enhanced system: your signature is a true digital signature. This makes sense if you want to separate the key generator (who can produce keys which will be accepted by the server) from the server itself (who validates the incoming signatures). Keys for signature algorithms are mathematical objects with a lot of internal structure, and each algorithm implies a specific key generation algorithm. Use a library which already implements the needed bits (e.g. OpenSSL).


Either way, there is more to it than just key generation and signatures. For instance, you probably want to avoid replay attacks: an ill-intentioned third party spies on the network, and records a valid request signed by a regular user. Later on, the attacker sends the request again, complete with its signature, so as to replicate the effect. To avoid replay attacks, you must add some sort of external protocols, and these things are hard to do (it is not hard to define a protocol; it is very hard to define a secure protocol). Therefore, the smart thing to do is reusing an existing, well-vetted protocol, which, in practice, means SSL/TLS.

With SSL, the "basic system" is reduced to sending the API key in a header at the beginning of the conversation (that's exactly what happens with password authentication on HTTPS Web sites). The "enhanced system" is then "SSL with a client certificate".

8
  • The API is running over SSL and I actually use the Basic authentication approach for the initial request. However, I need to store an authentication token on the client side to be used for subsequent requests. I am aware using SSL would mitigate MitM/Replay attacks as the channel is encrypted, however, this won't prevent someone from forging a request....right?
    – James
    Sep 5, 2012 at 22:16
  • Am I right in saying if I was to implement client certs then I wouldn't even need an "auth" token at all?
    – James
    Sep 6, 2012 at 10:54
  • @James: yes. With SSL with client certs, no need to do anything else with regards to authentication. With SSL without client certs, client must send a "password" (a secret string also known by the server) within the SSL tunnel, in the beginning of the conversation (e.g. as a HTTP header if your SSL happens to be HTTPS). Sep 6, 2012 at 12:33
  • In my scenario I have SSL, but no client certs. So I need to send this "API" (or "password") key to the client. I keep a copy of this stored at the server and for every request made by a client they sign it using the "API" key and the server can use that key to lookup the client & then validate the request. The only security risk I see here is I need to store the API key on the client somewhere (mobile app) which could potentially be extracted and re-used?
    – James
    Sep 6, 2012 at 12:51
  • 2
    what do you make the following approach?
    – James
    Sep 8, 2012 at 12:19

You must log in to answer this question.

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