I'm thinking about ways to secure my app against hacked in-app purchases by the likes of Freedom.
I'm using In-app Billing Version 3 API, and haven't yet implemented the "payload" feature that is in the sample in-app billing code (but not filled out). I am wondering whether that is a useful protection against Freedom, or not.
The idea appears to be to send a payload when initiating the in-app purchase:
/* TODO: for security, generate your payload here for verification. See the comments on
* verifyDeveloperPayload() for more info. Since this is a SAMPLE, we just use
* an empty string, but on a production app you should carefully generate this. */
String payload = "";
mHelper.launchPurchaseFlow(this, SKU_PREMIUM, RC_REQUEST,
mPurchaseFinishedListener, payload);
And you set up the mPurchaseFinishedListener
callback (passed above) to verify the purchase when you get a response, with something like:
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
if (!verifyDeveloperPayload(purchase)) {
complain("Error purchasing. Authenticity verification failed.");
return;
}
// ... it's OK... now we can act on the purchase...
}
}
boolean verifyDeveloperPayload(Purchase p) {
String payload = p.getDeveloperPayload();
/*
* TODO: verify that the developer payload of the purchase is correct. It will be
* the same one that you sent when initiating the purchase.
return true;
}
(My understanding is that, whatever format of payload you choose, you're stuck with it because it (the payload) is stored by google forevermore against each user purchase, so you need to be able to verify the payload in, say, 10 years' time.)
So, on to my actual question:
Does this "payload" mechanism provide any protection against hack apps like Freedom? Or does Freedom effectively just provide a fake credit card to fake the purchase in the middle of the above mechanism, without altering anything else in the purchase procedure, in particular leaving the "payload" intact?
So is it the case that, even using Freedom, the original payload that you send on initiating the purchase is still returned to the mPurchaseFinishedListener
, and will pass the checks in verifyDeveloperPayload()
regardless of the fake payment details used?
Or (hopefully) will the intervention by Freedom result in a non-existent (or at least different) "payload" returned to the mPurchaseFinishedListener
, and hence result in a failed verification?
If it would result in a failed verification (payload doesn't match with that sent when initiating the purchase), we then move on to a question about what form the "payload" should/could take. From some research there are complicated ways to generate the payload, and you can store it on your own server and query that, but it's all a big big hassle.
So, if the payload feature is effective against Freedom, would a valid approach be just to use some arbitrary fixed payload... one that generic hacks like Freedom would not know about? E.g. you could use "I love bananas" or "com.mydomain.app" or "EJF323MASd8DAS". That wouldn't provide any protection against hacks that specifically analyse and target your app, but for generic hacks like Freedom... maybe it would? And it has the benefit of simplicity...