Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a Secure API without using OAuth?

My Requirement

I am making a website which will have mobile version as well. So, I am making it API centric. Now I want to make my API secure without the complexities of OAuth because the security I need is quite simple. I don't want anyone with access to the api links to be able to access my data.

So, I came across this article http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/ which is quite amazing and cleared most of my doubts.

Right now, I am trying to recreate whatever is there in the article. I am using Laravel 5 framework for PHP for development.

I want to make sure that the API is being used by the mobile app and the web version only and no one else. I have seen api links like

example.com/fetchallinformation&publicKey=<something>&Hashkey?<some_hash_key>

Now, I understand that this key is generated by using hash_hmac() function in php.

My Approach

  • I have a table where I am storing the publicKey and privateKey for my api users
  • That HashKey in the URL is generated by hashing the privateKey and the publicKey in the client side and then sent to the server. So, i send the generated Hash along with the publicKey to the server.
  • In the server side, I take the publicKey and the Hash. I retrieve the private key from the table corresponding to the publicKey and has them and check if the resulting hash is same as the hash send by the client
  • If it is same, then I give permission to them, else, I don't.

My Confusion

  • I am not sure if this is the right way to do this.

  • Can we get the data that has been used to generate the hash using hash_hmac() by decrypting the hash?

like image 255
Parthapratim Neog Avatar asked Oct 19 '22 06:10

Parthapratim Neog


1 Answers

That HashKey in the URL is generated by hashing the privateKey and the publicKey in the client side and then sent to the server. So, i send the generated Hash along with the publicKey to the server.

Close, but not quite. As you just described it, a user with a given public key would send the same hmac with every request. That's no better than "username and password."

Side note: if you aren't using https, you're already insecure and whatever else you do to secure the site is of relatively little value.

The point of generating an hmac signature is that it not only authenticates the user as being in possession of the secret key, it also authenticates the specific request as being made by that user and being made during a specific window of time. Two different requests back to back should have a different hmac. One request today and an identical request tomorrow should also have a different hmac. Otherwise, you're in for replay attacks. This means information about the current time or expiration time of the signature, and information about the request itself, must be included in the information that's passed through the hmac algorithm or you're not accomplishing much.

For any given request, by a specific user, at a specific time, there can only be one possible valid signature. HMAC is not reversible, so you can't take the signature apart at the server end and figure out the attributes of the request.

Of course, of you're thinking about embedding that secret key in your app, remember that such tactics can be relatively trivial to reverse-engineer.

Is it a viable authentication mechanism? Of course. As the article points out, Amazon Web Services uses hmac signatures on their APIs, and they have a massive potential attack surface... but does that mean you will implement it in a meaningfully secure fashion? Not necessarily. There is always someone more clever, devious, and determined than you can imagine.

Even Amazon apparently realizes that their Signature Version 2 is not as strong as it could be, so they now have Signature Version 4, which has a much more complex algorithm, including several rounds of hashing and generation of an intermediate "Signing Key" that is derived from your secret, the current date, the specific AWS service, AWS region, and other attributes. Regions where Amazon S3 was first deployed in 2014 or later don't have support for the original Sig V2 at all -- and it seems like it can only be security-consciousness that drove that decision, since the old algorithm is computationally less expensive, by far.

Use caution in rolling your own security mechanisms.

If you are primarily trying to avoid the learning curve with OAuth, which I agree is quite annoying at first, you could be on a fool's errand.

like image 102
Michael - sqlbot Avatar answered Nov 01 '22 12:11

Michael - sqlbot