How to validate IAP receipt without a server after /verifyreceipt goes away?

Good day, all. Back in January I decided to write a little app out of necessity that nobody else had written as I needed it. I was looking at supporting IAP and at the time to do a Lite and Pro version, and /verifyreceipt wasn't yet deprecated. I put the app aside for a while to focus on another project, and finally came back to it in early August to start from scratch to learn SwiftUI, only to find that /verifyreceipt is now deprecated, and no date as to when it'll go away.

The problem is that Apple's documentation for IAP now assumes you're going to have a server for secure communication between your server and Apple's. I get that, but this teeny little app isn't worth the trouble of setting up and maintaining a server to go with it. All I want to do is make sure that if a user cancels their non-consumable Pro purchase, that I can determine that there was a change, and unmark the app as a Pro version.

So, down the rabbit hole I went trying to find a way to solve this problem without building OpenSSL. I think I found a solution, and I tested it and it works with one caveat.

https://github.com/filom/ASN1Decoder/tree/master

This code decodes the receipt file and gives me the fields I need, except for "in_app_ownership_type". I don't know if I need it, but if I do, I'll have to determine how to add support for that. I wanted to get people's opinions on whether this GitHub project is a viable solution in lieu of building and paying for a server, and if there are any caveats which come with it. For example: when the App Store asks if there's cryptographic code in the app, am I going to have to now say yes with this code?

If a server is the ONLY solution after /verifyreceipt shuts down, I'm just going to make a pro version and be done with it, I don't need this headache. I even tried RevenueCat which had its own set of problems (and will not be using). If anyone from Apple is reading this, please consider coming up with an easy solution for checking receipt values before removing /verifyreceipt.

And also, if there's an easy solution I'm missing, please let me know. I've done so much reading, but once I hit docs that say "...your server...", I just shake my head and move to finding a different solution.

Thanks!

Answered by App Store Commerce Engineer in 763091022

Hello starmike, we would recommend using StoreKit 2 for IAP, as StoreKit 2 has built-in verification of transactions. For example, https://developer.apple.com/documentation/storekit/product/3803206-latesttransaction returns a VerificationResult, which will allow different behaviors depending on the result of verifying the certificate chain and signature, abstracting both the verification and decoding of the transaction data away.

Here are some WWDC videos that go over StoreKit 2

https://developer.apple.com/videos/play/wwdc2021/10114/ https://developer.apple.com/videos/play/wwdc2022/10007/

Also, in our documentation: "Don’t call the App Store server verifyReceipt endpoint from your app. You can’t build a trusted connection between a user’s device and the App Store directly because you don’t control either end of that connection, which makes it susceptible to a machine-in-the-middle attack." (https://developer.apple.com/documentation/appstorereceipts/validating_receipts_with_the_app_store)

The verifyReceipt API was only ever useful from a server. Calling it from an app is very insecure.

Why not compile OpenSSL?

There is also all the StoreKit 2 stuff which I think will tell you all you need to know about the ISP on the device.

Thanks for your reply. In doing more reading, I see that you were posting in a thread about TPInAppReceipt which I just found and will try later today.

There are two reasons why I wanted to avoid using OpenSSL:

  1. It's like using a hammer to push in a thumbtack.
  2. I didn't know if using OpenSSL would open up a can of worms for encryption compliance.

I'm just trying to validate receipts with as little headache as possible. My app has been finished for two weeks but I'm stuck with trying to properly fix this IAP issue.

Accepted Answer

Hello starmike, we would recommend using StoreKit 2 for IAP, as StoreKit 2 has built-in verification of transactions. For example, https://developer.apple.com/documentation/storekit/product/3803206-latesttransaction returns a VerificationResult, which will allow different behaviors depending on the result of verifying the certificate chain and signature, abstracting both the verification and decoding of the transaction data away.

Here are some WWDC videos that go over StoreKit 2

https://developer.apple.com/videos/play/wwdc2021/10114/ https://developer.apple.com/videos/play/wwdc2022/10007/

Also, in our documentation: "Don’t call the App Store server verifyReceipt endpoint from your app. You can’t build a trusted connection between a user’s device and the App Store directly because you don’t control either end of that connection, which makes it susceptible to a machine-in-the-middle attack." (https://developer.apple.com/documentation/appstorereceipts/validating_receipts_with_the_app_store)

Thanks, I'll take a look at StoreKit 2 more closely.

I just wanted to mention that after looking at StoreKit 2 more closely, it did exactly what I needed. I moved from SK to SK2 in about two hours...maybe less. Thanks for the heads up on that.

How to validate IAP receipt without a server after /verifyreceipt goes away?
 
 
Q