Anonymously identify user by MAS receipt?

Is there a way to anonymously identify the user who purchased my app on the Mac App Store by his MAS receipt? By identifying I mean an opaque ID in the receipt that would be the same on *any* Mac where the user installs *my* app using his *same* Apple ID. (In other words, the ID could even be different for different apps for the same user.) This ID is needed when some user wants to get the stand-alone version of my app for it's not sandboxed and has slightly more features. We provide such customers with a free stand-alone license but ask for a proof of purchase. The MAS receipt is an almost sufficient proof. The client could send the receipt to our server, and our server could validate it locally or remotely with help of the Apple server. What our server cannot validate however is the authenticity of the hardware id, which is passed along with the receipt. The client could therefore pass our server someone else's receipt and also someone else's hardware id to get the free license. The "person ID" would limit the number of stand-alone licenses a single person could obtain.

Replies

>What our server cannot validate however is the authenticity of the hardware id, which is passed along with the receipt. The client could therefore pass our server someone else's receipt and also someone else's hardware id to get the free license. The "person ID" would limit the number of stand-alone licenses a single person could obtain.


Yea, I was thinking about the same type of thing. I don't think there is a way to do this? The best you can do I think would be to grab the hardware id, store it, and blacklist it. Also can you require internet connection and validate the receipt with Apple's server?


The user could just download the app on another Mac, get another receipt with a different hardware id, and send you another receipt and give it to a friend. Maybe a few copies will slip through the cracks, but how many Macs is a user likely going to have access to (so how many times are they going to be able to do this)? I would *guess* Apple must have some mechanism in place to see if the same Apple id is redownloading the same app on 1000 different macs (maybe?) generating 1000 receipts. I guess I would expect them to do something about that?

A receipt for an IAP comes with a transaction_id. You can require that the user purchase an IAP. Your server can record the transaction_id and credit only one device for each transaction_id.......I am not sure how this will work on Macs. It's straightforward on iOS.

Presumably you control the client software? So the only way it would send a fake hardware ID is if it was hacked/cracked to to so ... in which case you have already lost.

A single user can download the app from the store and generate multiple legit receipts (from the App Store's perspective) by logging in and installing on different Macs. Then the user could give out extra receipts to others (which they can use to redeem a outside the App Store receipt if the developer offers it). Some kind of unique id (like transactionIdentifier on iAP) could be used to blacklist a customer from redeeming his receipt multiple times, if you set up a server to store and blacklist the ids. That may or may not be worth the effort though.

In iOS so I don't know if it works in Mac; .......a receipt can be decoded by the developer rather than being sent to the Apple servers. When decoded by the developer (either on the device or elsewhere) it will be signed with a device ID. For iOS that will be the identifierForVendor. Such a receipt cannot be 'given' to another device because it will then have the wrong identifierForVendor.

Even though I control the client software (my Mac app), a request to my server can also come from other sources which I don't control. Theoretically, a hacker could even build and distribute a software that could send fake HTTP requests to my server, passing a legitimate pair of receipt and hardware id, in order to obtain free licenses for every one who desires. Building such "keygen" would not even require to hack my app because the receipt and MAC address can be easily found.


In the lack of some kind of "person id", the hardware id (for Macs it's the MAC address) looks like a practicable replacement. Of course, as Macho Man ***** Savage rightly noted, some user could install his purchased app on his friend's Mac to get another receipt for another hardware id and therefore get another stand-alone license too. However, this risk has always been present with any App Store purchase, and I'm sure there are people who are already abusing them exactly in that way 🙂 So we can safely leave it to Apple to decide.


Another important detail is that the stand-alone key is not sent directly in response to the HTTP request, but instead, to a registered user's email address, similarly to a password restore request on some website. In this case, if someone tries to reuse another person's receipt / hardware id, he will not get anything directly in return.

I don't have any IAPs, so I don't have any transaction id, just like I don't have any person id that I mentioned. Does it mean that I cannot use your idea?

@PBK: Thanks but on Macs it's a bit different. Yes, I can decode the receipt and extract the already mentioned hardware id, similar to iOS. However, unlike iOS which is a strictly managed environment, on Mac, the user could simply send a fake request pretending it was coming from a different app or even a different device. There is no way for server to know if the client is telling the truth...

But if your app is doing the decoding and checking that the receipt is aligned with the hardware id then your app can issue something that limits the use on the hardware with that hardware id.

@PBK: On client side, yes. This is actually how receipt validation works locally on the client – the receipt is analyzed, it must be signed by Apple, untampered with, and its device id should match the current device. On server side however, the data comes from an untrusted source and there is no way for the server to check that the receipt is really coming from the specified device. It could be a made-up request pretending to come from your device and your app.

There are many ways of authenticating a user.


For example, the server sends the user an authentication code. The user places that code into the app and the app (if there is a device specific receipt in the device) generates a response code (for example the hash of the original code). The user sends the response back to the server and the server checks to be sure the response is correct.


But this may not address your issue of the user who goes from machine to machine installing the app on their friend's machines. One way to address this issue is to update the app on a regular basis. That requires that the friend relog into the original user's Apple account to get the upgrade.

@PBK: Sorry, not sure, how exactly this will ensure that the response code will not be fake? There can be no private key inside the client app, because it could be extracted by a hacker. So there is no way to cryptographically ensure that the response code really comes from the app and not from a hacker's emulator (which knows how to calculate the hash too). In this regard, this scheme is no better than just sending the server in plain text the boolean "yes, the receipt was valid, give me the license" message. Or am I misunderstanding your idea?

You wrote above that you have a receipt in a device and "Yes, I can decode the receipt and extract the already mentioned hardware id, similar to iOS.". That means that within your app you can validate that the receipt is authentic for the device and that the device is therefore entitled to privledges. The question seems to be, how can your app communicate that entitlement to your server.


Your app can send your server a package with the message "I am entitled" and "My random number is 123456" and if you want "my username/password is NAME/PASSWORD" where the number 123456 is a random number generated by the device so that all packets will be different and app specific or device specific (for device specific use the hardware id for the random number). The app also calculates the hash of the package salted with a known secret (known to your server and in the app) and adds that hash to the transmission along with the package. Your server repeats that calculation and if the hash is correct it accepts the app on the device as trusted; it accepts the username and password as suitable. All further communications from the app are allowed as long as they come with the random number or if you want you can rely on username and password. (Aactually, I would hash the password and use that rather than the actual password.)