FWIW, here is the most secure method I can think of without seriously affecting performance - essentially the RESTful(ish) way, as to ramp it up any further would require multiple requests and connection state information stored on the server:
- The app and the server have an identical salt string hard-coded, unique to each successive version of the mobile app. This string must be kept private.
- When a user installs the app on their device, the app contacts your server and informs it of the version of the app, and the device's IMEI, which the APIs for whatever mobile platform you are working with should enable you to retrieve.
- The server generates a unique key for that instance of the app which is sent back to the app and stored on the device, and stores it in the server-side database with the IMEI and the installed version.
- During day-to-day operation (i.e. when making the request outlined in the question) the app follows this procedure:
- Retrieve the following information:
- Device IMEI
- App key
- App version
- Hard-coded salt string
- Randomly generated string for additional salt (derivative of the current timestamp with microseconds is always good for a reasonable amount of entropy).
- Concatenate all these pieces of information together, preferably with hard-coded padding between them and produce a hash of the resulting string.
- Send to the server the following pieces of information along with the actual request data (maybe in cookies for a tiny extra bit of security):
- Generated hash
- App key
- Randomly generated string used as additional salt
- The server now uses the App key to retrieve the device IMEI and app version of that instance from the database, and uses that information along with the hard-coded salt string for the version ID and the additional salt string sent by the device to construct the hash. If the hash generated on the server matches the hash generated by the mobile device, the request is good, if not reject it.
- All communication in this process is over HTTPS.
In order to break through this system and successfully spoof a request, an attacker would need to know the following:
- Device IMEI
- App key
- App version
- Hard-coded salt
- The mechanism that you use to generate the hash (the precise format of the input string and the hashing algorithm).
Obviously if you are working with the mobile device 1 - 3 are easy to extract, but 4 and 5 cannot be found without reverse engineering the app (which there is literally nothing you can do to prevent, for people with the knowledge and the patience to do it).
A man-in-the-middle attack would be basically impossible - even after breaking through the SSL (which is non-trivial, to say the least) and reverse engineering the app to get 4 and 5, 1-3 cannot be retrieved without a brute force attack on the hash, which is sufficiently complex that this would take an average of several hundred million years (see this page to see how I arrived at that figure), especially if one of the three is of a variable length - which the app version string could easily be.