How To Secure Web Service Without Login
Solution 1:
Actually in your particular case, since it is currently an iOS only app, there is a solution.
After the user downloads and runs the app for the first time, the app hits a
/access_token/create
API that comes up with a GUID and relays it back to the Application via Apple's Push Notifications.App stores this access_token, and uses it on all subsequent requests. Your actual API's can rate limit on the basis of the access_token.
Basically, you let Apple do all the hard work of ensuring that the initial request came from an actual iOS device.
Extending this to Desktop clients is possible, but somewhat ruins the UX. Just change step 1 to allow /access_token/create
to accept arbitrary requests, and if the request is not from a iOS device, then force the user to verify their email address/solve a captcha etc before issuing them an access_token.
Android devices (not really familiar with them) may have a similar Push Notification mechanism, in which case you can use that, or may not have a Push Notification mechanism, in which case you can subject your Android users to the inconvenience listed above.
Solution 2:
I've heard about this idea once, when talking about finding a global solution to SPAM problem: force your client to perform some time-taking computation.
To be precise: find some computational algorithm, that can compute some z
for a pair of x
and y
in a blink of an eye, but it takes some considerable amount of time to compute z
being given only x
. I can not provide actual algorithm but I am sure that there are plenty of them that would much this criteria.
Now the whole procedure should look as follows:
- Upon first client request generate some
session_id
and for thissession_id
a pair ofx
andy
. - Provide your client with
session_id
andx
. - Client can start calculations as soon as it receives data (in some background thread not related to user interactions).
- To request markers, client must provide
session_id
and calculatedz
. - You can quickly verify if client's
z
is all right, for you already havex
andy
that let you easily do it. - (option 1) For each
session_id
store how much/often it is being requested. The moment you suspect it is being abused - force regeneratingx
andy
. - (option 2) Force new
x
andy
upon each consecutive request for asession_id
.
Choosing between 6 and 7 is actually tweaking that depends on the complexity of algorithm vs. expected 'fair' use of marker database. If your estimates are good - the evil client should never obtain too much data or overload your server.
Hope it helps.
Solution 3:
There is nothing really you can do on the client side. You have to give the whole app (including any keys or any other protection mechanism) to your user. If a malicious user wants to play mischief with your web service he will have to do some reverse engineering to get to your web service. You can make this harder, but you cannot prevent this, no matter how hard you try.
I’d just implement some server-side rate limiting (per IP address) and not worry any more about this. This is a battle you cannot win. If someone really wants to hurt your server he could just DDOS it without knowing anything about your web service protocol.
Also, generating an unique key or certificate per user automatically on first connect does not help at all. After an attacker reverse-engineered your protocol he knows how to handle all this and doesn't have to play by your rules. Nothing would stop him from requesting a new key from your server every time he runs into the rate limiting.
The approach Kuba Wyrostek described could work - make the client perform some time-consuming computation you can quickly check before you allow the request to be processed. But this can't take too long or your users will complain about the reduced battery life. Also an attacker will probably use more powerful desktop hardware instead of another iPhone.
And a last point - do you really think this is necessary? You don’t want your users to have to register, so your data or service can’t be too important. So what would anyone have to gain from reverse-engineering your app and flooding your server with requests?