11

I have a pre-existing iOS & Android app, that I'm making an update for that includes a RESTful services API and Facebook login for user authentication. The general flow of the app is:

  1. Users "logs in" to my app, via Facebook's SDKs, which return an access token to my app.
  2. App calls a RESTful service, including the Facebook access token as a parameter (using HTTPS and SSL)
  3. Service that is called, sends the received access token (and app secret stored only on my servers) to Facebook to verify who the user is, and performs actions based on that. Facebook is set to require app secret from server-side calls.

My app has gained popularity and has several clones already, and I want to prevent these clones from being able to use my RESTful API (as I am sure that they will try to do when I release the update). Let's assume that the clones are smart, are using the same Facebook access tokens that my app does (if this is possible), and are following a similar pattern & frequency of calling the API that my app does.

Is there anyway to ensure, or nearly ensure, that calls to my services are coming only from my app, and not the clones?

Thanks in advance!

1

3 Answers 3

7

You can do this by including a signature in the request, and verifying it.

App Side:

  1. do something like: signature = md5( md5(url + data) + MY_RANDOM_KEY)

  2. append signature to the data, or url, etc.

  3. send call to REST api (as usual)

Server Side:

  1. extract the signature from the body/url (and remove it from there).

  2. calculate what you think it should be: signature_should_be = md5( md5(url + data) + MY_RANDOM_KEY) [keep in mind you've removed signature from url/data so that you get url/data in its original pre-hash state]

  3. verify that signature and signature_should_be are equal

Doing this, along with SSL, should make your API secure enough.

Sign up to request clarification or add additional context in comments.

15 Comments

No sorry, haven't had my coffee, makes no difference.
My concern about using this approach is that the clones can reverse engineer my app and see what I'd be doing here. If the clones also used signature = md5( md5(url + data) + MY_RANDOM_KEY), as seen in my app, then how would this make it secure? Also, I thought that MD5 has been outdated for a while now.
In a sense, you are correct. But in the same sense, they could also do the same with whatever else you do. Use whatever hashing you want. If MY_RANDOM_KEY is sufficiently long, and you're also taking a hash of hash (nested md5 calls), you'll be fine. If your MY_RANDOM_KEY is compromised, then yes you have an issue. But that's auth in general. Unless you're carrying banking data or something like that, this will be just fine.
There's also methods of ensuring that it's different one second from the next. You could append the TIME_SINCE_EPOCH to MY_RANDOM_TOKEN and then server side make the all the valid signature_should_be for the past and next 5 seconds (to account for various latency, etc). But for what you're probably trying to secure, that's overkill.
I see what you're saying @TommyCrush, but where would I store MY_RANDOM_TOKEN? If I'm storing it client-side, wouldn't it be easy to spot if they just decompile my code?
|
4

You could do as Tommy Crush suggests and add a secret inside you application. But if you are up against clever opponents, this probably won't help. The attackers can either decompile your application or try to simply reverse engineer your signature algorithm.

It is important to remember that anything stored within your application should be thought of as already compromised, as an attacker can decompile your app and scour through your code as much as he/she pleases and extract anything he/she wants from it. You cannot rely on anything in your application to be safe inside your app, since an attacker can extract it from your app into their app.

It is important to note that you are using trying to use OAuth for authentication, which is not intended for. It is simply meant for authorization, which is not the same as authentication. Authorization simply gives you access to a resource, but does not tell you who accessed it, which is the problem you are facing. To authenticate your users as your real users (or as close as you can get), you would need to add a login service for your service - something like rolling your own OAuth-server, or similar. Then you can decide who can access the resource, which in this case is your RESTful API :) If this is more work than it is worth, then Tommy's scheme is a good alternative :)

4 Comments

The problem is though, that I don't want to have a separate login service aside from Facebook...I think that would annoy users to have to log in on my app as well as link their Facebook account.
Another question: how would an OAuth-server guarantee that the API usage is coming from my app and not any other app dev that has reverse engineered my code?
Unfortunately, as you suggest, an attacker could tell their users to register to your site to overcome that obstacle. And once registered they can access your API as a valid registered user. You can try to circumvent this by strengthening your site's registration. Make sure that you only allow registrants from your domain, not other domains, make CRSF difficult with nonces, etc. Then maybe the attackers users will see the scammer for what they are and join you instead. Sorry if that was too incomprehensible - it is 4 AM here :P
The short answer here is that there is no such thing as a 100% safe API here. Anytime source code is compromised, then so will the data that handles it. There's no way around that. My proposed solution is pretty much the standard, and will prevent the overwhelming majority of hackers from moving further.
0

The de facto solution for authentication on restful APIs like Twitter and Facebook use is the OAuth mechanism. You can find more details here: http://en.wikipedia.org/wiki/OAuth.

OAuth is supported from the majority of the languages with external libraries. On Android for example there is the https://github.com/wuman/android-oauth-client library.

1 Comment

This is inherently different than what he/she is trying to achieve.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.