REST authentication and HMAC/private key (when do I set it?)

jfrobishow picture jfrobishow · Jun 30, 2013 · Viewed 7.7k times · Source

I've been toying around with a simple application idea the last couple of days as I'm trying to teach myself the basic of REST authentication.

So far I've gathered that the best way to do this is with an implementation of HMAC like the one used by Amazon.

My biggest concern is with exactly how am I suppose to authenticate the user and give them their private key so they can begin signing the HMAC? I keep reading that the private key used for signing the HMAC is not supposed to be sent over the wire ever, but then how do they ever get it in the first place?

My idea was something like this, but I am not sure if this is valid.

Database table for users:

users (simplified, this would probably be a private key per client app?)
  id (their public key?)
  username
  password?
  privatekey

Assuming a HTML/JS client the user would be presented with a traditional login page that POST to the API with something like this:

https://example.com/myapp/api/v1/authenticate.json
POST: username / password

That would return either

404:User not found
200:{ "id" : <id>, "privatekey": <privatekey> }

The client would then store that key somewhere (would local storage/cookie be a safe place?) and use it to sign further requests that would look like this

GET https://example.com/myapp/api/v1/something/?key1=value1&publickey={theirID}&hmac={hmac signature of the request using their private key}

The server would then check the public key, retrieve the associated private key and rebuild the HMAC signature, if they match we have an authenticated request process it.

Am I getting this right? I'm not sure I understand the role of a private key if I still need a password like in my example so something is telling me that I might be wrong.

Answer

Sergey Zyuzin picture Sergey Zyuzin · Jul 18, 2013

I think you need to provide more details about your application and how it will be used. There are many ways you can do REST authentication. Some of them are standard, some not. These are just some examples:

  1. Basic authentication over SSL
  2. Digest authentication
  3. Various kinds of token authentication (OAuth 2, SPNEGO, various STS)
  4. HMAC
  5. Client SSL Certificates
  6. Signed/encrypted cookies.

In case of Amazon S3, they give you "AWS secret access key" when you register. Later your application code needs to know secret key to be able to compute signatures (or it needs to know signed request/url) So ultimately "secret access key" is transmitted over the wire at least once initially during registration.

If you use public key cryptography (like client SSL certificates) - you can avoid transmitting private key altogether

  1. you generate public/private key on client
  2. Submit public key to the server (or certificate signed by trusted authority)
  3. Sign requests(or nonces) with private key and server validates the signature using public key.

If your goal is to just authenticate AJAX requests made to your site after user has authenticated on login page - you can simply use server signed cookies.