Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

securing a REST API accessible from Android

We're building a game for Android, which needs access to web services - so we wrote a RESTful API in PHP that runs on our own server. What the API offers is: creating user, logging in, downloading games, retrieving game list, submitting score... etc. Now I'm thinking, if some experienced user gets the URL format of the API - s/he will be able to trash the system in many ways:

  • Create a script & run it to create automatic users - I think I can prevent it by CAPTCHA or someting like that. But again, captcha will annoy game players.
  • Malicious user logs in using his browser, downloads game & then submits score as he wish - all via calling the API by simply typing it from his browser. I assume malicious user somehow knows API urls to call - by sniffing when the application was making HTTP requests.
  • I need to ensure that requests are made only from Android device that installed the game. (The game will be free)

Now How do I prevent such abuses?

like image 254
Shafiul Avatar asked Oct 03 '11 04:10

Shafiul


People also ask

How do I secure access to REST API?

How do you secure a REST API? The first step in securing an API is to ensure that you only accept queries sent over a secure channel, like TLS (formerly known as SSL). Communicating with a TLS certificate protects all access credentials and API data in transit using end-to-end encryption.

Which is the most secure method to transmit an API?

HMAC Authentication is common for securing public APIs whereas Digital Signature is suitable for server-to-server two way communication. OAuth on the other hand is useful when you need to restrict parts of your API to authenticated users only.


2 Answers

I think you will never be able to hide the urls being called by the application (if I am running a root-ed android phone, I should be able to spy on all network traffic)

But your real problem is that you need to authenticate your api in some way.

One way would be to implement OAUTH, but maybe this'd be overkill.

If you want a simple mechanism, how about this;

  1. create a secret key
  2. build the api request (eg. https://my.example.com/users/23?fields=name,email)
  3. hash this request path + plus your secret key (eg. md5(url+secret_key) == "a3c2fe167")
  4. add this hash to your request (now it is https://.....?fields=name,email&hash=a3c2fe167)
  5. on the api end, do the same conversion (remove the hash param)
  6. check the md5 of the url and the secret key

As long as the secret remains secret, no one can forge your requests.

Example (in pseudo-code):

Android side:

SECRET_KEY = "abc123"  def call_api_with_secret(url, params)   # create the hash to sign the request   hash = MD5.hash(SECRET_KEY, url, params)    # call the api with the added hash   call_api(url+"&hash=#{hash}", params) end 

Server side:

SECRET_KEY = "abc123"  def receive_from_api(url, params)   # retrieve the hash   url_without_hash, received_hash = retrieve_and_remove_hash(url)    # check the hash   expected_hash = MD5.hash(SECRET_KEY, url_without_hash, params)    if (expected_hash != received_hash)     raise our exception!   end    # now do the usual stuff end 
like image 128
Matthew Rudy Avatar answered Oct 07 '22 19:10

Matthew Rudy


Solutions that others have presented here are called security through obscurity. Basically they are trying to obscure the protocol and hide the implementation. This might work until someone capable enough disassembles the app and reverse-engineers the protocol. Hackers are very capable at that.

The question is if your app is worth cracking? Schemes like iTunes, DVD or Sony PS3 network were obviously worth the effort. The obscurity approach might work if no one capable of cracking cares. Just don't fool yourself that it is not doeable.

Since you can not trust the device or your app, you must trust the user. In order to trust the user, you need user identification and authorization system. Basically a login to your app. Instead rolling you own indentification system (login with confirmation emails, etc..), use a 3rd party system: OpenID (google accounts) or OAuth (facebook, twitter). In case of facebook use the server-side auth scheme.

What I'd do:

  1. Allow users to freely play the game until they want to "save" the results on server.
  2. Before saving their results have them login via above mentioned method.
  3. Use HTTPS to send the data to your server. Buy a ssl certificate from trusted CA, so you don't have to deal with self-signed certs.
like image 29
Peter Knego Avatar answered Oct 07 '22 18:10

Peter Knego