1

I'm writing a mobile app that aggregates weather data and generates a push notification when certain criteria are met. The user has the option to change some of the variables (e.g. if the current temperature exceeds X degrees) which is stored both on the device, and on my server.

When my app opens, it requests the GCM (or APN) token and the user-defined variables and sends them to my server via POST. The endpoint would look something like this (if it were a GET):

https://api.example.com/registerPush.php?key=gcm_key_here&maxtemp=80&type=android

(obviously type would be apple if it were an iOS device)

On the server end, registerPush.php takes the variables and stores them (via prepared statements) in a MySQL database. The requester is allowed 1 registration per 10 seconds (determined via PHP sessions) and if they exceed that, they get locked out for 2 minutes, to avoid one user trying to spam the database with bogus entries.

Every hour, a cron job runs and loops through all the items. If the temperature exceeds maxtemp, the token is added to an array, and bulk-sent to those users via the correct push method (e.g. GCM or APN).

I'd like to keep this system "anonymous" (that is, not require a user to sign up), because creating an account simply to store push notifications is a bit overkill for the simplistic nature of my app, and things such as "Login with Facebook" are the same, because why should a user sign in with Facebook, just to get push notifications?

So my question is, short of throttling registration attempts via $_SESSIONs, and perhaps storing the last time the token was sent to the server (and clearing out old tokens after X many units of time), what can I do to make this system more secure, short of asking people to create an account (for a simple weather app)?

DrFrankly
  • 11
  • 1
  • if it's only run 24 times a day, RSS seems like a fading yet viable push system – dandavis Jul 04 '16 at 00:56
  • @dandavis But if the app is closed, then no messages get through because my app isn't pulling in the feed to generate a notification. Push notifications work at the system-level so my message will be delivered regardless – DrFrankly Jul 04 '16 at 06:51
  • no, i mean just offer the feed and let the user use their favorite app to consume... – dandavis Jul 05 '16 at 04:02

1 Answers1

1

I would suggest using String m_androidId = Secure.getString(getContentResolver(), Secure.ANDROID_ID);

This will give you a unique ID, that require no permissions, that does only change during factory reset, and can be used to track so nobody spams the database. I would also suggest hashing with a app-specific key.

However, you still need to have any throttling to prevent someone from creating malicious entries. A good idea could be requiring the solving of a captcha to submit a "new" ANDROID_ID string that does not exist in database. This can be solved with a WebView and using Google Recaptcha, upon first launch of the app, combined with IP-based throttling.

Do remember that many cellular operator NAT's lots of customers behind one IP, so guard the logs carefully and if you see the app being popular and be prepared to increase the throttle limits incase your app start being more popular.

This could be implemented automatically by having a AI, that will compare the median request rate for all IPs to a specific rate, and only block if the rate is considered higher than this. Median request rate is in other words, the request rate that is the average of the request rate of all IPs, but with the "low-balls" and "high-balls" removed.

sebastian nielsen
  • 8,779
  • 1
  • 19
  • 33
  • App-specific key sounds good, though I'd have to to store that within the app itself, so if (when) it's decompiled, it'd be the same as if I had never added it. CAPTCHA sounds interesting. It's still a UX breaking design (many Pebble watch apps I've installed don't require this, so I wonder what they're doing), but I'll look in to it. I'll also research the median request rate and see if that'll fit in. Thanks :) – DrFrankly Jul 03 '16 at 22:21