How do you uniquely identify a user on Android? - android

My app uses licensing and in-app billing for subscriptions. I was able to use
AccountManager manager = AccountManager.get(context);
Account[] accounts = manager.getAccountsByType("com.google");
but that gets a number of accounts. Currently I'm just using the 1st one. I don't know which one was used to purchase/download the app. I myself had up to 3 Google accounts (the GMail one dumb old Google forces you to sign up with to activate your phone, my real Google account, and my work account).
I don't really need the email address, just some way to acknowledge one user is the same even if they are on different devices. If they access the app from different devices, that is ok.
The app accesses a server in the background, so will send the user id to record.
None of the similar questions had an answer, or rather the answer was 'no way'.
Is the most proper solution to have a menu item to let the user chose the account? Or would it be better to save ALL of the user ids on the server and if the user matches one, let them in? Doesn't the license server API provide some kind of unique user hash? (I can't find one, but it's a little fuzzy to me.)

So I'll repeat what others have said: if the only reason you're concerned is to identify the user for licensing purposes, stop right now because the licensing library does not require you to read e-mail addresses in order for it to work. The Play app will be the man in the middle for you.
An app you buy is available to other devices just fine.
The other questions answered 'no way' for a reason.
edit: however, if you're concerned about "unmanaged" products and not just for licensing purposed (you didn't make that clear, only now I'm seeing), then you could pair the information to a given user account. You should use the Account manager and ask the user to select the account he/she thinks is fit. By all means do not arbitrarily select an account for the user. Do as other apps do. The user knows better about his/her own personal information. And please do it securely.
My reasonable opinion.

Related

Is it possible to track in app purchase in android / ios without database react native [duplicate]

I plan to use non-renewing subscription on SaaS app since apple doesn't allow auto-renewable for SaaS.
Apple also requires us to provide a server side mechanism to track the subscription with multiple devices.
But, based on my research, apple also seems to reject app if registration is mandatory, so such user registration must be made optional.
My app can be used without registration at start, so registering is optional at this point. But, if users want to buy non-renewing subscription, registration is mandatory to track the subscription.
Does apple reject this approach?
Related links:
app rejected.how to track user non-renewing subscription
*UPDATE
I checked the session video of WWDC2012, and it seems it is ok to ask user to register with your server BEFORE purchase for non-renewing subs. I will post an answer once they really approved this method.
*UPDATE
I got an reply from apple through Resolution Center.
The bottom line is we should allow user to buy subscriptions without registration anyway.
This is the answer from apple review team.
It would be appropriate to make registration optional. You may provide
an alert stating that the user will not be able to track a
subscription on multiple devices without registering. However, you
should provide the option to register and track a subscription after
the subscription is purchased as well.
I don't have a definitive answer but my understanding (not just a guess) is that you must permit them to purchase the subscription without making an account. You can warn them that if they don't make an account, their subscription won't be portable to other devices, but you still have to let them move forward without an account if they want.
From a technical perspective, you could treat this as "you must allow the user to make an account without any personal information"; they might have an account on your server for receipt validation, etc, but it's not tied to their name, email, udid, etc. The issue is one of privacy, so as long as it's not personally identifiable info you're storing, it's fine to keep track of the subscription so you know when it expires, etc. (It's nice to later let them enter their email if they want so they can make the subscription portable.)
Of course, what Apple approves or not changes over time and varies for other reasons, so YMMV.

some google in-app billing API3 questions

I'm starting to make some in-app purchases on my future app, and i wish to ask some questions regarding the new API (3) of the in app billing library (shown here):
google says (here) that there are no more unmanaged items. this means that in order to have multiple consumable items, the play store cannot hold a counter, so you need to either consume the purchase right when you put it in the app, or only when you need it.
My question about it is how would you get the consumable items stay on multiple devices? for example, if the user purchased 2 health potions, and because of the new limitations, they both are stored only on the app itself of one device, how could the end user go to another device , run the app and see that he has 2 health potions?
is it possible to make some purchases for free on some cases, programmatically ?
it could be useful for testing or on some cases when i want to reward the user for something he has done . i might even want to do it completely transparent and without any dialogs.
i know that there is a sandbox mode but that's only available by adding specific accounts as test accounts .
the lecture speaks of a "developer payload" (here) that you can put on the purchases for better security. they said that the data should be an id of the user, but they don't say what id i should use (only gave an example of google plus , which many people don't have).
my question is: what should be used for the "developer payload" ? if i use the sample, what do they use, and is it safe to use it or should i change it ?
i also don't understand how could it be useful, since the play store should always hold data as to which user has which items, so how could the play store be fooled on this? or maybe they talk about protection from changing the apk of the app?
is it possible to make a transaction of multiple purchases ? if so, can i hide those that don't cost money ? and if all are for free, maybe not show anything at all ?
Answer 1)
The way I have found for the question 1 is given below.
if your application used server database(stored data on server using internet connection) then you can simply stored data for particular user,Like if user has purchased 2 health potions and when user trying to use that 2 health potion from the another device then simply checked it is purchased by that user previously or not. if it is already purchased by that user then simply restrict that user to purchase potions again.
Answer 2)
Google is provided trial period for the subscription product. so that user can purchase that item as $0.00 amount as a trial period and when time expired(time can be 7day or more) item can be changed it's type as subscription item with credit card information as like simple purchase flow.
but, you used word "pro grammatically and without any dialog" then according to my knowledge Google will not provide it for the single user or for the particular user. you can simply give trial period value in the Google console for the all application user.
check this link for more detail: "Free trials" http://developer.android.com/google/play/billing/billing_subscriptions.html#administering
Answer 3)
I would like to suggest you for the developer payload, first of all it is not mandatory you can pass either blank string or with developer payload. According to my knowledge it should be working like "security code" same as you given in the Google site while searching content "Some Random String".
how to use developer payload and what should be use for developer payload
check this link
Developer payload is useful for the application?
I think it is working like security code like Random String, and while you retrieve data you can verify that item that was purchased is same or not so that if in case some kind of hacker can be redirect to the other product then you can check it at response time, is it the same product as you are going to purchased or not and user can be protect from unnecessarily withdrawn money from his account.
and also check given link I have explained more for the developer payload.

Why is it important to set the developer payload with in-app billing?

I'm using version 3 of the in-app billing API. I have a single, managed, non-consumable item. I have not released this feature in my app yet, so I want to decide on the purchase payload contents before there are any purchases.
From "Security Best Practices":
Set the developer payload string when making purchase requests
With the In-app Billing Version 3 API, you can include a 'developer
payload' string token when sending your purchase request to Google
Play. Typically, this is used to pass in a string token that uniquely
identifies this purchase request. If you specify a string value,
Google Play returns this string along with the purchase response.
Subsequently, when you make queries about this purchase, Google Play
returns this string together with the purchase details.
You should pass in a string token that helps your application to
identify the user who made the purchase, so that you can later verify
that this is a legitimate purchase by that user. For consumable items,
you can use a randomly generated string, but for non-consumable items
you should use a string that uniquely identifies the user.
When you get back the response from Google Play, make sure to verify
that the developer payload string matches the token that you sent
previously with the purchase request. As a further security
precaution, you should perform the verification on your own secure
server.
Rightly or wrongly, I have decided not to take the "further security precaution" of setting up a server to perform purchase verification. And I do not store my own record of the purchase -- I always call the billing API. So is there really any reason for me to do this payload verification? The verification API itself certainly verifies the identity of a user before reporting an item as purchased, and if an attacker has compromised a device (either the app or the google play API), I don't see any benefit of doing an additional check on the user's identify on the device where it can easily be circumvented. Or is there a reason to do this that I'm not thinking of?
If you don't keep a record there is no way to verify that what you get is what you sent. So if you add something to the developer payload, you can either trust that it is legitimate (which is a reasonable assumption if the signature verifies), or not trust it completely and only use it a reference, but not for validating license status, etc. If you store the user email, for example, you can use the value instead of asking them to enter it again, which is slightly more user friendly, but your app won't break if it is not there.
Personally, I think that this whole 'best practices' part is confusing and is trying to make you do work that the API should really be doing. Since the purchase is tied to a Google account, and the Play Store obviously saves this information, they should just give you this in the purchase details. Getting a proper user ID requires additional permissions that you shouldn't need to add just to cover for the deficiencies of the IAB API.
So, in short, unless you have your own server and special add-on logic, just don't use the developer payload. You should be OK, as long as the IAB v3 API works (which is, unfortunately, quite a big 'if' at this point).
You should pass in a string token that helps your application to identify the user who made the purchase...
If your application provides its own user login and identity, which is different from what Google accounts the phone is connected to, then you would need to use the developer payload to attach the purchase to one of your accounts that made the purchase. Otherwise someone could switch accounts in your app, and get the benefit of purchased stuff.
e.g.
Suppose our app has login for userA and userB. And the phone's Android google account is X.
userA, logs into our app and purchases life membership. The purchase details are stored under google account X.
userA logs out, and userB logs into our app. Now, userB also gets the benefit of life membership, as android google account is still X.
To avoid such misuse, we will tie a purchase to an account. In the above example, we will set developer payload as "userA" when userA is making the purchase. So when userB signs in, the payload won't match to signed in user (userB), and we will ignore the purchase. Thus userB can't get benefits of a purchase done by userA.
There is also another approach to the developer payload handling. As Nikolay Elenkov said it is too much overhead to require user ID and setting additional permissions for user profile to your app, so this is not a good approach. So let's see what Google says in the latest version of TrivialDrive sample app in In-App Billing v3 samples:
WARNING: Locally generating a random string when starting a purchase and
verifying it here might seem like a good approach, but this will fail in the
case where the user purchases an item on one device and then uses your app on
a different device, because on the other device you will not have access to the
random string you originally generated.
So the random string is not a good idea if you are going to verify the purchased item on another device, but still they don't say this is not a good idea for verifying the purchase response.
I would say - use developer payload only for verifying the purchase by sending a random unique string, save it in preferences/database and on the purchase response check this developer payload. As for querying the inventory (in-app purchases) on Activity start - don't bother checking developer payload since that might happen on another device where you don't have that random unique string stored. That's how I see it.
It depends how you verify the developerPayload. There are two scenarios: remote verification (using server) and local (on device).
Server
If you're using a server for developerPayload verification it can be arbitrary string that can be easily computed on both the device and server. You should be able to identify the user who has performed the request. Assuming every user has the corresponding accountId, the developerPayload may be computed as combination with purchaseId (SKU name) like this:
MD5(purchaseId + accountId)
Device
developerPayload shouldn't be user email. A good example why you shouldn't use email as payload is Google for Work service. Users are able to change their email associated with the account. The only constant thing is accountId. In most cases email will be OK (e.g. Gmail addresses are immutable at the moment), but remember to design for future.
Multiple users may use the same device, so you must be able to distinguish who's the owner of the item. For device verification developerPayload is a string that uniquely identifies the user e.g.:
MD5(purchaseId + accountId)
Conclusion
Generally the developerPayload in both cases may be just the accountId. For me it looks like security through obscurity. The MD5 (or other hashing algorithm) and purchaseId is just a way to make the payload more random without explicitly showing that we're using id of the account. The attacker would have to decompile the app to check how it is computed. If the app is obfuscated even better for you.
The payload doesn't provide any security. It can be easily spoofed with 'device' approach and without any effort seized in 'server' checking. Remember to implement signature checking using your public key available in the Google Publisher account console.
*A must-read blog post about using account id instead of email.
In the Google IO video about IAB v3 given by the author of the trivial drive sample himself, this was briefly addressed towards the end of the video. It's to prevent replay attacks, e.g. attacker sniffs the traffic, steals the packet containing a successful purchase, then tries to replay the packet on his own device. If your app doesn't check the identity of the buyer via the dev payload (ideally on your server) before releasing the premium content (also ideally from your server), the attacker will succeed. Signature verification can't detect this since the packet is intact.
In my opinion, this protection seems ideal for apps with online account connectivity like clash of clans (payload comes in naturally since you have to identify users anyway), especially where hacking compromises multiplayer gameplay with far reaching effects other than a simple localized case of piracy. In contrast, if client side hacks on the apk can already unlock the premium content then this protection is not very useful.
(If the attacker attempts to spoof the payload, the signature verification should fail).
Late 2018 update: The official Google Play Billing Library intentionally does not expose the developerPayload. From here:
The field developerPayload is a legacy field, kept to maintain the compatibility with old implementations, but as mentioned on Purchasing In-app Billing Products page (https://developer.android.com/training/in-app-billing/purchase-iab-products.html), this field isn't always available when completing tasks related to In-app Billing.
And since the library was designed to represent the most updated development model, we decided to don't support developerPayload in our implementation and we have no plans to include this field into the library.
If you rely any important implementation of your in-app billing logic on the developerPayload, we recommend you change this approach, because this field will be deprecated at some point (or soon).
The recommended approaches is to use your own backend to validate and track important details about your orders. For more details, check the Security and Design page (https://developer.android.com/google/play/billing/billing_best_practices.html).
I struggled with this one. Since a Google Play account can only own one of any "managed" item, but could have several devices (I have three), the above comment from somebody that you sell a "per device" won't work... they'd be able to put it on their first device, and no others ever... If you buy a premium upgrade, it should work on all your phones/tablets.
I despise the notion of getting the user's email address, but I really found no other reliable method. So I grab the 1st account that matches "google.com" in the accounts list (yep, a permission to add to your manifest), and then immediately hash it so it's no longer usable as an email address but does provide a "unique enough" token. That's what I send as the Developer Payload. Since most people activate their device with their Google Play id, there's a good shot all three devices will get the same token (using the same hash algorithm on each device).
It even works on KitKat with multiple "users". (My developer id is on one user, my test id on another, and each user in their own sandbox).
I've tested it across six devices with a total of 3 users and each users devices have returned the same hash, and the different users all have distinct hashes, satisfying the guidelines.
At no point am I storing the user's email address, it's passed straight from the code to get the account names to the hash function and only the hash is saved in the heap.
There's probably still a better solution out there that respects users privacy even more, but so far I haven't found it. I'll be putting a very clear description of how I use the users Email address in my privacy policy once the app is published.
This often responds to a product definition (Your application).
For example for the case of subscriptions. Will the same user be able to use the subscription on all the devices he / she has? If the answer is yes. We did not check the payload.
For consumables. Suppose a purchase in your application gives you 10 virtual coins. Will the user be able to use these coins on different devices? 4 on one device and 6 on another?
If we want to work only on the device that made the purchase we have to check the payload for example with a self-generated string and locallly stored.
Based on these questions we have to decide how to implement payload check.
Regards
Santiago

Is there a way to give an Android in-app subscription to someone for free?

I've seen similar posts from a while back that say that the only way to do this is to have the person actually purchase the subscription, and then I can process a refund. Is there any update on this, or is that still the only way to give a specific person a free subscription?
A friend of mine has a solution with an iPhone app... The person that requests the app for free gives my friend their UDID, and my friend puts it into a database. The app checks the database for the specific UDID each time it is run, and if it is there, the subscription content is provided. Otherwise, it must be purchased.
But this doesn't seem feasible for Android, because Android devices don't really have unique IDs; and I don't know how a user can find this device ID on an Android, anyway.
Not a subscription to the best of my knowledge, unless you set them up with a test account. For refunds for in app managed items, you can control what a refund does however and hence it's up to you.
Set the user up with a test account. The test accounts work based off of email address. If you provide their Google email address, it should allow you to do anything, including giving them a free subscription.

How do I transfer one of my Android Apps to another Android Developer account (not mine)

To be clear, I am an Android Developer - and sold one of my apps (i have 5 in my account) to a business contact of mine. I want to transfer that ONE app from my developer account to his developer account.
It seems Android clearly defines how you transfer apps from an old account, to a new account (but both of those accounts are owned by you - and in this case the old account is closed down)
How do i transfer this one app i sold, with out affecting either account, or without hurting/losing the apps ratings/reviews/rank etc?
There is no official way to do this that I know of. As you mentioned, there is a support page that suggests that Google has this capability. I would recommend that you contact the Android Market support team and ask them directly, clearly explaining your situation. That page says:
Contact us from both the original email address and the new email address requesting to transfer applications. We require emails from both accounts so that we can confirm ownership.
So I think it's not so much about owning both accounts as much as proving that this isn't a fraudulent transaction. If you explain the situation and have both yourself and the contact you sold the app to email them, that would confirm that both parties have consented.
I'm not sure if the Android Market support team will actually do it, but it's worth a shot.
I don't have an answer to your question, but hope you realize that you can't change the apk signing key for signing the app. If you do, users can't update and you have to release the app with a new package name.
Verify you have everything ready in checklist:
https://support.google.com/googleplay/android-developer/checklist/3294213
Ask to transfer your app to target Google Play account e-mail:
https://support.google.com/googleplay/android-developer/contact/appt
Always remember to get original signing key for the app from developer. If he's using one singing key for all of his apps, it's his fault.

Categories

Resources