IAP cracks that seem to have valid receipts - ios

We have a successful app on the iOS app store with in-app purchases. Every time a purchase is completed we send the receipt to our server, our server than checks the receipt with Apple's servers and logs apple's response(including whether the purchase was valid and that they come from our app in that same time and date).
We have quite a few users who use iap cracks that send us receipts that apple says are invalid. However we started now to see cheaters that have receipts that apple replies that are VALID. What is strange in these cheats, that when such a cheater user purchases in our app, he usually purchases all of the purchases with the exact same receipt.
Have you heard of such a way to 'fool' apple receipt validation?(to generate receipts that apple will say they are from our app in the time of the 'purchase')
Is there something we can do to find those cheaters in their 1st purchase (for the next purchases we can simply check times of the next receipts or make sure that our receipts are unique)
Thanks!

Is there something we can do to find those cheaters in their 1st purchase
Actually, if this is the same hack I've seen discussed as a proof of concept recently, the first purchase is legitimate. The "innovation" is in decoding that legitimate receipt and rejigging its IAP ID with a different one while the receipt overall still appears valid. So simply avoiding the duplicates is enough. Didn't think that one was anywhere near production-ready though, so this might be something different.

We also faced similar issue while developing a game of iOS app store where business model was based on In App Purchase only.
Initially we used to check with Apple Servers for the receipts directly from the device. But some hacker has created a hack for the users where they can install the DNS server certificate on their device which spoofs the response from Apple.
The way to do this is let web server check for the receipts from Apple directly with some kind of hashing or md5 check to make sure the response if from Apple.
here is a link which have a detailed information on this https://www.objc.io/issues/17-security/receipt-validation/
Hope this helps.

Related

iOS in-app purchases verify receipts for consumables

in iOS with in-app purchases, it is necessary to verify receipts with subscriptions. is it necessary to verify receipts for consumables also?
No you don't need to verify receipts for consumables.
You don't need to verify receipts for subscriptions either. What's important here is that you can restore running subscriptions; but for that you can use purchase ID.
As always make 100% sure you've given the user what was paid for before telling iOS that the purchase was successful!
(There are all kinds of other considerations why you would like to keep purchase related information on a server, but that's not what you ask about.)
Necessary, no. Recommended, yes.
All purchases; consumables, un-consumables and subscriptions are susceptible to fraudulent attacks. Often though iap crackers or network spoofing. Validating the receipt can mitigate this problem.
You can validate the receipt locally in the app (see Validating Receipts Locally), though it is still susceptible to cracking.
The safest way to prevent fraud is to perform server-side validation by sending the receipt to your server then sending it on to Apple (see Validating Receipts With the App Store).
However, do not validate the receipt with the app store in the app itself. It's really easy to spoof the network request and return a positive (valid) result.
If you notice a large discrepancy between the actual purchases in your reports from Apple and your in-app purchase analytics (assuming you have that), you may want to invest in server-side validation, otherwise, if it's not a problem, don't worry about it.

iOS In App Purchase with Rails Backend

I'm having some confusions when creating in app purchase strategy for my iOS app. Some background info below;
I have an iOS app and a web app which both will work in subscription model. The backend has been developed in Ruby on Rails.
Currently I'm trying to develop the iOS auto-renewal in app purchase. I came across couple of gems which helps to verify in app purchase receipts (e.g Venice). I get that the whole point of verifying the receipts from the backend rather then the client is to make it secure and to be able to keep a copy of the receipt in your own server.
I can foresee a huge problem as explained below;
A user can create an account using the iOS app and subscribe to the service by paying X dollars monthly using x#x.com apple id. By doing this I will have the record of this user in my backend including the expiry date of his subscription which will enable for me to track if he renewed his subscription or not. The problem arises when this user logs out from the app and creates another user. Since his apple id is still x#x.com and as account email address or id doesn't matter at all when making a purchase from apple, the expiry date will still be a month ahead since he just subscribed with his previous account the new user will be identified as an already paid customer. Boom! now his friend can login with this account using the web app and enjoy it without paying a quid.
If this makes sense for you, there must be a solution for this hack. I know that Netflix uses Apple's IAP, Spotify used for a very long time.
Also gems like Venice, they don't put a thorough documentation on their github page therefore I don't know if this problem is solved by them out of the box. Just wanted to check with you guys and I'm sure many of you thought about this.
If you're attributing the auto-renewing purchase to a user in your database you will also want to attribute the original_transaction_id that is found in the receipt. Store this ID with the expires_date and ignore or error any receipts containing the same original_transaction_id the API receives that are already attributed to a different user in the database.
The original_transaction_id will never change for the iTunes user, even if they unsubscribe and re-subscribe at a later date it will remain the same. It will also remain the same if they upgrade/downgrade the duration of the subscription when the product IDs are of the same subscription family.
If you're looking for an alternative to Venice take a look at the itunes_receipt_validator gem (full disclosure: I am the author). It validates the signatures and decodes of both the deprecated transaction receipts and the newer grand unified receipts locally without connecting to Apple's API, but also provides the functionality to retrieve the updated receipt and receipt info from the Apple API.

Is there a way to retrieve a list of in-app purchases made with my app?

Suppose there is an app with in-app purchase that uses a web server to verify in-app purchases with Apple and keep records. Suppose that web server had a bug and wasn't properly processing purchase verification. Suppose that bug was discovered and fixed.
Does Apple provide any sort of API for retrieving a list of purchases made for an app so that the verification can be re-run and the end users credited with their purchases? So far googling things like "ios in-app purchase retrieve list of purchases" hasn't turned up very much.
(Yes, said app ought to have been logging that information thus invalidating the need for such an API).
Edit: To be clear, I'm looking to see if there's a way to do this from MY purchase verification server and not involve the client devices.

iOS In-App Purchase No Back-end

I am investigating the use of in-app purchase for what essentially would be a "pro" version of my app.
The app itself would be free but once in the user has the option to purchase the pro content (only 1 thing). The "pro" content would already be on the app and there is no need to download it, it would simply "unlock" it.
Is this allowed from the Apple Guidelines?
As only 1 non-consumable would be purchased I think the use of a back-end server isn't required.
Again is that allowed from the guidelines?
And is it safe and simple to just store the result in NSUserDefaults and if installed on another device pull it from SKPayment restore purchased and such?
I've looked at several other questions.
In-App Purchasing?
Retrieve purchased information in In-App purchase
How do I add consumable In App Purchases using NSUserDefaults and not my own server?
And those seem to suggest that my approach is valid, but as I know those things have changed recently I want to make sure I'm taking the right approach.
Thanks!
No problem having the content built in.
Best practice is to perform receipt verification on a server with an authentication protocol between the app and server (this is also true for several other mobile app stores). If you perform the verification on the device, people can use existing tools to get around your IAP checking and steal content. Take a look at https://developer.apple.com/library/ios/#releasenotes/StoreKit/IAP_ReceiptValidation/ for some information.
So while a server is not required, it is recommended. Only you can say if protecting your content is worth the hassle of maintaining a server.
I agree with J. Freeman that straight storage in NSUserDefaults seems weak. I store things in a local file but the format is tied to the device and requires a server computed key to create it. Finally, yes you should use SKPaymentQueue restoreCompletedTransactions to get things purchased on another device. Realize that the restored transactions should also have their receipts verified on your server.
Yes that is fine. You do not need a backend to do in-app purchases, and it is ok to ship with your content built in.
The one thing I would say be careful with though is storing the unlock information in NSUserDefaults as someone will easily be able to forge purchases that way. You should store the unlock information in the keychain.

Accessing StoreKit receipts directly from a server

I'm building an iOS app, which provides a service which our website already provides. It's a subscription based service, where all features are enabled when you're subscribed. To get people to sign up for regular payments on the app, it seems like I'll have to go through Apple's in app purchasing API, with auto-renewing subscriptions. That's fine, but the problem is the service users will purchase through the app must also be available on the site. But reading through walkthroughs and the developer guide, it looks like the only way to process transactions is through the app itself, which then can be set up to pass the info to the server. But then I'm imagining this scenario:
User purchases a subscription on the iOS app, goes back and forth between using the site and the iOS app. On the day the user is to be charged, and the days after, they're using just the website, for whatever reason. The server doesn't know they've been billed though, and so features are disabled. In order for the server to find out the user has been billed by Apple, the user has to open the app on their iphone or ipad and sync it with both Apple and my server.
Is there any way for my server to ping Apple directly and get information about the purchases made for my app for a given user? I haven't been able to find anything; the two suggested layouts, with or without server, both use the iOS app as the sole communicator with Apple, aside from having the server verify that information is valid. If it's not possible for the server to get this information first hand, what other possible solution could there be?
Try to not use Apple's built in payment system, and risk getting rejected (with the app duplicating a service that's been available for years online, do we no longer have to use their in app purchasing system anyway?)
If a user is paying through Apple, have the server give them a generous buffer between expected payment dates and when features are disabled (makes the problem happen less frequently but doesn't solve it)
When their account seems expired to the server but it doesn't expect that, email the user a message saying they have to open the app or else their account will not be credited for time purchased (seems like a strange and not really great thing to have to ask a user to do in order to use the service)
This is about all I've been able to think up so far. Anyone have any advice on these solutions, or know of others, or know who I could talk to to try and figure this out?
Yes, you can check on the status of a user's account from your server. There are a few caveats:
First and foremost, Auto-Renewing Subscriptions are reserved for periodicals such as magazines and newspapers. If your app doesn't resemble those, Apple may reject it (as they did mine) and request that you use Non-Renewing Subscriptions (read: Manually-Renewing Subscriptions).
Second: This scenario would require you to store all receipts that you receive on the app, on your server.
Finally: I don't know how your username/password system works, but the user would have to login with the same credentials on your app as they do on your website.
Here's how you check the status of a user's account: Store at least one receipt per user on your server. When you want to check the status, follow Apple's procedure for Verifying App Store Receipts. Send them that one receipt and they'll respond with the latest receipt and the expiration date. Now you'll know, at any given moment, if a person's account is current or not.

Resources