5

As suggested by someone I post a question here (for the first time). I'm using web services from an Android application. I use https (I bought a SSL certificate).

I want to prevent unwanted accesses from others that know the urls of my web services.

I use a "secret key" that the app must provide to the web service method, but it's stored in a constant variable inside the code and I know this is not the best solution to ensure security.

What's the best way to achieve the definitive solution?

3 Answers 3

8

You need to define with high precision what it is that you exactly want.

Here, you want to allow accesses from you, personally. The business with the secret key means that access will be granted to whoever/whatever knows the secret key. Embedding the key in the application means that the application knows the key, not you; and, as you note, secrets embedded in a widely published application are not really secret.

So, you have to be clear with yourself. First of, define who should be granted access, and by "who" I mean "the humans". Every human in this set should "know" a secret value which is used by the server to authenticate the said human. If several humans use the same secret value, then the management of this secret becomes complex, because you cannot enforce forgetfulness: you cannot evict a user from the set of people who "know the secret" because he will remember it nonetheless.

Therefore, you should have user-specific secrets. Each human should have his own secret value, and send it to the server to be granted access (since we are talking about sending secrets over a network, I assume that all of this happens under the aegis of SSL). Then comes the question of how technically a user will store his secret value. If he stores it in his head, and make it available to the application he uses by typing it when required, then this secret is a password. But other models are possible, e.g. the secret could be a bunch of randomly generated bytes which the user stores in a file along his app.

You cannot prevent a user who has access to your server from "sharing" that access with anybody else; but with user-specific secrets you can at least:

  1. know on the server who is (allegedly) connecting, and thus modulate the set of operations which the server will allow or disallow;
  2. evict specific users, by removing the secret server-side, without impacting other users.

What you cannot do is to have an app that everybody in the world could download and install and use to access your server, while reliably preventing any access which did not use the exact app that you published. This would be the Holy Grail of piracy prevention, and it proves as elusive as its theological counterpart.

1
  • At this time, the application can only get software updates and send some usage data to the server. I'm scared about the possibility of a DOS attack or something else that can fill my server with unuseful requests. A solution: first, I need to register user with login/password and send it to the server to recognize the web service access. Than I could ignore requests from the same user that exceed a predetermined number (within an hour). What do you think? Feb 15, 2013 at 11:31
3

Restating your question.

You have a mobile application installed on an untrusted client's phone.

The mobile application has to fetch/send data to your web service; however you want to restrict access to your web service to just mobile applications not to any random user (who may be using a desktop device, post it to the web).

Your current solution is to encode a secret key inside the application, which is passed to the web service with each request -- only requests with the correct secret key get processed.

Perfect Solution is Infeasible

First, your goal isn't feasible against sophisticated attackers. They'll be able to decompile the byte-code of your android application, see what your application is doing, and then do whatever your application does offline.

However, you may be able to use the android application licensing functionality to do mostly what you want.

Basically you can generate a unique ID for your application when its first installed. Then your appication sends a query to google play's "Market License Server" that checks that the user purchased the application for this device, and sends back a license status (cryptographically signed with google's certificate). Your application passes back this signed license status to your server, which verifies it, and generates a secret key (tied to the unique id) for that device.

Now if some application is using your web service too frequently (e.g., you believe its offline), you can ban its unique secret key.

2
  • This is a very interesting approach to my problem. I need to do some experiment (and a lot of coding, I'm sure) Feb 13, 2013 at 16:28
  • 1
    @Seraphim'shost - I should add that I have not used the Android/Google Play Licensing service. But it seems along the path of what you need. You could even use the license server response as your secret key (e.g., if its a valid license + cryptographically signed with the right key + not banned for too frequent calls), give it a validity/grace period of a week. Agree much testing is needed.
    – dr jimbob
    Feb 13, 2013 at 16:58
2

Do the user's have to login to the application? If so, you can have the credentials be used to validate the requests. If not, then having some kind of shared secret between the application and the web service is pretty much the best you can do.

2
  • No, unfortunately users are not asked to login... Feb 13, 2013 at 16:25
  • but I'm thinking that this should be a must for my app... thanks Feb 15, 2013 at 11:27

You must log in to answer this question.

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