Recommended approach for new auto-renewable subscription purchase using StoreKit 1.0 + Apple Server Notifications 2.0

After watching all related WWDC content on auto-renewing subscriptions, including the most recent 2021 session titled "Manage IAP On Your Server," it's still unclear what actions are required for developers when an auto-renewing subscription is initially purchased using Store Kit 1 + Server Notifications v2.

From "Manage IAP On Your Server" around 21:30 a diagram of the initial subscription flow is shown:

What is most unclear to me is:

  • Is it necessary to retrieve the receipt data from the device and send it to the application server (to then be sent to Apple's server to verify and get the decoded data) if the App Store server is going to be sending a SUBSCRIBED + INITIAL_BUY notification around the same time to the application server anyway?

  • If it is still necessary to verify the receipt data from the local device, then what purpose does the SUBSCRIBED + INITIAL_BUY notification serve? What should the application server do when this notification is received if the subscription status has already been updated based on the receipt data?

It seems that the recommendation from Apple is to verify the receipt data from the device to obtain the original_transaction_id and then use this value to relate future server notifications received for this id.

Looking at the JWSTransactionDecodedPayload, it includes a field called appAccountToken however, it appears as though this can only be utilized with the iOS15+ StoreKit2 API.

It would be greatly appreciated if someone could clarify the required steps for managing an initial purchase on both the client and server for:

  • StoreKit 1 + Server Notifications v2
  • StoreKit 2 + Server Notifications v2

(I would love to start with StoreKit 2; however, I don't think it is feasible to limit purchases to iOS15+ at this time, given the large # of users still using older versions of iOS.)

Thank you!

Accepted Reply

In response to your questions

Q. Is it necessary to retrieve the receipt data from the device and send it to the application server (to then be sent to Apple's server to verify and get the decoded data) if the App Store server is going to be sending a SUBSCRIBED + INITIAL_BUY notification around the same time to the application server anyway?

Response - yes. The server-to-server notification contains no information to identify the user so as to be able to manage a user account on the app. By having the app pass the receipt to the server - and saving the initial appStoreReceipt to a user account, your server can validate the appStoreReceipt and decode the JWT signedTransaction in the server-to-server notification to match the original_transaction_id. From that point on, if the user never relaunches the app, the server-to-server RENEWAL notifications (and other notifications) can be matched to the appropriate user account.

Q. If it is still necessary to verify the receipt data from the local device.

Response - the recommendation is to implement server-side receipt validation to reduce the possibility of a man-in-the-middle attack. The app process can perform app side validation. There is no App Store requirement that server side validation be performed. This is an app security recommendation.

You noted - Looking at the JWSTransactionDecodedPayload, it includes a field called appAccountToken however, it appears as though this can only be utilized with the iOS15+ StoreKit2 API.

Response - there is no means with the StoreKit 1 API to set the accAccountToken. The app can only do so using the StoreKit 2 APIs.

You asked - It would be greatly appreciated if someone could clarify the required steps for managing an initial purchase on both the client and server for: StoreKit 1 + Server Notifications v2 StoreKit 2 + Server Notifications v2 For both scenarios, I refer you to the WWDC 2021 Session "Manage in-app purchases on your server". Another document to read is "Handling Subscription Billing"

rich kubota developer technical support CoreOS/Hardware/MFI

  • With regards to notifications in particular, "man-in-the-middle" is the wrong term to use for various reasons, but for this discussion, the relevant point is that there is no "middle". This is a web call that your application is receiving, that it did not request. It has simply arrived. The developer's job is now to make sure it was sent by Apple and isn't coming from someone who is just using Postman and happens to know the endpoint you're using, and knows how to make a JWT with a self-signed certificate.

    How was this answer marked as accepted, when the topic clearly includes notifications? The documentation linked to is just the existing documentation everyone already has access to, and doesn't address how to properly validate the certificate chain to secure notifications.

Add a Comment

Replies

In response to your questions

Q. Is it necessary to retrieve the receipt data from the device and send it to the application server (to then be sent to Apple's server to verify and get the decoded data) if the App Store server is going to be sending a SUBSCRIBED + INITIAL_BUY notification around the same time to the application server anyway?

Response - yes. The server-to-server notification contains no information to identify the user so as to be able to manage a user account on the app. By having the app pass the receipt to the server - and saving the initial appStoreReceipt to a user account, your server can validate the appStoreReceipt and decode the JWT signedTransaction in the server-to-server notification to match the original_transaction_id. From that point on, if the user never relaunches the app, the server-to-server RENEWAL notifications (and other notifications) can be matched to the appropriate user account.

Q. If it is still necessary to verify the receipt data from the local device.

Response - the recommendation is to implement server-side receipt validation to reduce the possibility of a man-in-the-middle attack. The app process can perform app side validation. There is no App Store requirement that server side validation be performed. This is an app security recommendation.

You noted - Looking at the JWSTransactionDecodedPayload, it includes a field called appAccountToken however, it appears as though this can only be utilized with the iOS15+ StoreKit2 API.

Response - there is no means with the StoreKit 1 API to set the accAccountToken. The app can only do so using the StoreKit 2 APIs.

You asked - It would be greatly appreciated if someone could clarify the required steps for managing an initial purchase on both the client and server for: StoreKit 1 + Server Notifications v2 StoreKit 2 + Server Notifications v2 For both scenarios, I refer you to the WWDC 2021 Session "Manage in-app purchases on your server". Another document to read is "Handling Subscription Billing"

rich kubota developer technical support CoreOS/Hardware/MFI

  • With regards to notifications in particular, "man-in-the-middle" is the wrong term to use for various reasons, but for this discussion, the relevant point is that there is no "middle". This is a web call that your application is receiving, that it did not request. It has simply arrived. The developer's job is now to make sure it was sent by Apple and isn't coming from someone who is just using Postman and happens to know the endpoint you're using, and knows how to make a JWT with a self-signed certificate.

    How was this answer marked as accepted, when the topic clearly includes notifications? The documentation linked to is just the existing documentation everyone already has access to, and doesn't address how to properly validate the certificate chain to secure notifications.

Add a Comment