Mapping users from Google Checkout to Android Licensing responses - android

I am using Android Licensing as described here:
http://developer.android.com/guide/market/licensing/index.html
(...to verify that my customers for my android app have actually payed for the app.) My app has a server component on the web, and for extra safety I'm doing the license validation on this server.
It all works okay. Now, to my problem. Since each new user ties up resources on my central server, I'm actually kind of reluctant to have non-paying users. I have seen some evidence of users continuing to use the app after having gotten a refund (per the normal 15-minute grace period).
To curb this behavior, it would be great if there was some way to map the payment of users at Google Checkout, to actual users in my system. Is this possible?
The ResponseData that I receive from the android license server contains a field called "userId", but this doesn't seem to correspond to any information in Google Checkout. (See http://www.androidadb.com/source/skylight1-read-only/GoogleLVL/src/com/android/vending/licensing/ResponseData.java.html for the definition of ResponseData.)
Is it possible to determine which payment in Checkout maps to which app installation?

As I currently understand it, the userId is obfuscated even on a per-app basis such that you can uniquely identify users per app but not figure which user it is nor whether the same user bought another app.
But I'm not sure you really need to identify these customers based on userId. If you have a server running anyway, the best way to protect your app is to have your server check the licence.
App -> Server: Give me a new nonce
Server -> App: Here is a secure random nonce
App -> Licence Service: Check user licence with this secure random nonce
Licence Service -> App: Signed licence response including repetition of nonce
App -> Server: Check licence signature with secret key (only on server)
Server -> App: Reject, or provide random token for access, etc
In this scenario, you won't authenticate users even if they mess with your LVL checking code.
However, you may of course introduce vulnerabilities after step 6 if you don't watch your step. Still, if you're currently using the standard LVL code and App-side licence check with the secret key stored in your app, changing to a mechanism as sketched above would be a huge improvement (there's even a script to remove standard LVL checking code from apps).

Related

Why are Google API manager credentials necessary? (Or are they?)

I'm making an Android app that uses the Google Calendar API with a group of 3 other students, and we're struggling to understand the authentication process.
We expected to be able to be able to just include a Java library that calls the API and set our app to request calendar permissions, and then sign in to our personal Google accounts on our emulators and have the app be able to access our respective Calendars. We kept getting 403 (forbidden) errors, so obviously that didn't work.
So we tried to stumble through the confusing API documentation and copied some things from the Quickstart project. We managed to share the project with each other on the Google Developer Console and add OAuth credentials for each of our computers, and now it works for each of us, but we're still confused.
Why is this credential creation necessary?
How will the release process work? Obviously we don't want our users to have to generate SHA1 keys per-device to use our app from the Play Store.
Is there an easier way to do this? Do we even need the Developer Console?
These questions have likely already been answered, but I don't know enough about the process to know what to search for.
Google uses OAuth 2.0 for user authentication. What it means is that whenever a third party app requires permission to access Google's data, user has to first approve that request.
Now, to provide authorization Google provides you credentials (key & secret),Using this key & secret Google generates Access key and Refresh key to the application.
Access Key: Key used to access data from Google server for limited time.
Refresh Key: Key used to fetch new access key when older one expires.
Now focusing on your questions.
Q: Why is this credential creation necessary?
A: Credentials to assure that only your app can access user's calender data.
Q: How will the release process work? Obviously we don't want our users to have to generate SHA1 keys per-device to use our app from the Play Store.
A: Google will generate access and refresh key.
Q: Is there an easier way to do this? Do we even need the Developer Console?
A: Trust me..once you figure it out,it is very easy and most importantly secure way. (Google does not allow authentication using password as default)
You can learn more from here: https://developers.google.com/identity/protocols/OAuth2

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

What do I need from OAuth 2.0 in this simple Android app case?

The Story: I am making an Android app that allows a user to purchase a subscription, and does not require the user to have an account or login. I want to check whether or not a user has purchased a subscription, and the Google Play Android Developer API seems to provide this service.
The Problem (TL;DR): Should I use OAuth as a "web application", "installed application", "service application", or none of the above?
The Problem: To get started with this, I am told:
Access to the Google Play Android Developer API is authenticated using
the OAuth 2.0 Web Server flow. Before you can use the API, you will
need to set up an APIs Console project, create a client ID and
generate a refresh token. -source
Fair enough. There are then setup instructions that go on to say:
On the second page, select web application and set the redirect URI
and Javascript origins.
My application does access the Internet, but it is an installed Android app, not a web application, so I don't have a "redirect URI" or "Javascript origins" to link it to. Additionally, this would require a user to log in, which I do not want and is not necessary in my case (I just want to check whether or not the user has purchased a subscription).
So if instead of a "web application" I try to create an "installed application (Android)", this still requires a user login, to be able to manage the user's resources.
I do not want this. There is a third alternative called a "service account" that does not require a user login:
A Service Account is used when you have a service that wants to handle
its "own" resources (e.g., an App Engine app that manages Compute
Engine resources), as opposed to the resources of an external user
(e.g., the standard OAuth flow). Using a Service Account the app will
be the owner of the resources... If you use a Service Account, you will only get data about the service's purchases. -source
I'm not sure if that is what I want in my case...
Finally, there is also this option:
The simplest flow is one where no end-user authorization is needed.
You still need to identify your client application using the API key. -source
This seems perfect! However, I was told initially that to use the Google Play Android Developer API I need to authenticate with OAuth 2.0, and this does not use a client ID which I was initially told that I specifically need.
There are at least 2 problems with what you are trying to achieve here:
As you would be handling the server response in your Android application, you would have something like this in your code:
if (isSubscriptionValid())
Somebody could tamper with your application's APK on his device (which is very easy) and simply replace that check with:
if (true)
The attacker would then have access to your content without ever being subscribed.
As calls to the API have to be authorized by your developer account and being personally logged in on each users device is obviously no option, you would have to go for Service Accounts, as you've already figured out correctly.
These however are only meant for server-to-server interactions, as otherwise it would require you to store your private key on everybodys device and as it is not possible to store data securely on an Android device, you wouldn't meet this requirement:
The private key must be stored and managed securely.
Google recommends you to have a backend server to do this kind of checks. So you can decide if a subscription is valid before handing over content to the client and other things:
The API is designed to be used from your backend servers as a way of securely managing subscriptions, as well as extending and integrating subscriptions with other services.
If you do not have a backend server available, you have to rely on In-app Billing Notifications.

Coupons for In-app Billing

We are about to release an application on the Android Market, with In-app Billing for subscription that unlocks certain features for a the subscription period.
My boss now wants me to implement varying number of "free subscriptions" in the sense that:
The "lucky user" downloads & installs the application from the Android Market like any other customer (always free to install, but premium features require payment via In-app Billing).
The "lucky user" receives some key via email that allows him or her to avoid going through the In-app Billing checkout process (i.e. actually pay).
The key can only be used once.
Entering the key via a menu item, enables subscription for X months, as if he actually paid via In-app Billing.
The "key" basically acts like a coupon, but I haven't found any such option in the Publisher's Console.
Do you know of any such feature or a simple way to implement the above without duplicating the customer database on our (the publishers) server?
I actually dove into this subject maybe 2, 3 months ago. My conclusion was that currently there's no way of setting up this system, without using your own server.
Generating unique coupon-codes and expiring them on use is pretty straightforward. Let the user enter the code, send a POST-request to your server, hash the code both client- and server-side and see if they match. Next, expire the code serverside and you're set. It does however make your app vulnerable to piracy (if it isn't already); if you have a high-profile app, make sure to implement security checks (e.g. check SSL certificates to prevent a man-in-the-middle attack).
The hard part is reinstating previously acquired 'freebies' when users reinstall your app or change phones/firmware. For this purpose you're going to need a stable and reliable (cross-device) form of identification (e.g. access to the user's main Google-account on the phone). If you use user-provided e-mailaddresses, it's too easy to just enter someone else's e-mailaddress. If you were to implement a coupon-system, I would advise against reinstating 'freebies'.
I know this is a really old thread, but I had a similar need and found an official solution. For anyone who comes here for a solution:
Google introduced Promotional Codes couple of years ago and that is exactly what you're looking for.
You can create Promo Codes on the Play Console under Your App -> User Acquisition -> Promotion.
You can use promotions to give users a paid app or in-app product for free with a promo code. You can create promotions to reward loyal fans, acquire new users, and reconnect with previous users. Learn more.
yuo can add a screen for enter a coupons.
and the user can go in there and insrert his code and if it is correct you can give him whatever you want.

Can I obtain Google Checkout Order Id for a purchased Android app from the app itself?

We would like to allow our users to activate a service on one of our servers with each app purchased from the Android Market, verifying that the user has really purchased the app.
For this purpose we are evaluating to use Google Checkout's Notification History API, which allows us to query from our server the status of a Checkout Order ID.
Now the problem is that we don't know how to obtain the Checkout Order Id from the app itself.
With the new in-app purchases API we can get Checkout Order Id for each one of the in-app purchases, but not for the app purchase.
A better solution for getting confirmation of an app purchase is by using the Market Licensing Verification Service.
The purpose of this library is to let your app confirm that the user has actually purchased the app in question.
In order to check the transaction from your external server, you can use the techniques described under the heading "Offload license validation to a trusted server" on this blog post.
In essence, it suggests that you send a copy of the license server response, contained inside the ResponseData class, along with its signature, to your online server. Your server can then verify that the user is licensed.
Since the license response is cryptographically signed, your server can check to make sure that the license response hasn’t been tampered with by using the public RSA key stored in the Android Market publisher console.

Categories

Resources