Open atacan opened 4 months ago
That's a great question. The app account token is not stored on the client, but on Apple App Store servers. These are the steps:
1) Client creates a unique UUID
2) Token is passed to Apple's App Store servers using product.purchase()
3) The proxy fetches the the app account token from the App Store Servers
I could be wrong, but I think there are edge cases where the originalTransactionId
isn't available, for instance when not the original transaction receipt is available. I'm also not sure if originalTransactionId
works in case of family subscriptions. In both cases, app account token does work.
The app account token is used for the rate limiter. In case no app account token is set, you can disable the rate limiter using the environment variables by setting enableRateLimiter
to 0.
Note that the app account token is a different token than the JWT session token, which is stored on the client side. The session token is just a convenience token so the proxy doesn't have to make a slow call to the Apple App Store Server for every call.
Thank you.
The transaction id that the client puts in the fetchToken
request's body is this TranSaction
id
https://developer.apple.com/documentation/storekit/transaction/3749696-id, right?
I see that it's a UInt64. I haven't had any real transaction ID, could you tell me whether the following concern makes sense?
If this id is a naively incremented integer like 1,2,3... for each transaction, then the attacker can easily try a few integers and find one that would correspond to an active subscription's transaction ID. They can call the /appstore
endpoint whenever they need to get a new token.
@atacan: I've updated the in-app purchase validation and Pico Proxy now verifies the JWS representation of StoreKit 2's Transaction. The previous step where Pico Proxy calls the App Store Server is no longer necessary. See for more details: https://medium.com/p/98626641d3ea
The AppStoreAccount token is still used to identify the original purchaser so that there is one rate limit for the whole family (in case the developer enabled family sharing).
First of all, thank you for the great work, and sorry to hear the financial loss that you had.
I was wondering why transaction ID was not used as a user identifier instead you rely on app account token that is set by the app during the purchase. Isn't
originalTransactionId
also unique by an Apple account that made the purchase?I thought wherever I save it, the user can delete the app account token. UserDefaults, Keychain, Application support etc. can easily be manipulated by the user on macOS.