J'utilise la version 3 de l'API de facturation intégrée à l'application. J'ai un seul article géré non consommable. Je n'ai pas encore publié cette fonctionnalité dans mon application, je veux donc décider du contenu de la charge utile d'achat avant tout achat.
De "Meilleures pratiques de sécurité" :
Définissez la chaîne de charge utile du développeur lors de la demande d'achat
Avec l'API In-app Billing Version 3, vous pouvez inclure un jeton de chaîne "développeur payload" lors de l'envoi de votre demande d'achat à Google Play. En règle générale, cela est utilisé pour transmettre un jeton de chaîne qui identifie de manière unique cette demande d'achat. Si vous spécifiez une valeur de chaîne, Google Play renvoie cette chaîne avec la réponse d'achat. Par la suite, lorsque vous posez des questions sur cet achat, Google Play renvoie cette chaîne avec les détails de l'achat.
Vous devez transmettre un jeton de chaîne qui aide votre application à identifier l'utilisateur qui a effectué l'achat, afin que vous puissiez vérifier ultérieurement qu'il s'agit d'un achat légitime par cet utilisateur. Pour les articles consommables, vous pouvez utiliser une chaîne générée de manière aléatoire, mais pour les articles non consommables, vous devez utiliser une chaîne qui identifie de manière unique l'utilisateur.
Lorsque vous récupérez la réponse de Google Play, assurez-vous de vérifier que la chaîne de charge utile du développeur correspond au jeton que vous avez envoyé précédemment avec la demande d'achat. Par mesure de sécurité supplémentaire, vous devez effectuer la vérification sur votre propre serveur sécurisé.
À tort ou à raison, j'ai décidé pas de prendre la "plus grande précaution de sécurité" de la configuration d'un serveur pour effectuer une vérification d'achat. Et je ne stocke pas mon propre enregistrement de l'achat - j'appelle toujours l'API de facturation. Y a-t-il vraiment une raison pour moi de faire cette vérification de la charge utile? L'API de vérification elle-même vérifie certainement l'identité d'un utilisateur avant de signaler un article comme acheté, et si un attaquant a compromis un appareil (l'application ou l'API Google Play), je ne vois aucun avantage à effectuer une vérification supplémentaire sur l'identification de l'utilisateur sur l'appareil où il peut être facilement contourné. Ou y a-t-il une raison pour laquelle je n'y pense pas?
Si vous ne conservez pas d'enregistrement, il n'y a aucun moyen de vérifier que ce que vous obtenez est bien ce que vous avez envoyé. Donc, si vous ajoutez quelque chose à la charge utile du développeur, vous pouvez soit faire confiance à sa légitimité (ce qui est une hypothèse raisonnable si la signature est vérifiée), soit ne pas lui faire entièrement confiance et ne l'utiliser que comme référence, mais pas pour valider l'état de la licence, etc. Si vous stockez l'e-mail de l'utilisateur, par exemple, vous pouvez utiliser la valeur au lieu de lui demander de l'entrer à nouveau, ce qui est légèrement plus convivial, mais votre application ne se cassera pas si elle n'y est pas.
Personnellement, je pense que toute cette partie des "meilleures pratiques" prête à confusion et essaie de vous faire faire un travail que l'API devrait vraiment faire. Étant donné que l'achat est lié à un compte Google et que le Play Store enregistre évidemment ces informations, ils devraient simplement vous les fournir dans les détails de l'achat. L'obtention d'un ID utilisateur correct nécessite des autorisations supplémentaires que vous ne devriez pas avoir à ajouter uniquement pour couvrir les carences de l'API IAB.
Donc, en bref, à moins que vous n'ayez votre propre serveur et une logique d'extension spéciale, n'utilisez pas la charge utile du développeur. Vous devriez être OK, tant que l'API IAB v3 fonctionne (ce qui est, malheureusement, un assez grand "si" à ce stade).
Vous devez transmettre un jeton de chaîne qui aide votre application à identifier l'utilisateur qui a effectué l'achat ...
Si votre application fournit ses propres identifiants et identifiants utilisateur, qui sont différents des comptes Google auxquels le téléphone est connecté, vous devez utiliser la charge utile du développeur pour associer l'achat à l'un de vos comptes qui a effectué l'achat. Sinon, quelqu'un pourrait changer de compte dans votre application et profiter des achats.
par exemple.
Supposons que notre application dispose d'une connexion pour userA et userB. Et le compte Google Android du téléphone est X.
Pour éviter une telle utilisation abusive, nous lierons un achat à un compte. Dans l'exemple ci-dessus, nous définirons la charge utile du développeur sur "userA" lorsque l'utilisateurA effectuera l'achat. Ainsi, lorsque l'utilisateurB se connecte, la charge utile ne correspond pas à l'utilisateur connecté (utilisateurB), et nous ignorerons l'achat. Ainsi, userB ne peut pas bénéficier d'un achat effectué par userA.
Il existe également une autre approche de la gestion de la charge utile des développeurs. Comme Nikolay Elenkov l'a dit, il y a trop de frais généraux pour exiger un ID utilisateur et définir des autorisations supplémentaires pour le profil utilisateur de votre application, ce n'est donc pas une bonne approche. Voyons donc ce que Google dit dans la dernière version de l'exemple d'application TrivialDrive dans les exemples de facturation In-App v3:
- AVERTISSEMENT: générer localement une chaîne aléatoire lors du démarrage d'un achat et la vérifier ici peut sembler une bonne approche, mais cela échouera dans le cas où l'utilisateur achète un article sur un appareil et utilise ensuite votre application sur un autre appareil, car sur l'autre appareil, vous n'aurez pas accès à la chaîne aléatoire que vous avez générée à l'origine.
La chaîne aléatoire n'est donc pas une bonne idée si vous allez vérifier l'article acheté sur un autre appareil, mais ils ne disent toujours pas que ce n'est pas une bonne idée pour vérifier la réponse d'achat. Je dirais - utilisez la charge utile du développeur uniquement pour vérifier l'achat en envoyant une chaîne unique aléatoire, enregistrez-la dans les préférences/base de données et sur la réponse d'achat, vérifiez cette charge utile du développeur. En ce qui concerne l'interrogation de l'inventaire (achats intégrés) au démarrage de l'activité - ne vous embêtez pas à vérifier la charge utile du développeur, car cela pourrait se produire sur un autre appareil où vous n'avez pas cette chaîne unique aléatoire stockée. Voilà comment je le vois.
Cela dépend de la façon dont vous vérifiez le developerPayload
. Il existe deux scénarios: vérification à distance (à l'aide du serveur) et locale (sur l'appareil).
Serveur
Si vous utilisez un serveur pour la vérification de developerPayload
, il peut s'agir d'une chaîne arbitraire qui peut être facilement calculée à la fois sur l'appareil et sur le serveur. Vous devriez être en mesure d'identifier l'utilisateur qui a effectué la demande. En supposant que chaque utilisateur possède le accountId
correspondant, le developerPayload
peut être calculé en combinaison avec purchaseId
(nom SKU) comme ceci:
MD5(purchaseId + accountId)
Périphérique
developerPayload
ne doit pas être un e-mail utilisateur . Le service Google for Work est un bon exemple pour lequel vous ne devez pas utiliser le courrier électronique comme charge utile. Les utilisateurs peuvent modifier leur adresse e-mail associée au compte. La seule chose constante est accountId
. Dans la plupart des cas, l'e-mail sera OK (par exemple, les adresses Gmail sont immuables pour le moment), mais n'oubliez pas de concevoir pour l'avenir.
Plusieurs utilisateurs peuvent utiliser le même appareil, vous devez donc pouvoir distinguer qui est le propriétaire de l'article. Pour la vérification de l'appareil, developerPayload
est une chaîne qui identifie de manière unique l'utilisateur, par exemple:
MD5(purchaseId + accountId)
Conclusion
Généralement, le developerPayload
dans les deux cas peut être juste le accountId
. Pour moi, cela ressemble à la sécurité par l'obscurité . Le MD5 (ou un autre algorithme de hachage) et purchaseId
est juste un moyen de rendre la charge utile plus aléatoire sans montrer explicitement que nous utilisons l'id du compte. L'attaquant devrait décompiler l'application pour vérifier comment elle est calculée. Si l'application est encore mieux obscurcie pour vous.
La charge utile ne fournit aucune sécurité . Il peut être facilement usurpé avec une approche "appareil" et sans aucun effort saisi dans la vérification "serveur". N'oubliez pas d'implémenter la vérification de signature à l'aide de votre clé publique disponible dans la console de compte Google Publisher.
* Un à lire absolument article de blog sur l'utilisation de l'ID de compte au lieu de l'e-mail.
Dans la vidéo Google IO sur IAB v3 donnée par l'auteur de l'échantillon de lecteur trivial lui-même, cela a été brièvement abordé vers la fin de la vidéo. C'est pour empêcher les attaques de rejeu, par exemple l'attaquant renifle le trafic , vole le paquet contenant un achat réussi, puis essaie de rejouer le paquet sur son propre appareil. Si votre application ne vérifie pas l'identité de l'acheteur via la charge utile du développeur (idéalement sur votre serveur) avant de publier le contenu premium (également idéalement depuis votre serveur), l'attaquant réussira. La vérification de la signature ne peut pas le détecter car le paquet est intact.
À mon avis, cette protection semble idéale pour les applications avec une connectivité de compte en ligne comme le choc des clans (la charge utile entre naturellement puisque vous devez identifier les utilisateurs de toute façon), en particulier lorsque le piratage compromet le gameplay multijoueur avec des effets d'une grande portée autres qu'un simple cas localisé de piratage . En revanche, si les hacks côté client sur l'apk peuvent déjà déverrouiller le contenu premium, cette protection n'est pas très utile.
(Si l'attaquant tente d'usurper la charge utile, la vérification de la signature devrait échouer).
J'ai eu du mal avec celui-ci. Puisqu'un compte Google Play ne peut posséder qu'un seul élément "géré", mais peut avoir plusieurs appareils (j'en ai trois), le commentaire ci-dessus de quelqu'un que vous vendez un "par appareil" ne fonctionnera pas ... ils être en mesure de le mettre sur leur premier appareil, et aucun autre jamais ... Si vous achetez une mise à niveau premium, elle devrait fonctionner sur tous vos téléphones/tablettes.
Je méprise l'idée d'obtenir l'adresse e-mail de l'utilisateur, mais je n'ai vraiment trouvé aucune autre méthode fiable. J'attrape donc le premier compte qui correspond à "google.com" dans la liste des comptes (oui, une autorisation à ajouter à votre manifeste), puis le hache immédiatement pour qu'il ne soit plus utilisable comme adresse e-mail mais fournit un "assez unique" " jeton. C'est ce que j'envoie en tant que développeur Payload. Étant donné que la plupart des gens activent leur appareil avec leur identifiant Google Play, il y a de bonnes chances que les trois appareils obtiennent le même jeton (en utilisant le même algorithme de hachage sur chaque appareil).
Il fonctionne même sur KitKat avec plusieurs "utilisateurs". (Mon ID de développeur est sur un utilisateur, mon ID de test sur un autre et chaque utilisateur dans son propre bac à sable).
Je l'ai testé sur six appareils avec un total de 3 utilisateurs et les appareils de chaque utilisateur ont retourné le même hachage, et les différents utilisateurs ont tous des hachages distincts, satisfaisant aux directives.
À aucun moment, je ne stocke l'adresse e-mail de l'utilisateur, elle est transmise directement du code pour obtenir les noms de compte à la fonction de hachage et seul le hachage est enregistré dans le tas.
Il existe probablement encore une meilleure solution qui respecte encore plus la confidentialité des utilisateurs, mais jusqu'à présent, je ne l'ai pas trouvée. Je mettrai une description très claire de la façon dont j'utilise l'adresse e-mail des utilisateurs dans ma politique de confidentialité une fois l'application publiée.
Mise à jour de fin 2018: la bibliothèque de facturation officielle de Google Play n'expose pas intentionnellement le developerPayload
. De ici :
Le champ developerPayload est un champ hérité, conservé pour maintenir la compatibilité avec les anciennes implémentations, mais comme mentionné sur la page d'achat de produits de facturation intégrés ( https://developer.Android.com/training/in-app-billing /purchase-iab-products.html ), ce champ n'est pas toujours disponible lorsque vous effectuez des tâches liées à la facturation via l'application. Et comme la bibliothèque a été conçue pour représenter le modèle de développement le plus récent, nous avons décidé de ne pas prendre en charge developerPayload dans notre implémentation et nous n'avons pas l'intention d'inclure ce champ dans la bibliothèque.
Si vous comptez sur une implémentation importante de votre logique de facturation dans l'application sur developerPayload, nous vous recommandons de modifier cette approche, car ce champ sera obsolète à un moment donné (ou bientôt). L'approche recommandée consiste à utiliser votre propre backend pour valider et suivre les détails importants concernant vos commandes. Pour plus de détails, consultez la page Sécurité et conception ( https://developer.Android.com/google/play/billing/billing_best_practices.html ).
Cela répond souvent à une définition de produit (votre application). Par exemple pour le cas des abonnements. Le même utilisateur pourra-t-il utiliser l'abonnement sur tous les appareils dont il dispose? Si la réponse est oui. Nous n'avons pas vérifié la charge utile.
Pour les consommables. Supposons qu'un achat dans votre application vous donne 10 pièces virtuelles. L'utilisateur pourra-t-il utiliser ces pièces sur différents appareils? 4 sur un appareil et 6 sur un autre? Si nous voulons travailler uniquement sur l'appareil qui a fait l'achat, nous devons vérifier la charge utile par exemple avec une chaîne auto-générée et stockée localement.
Sur la base de ces questions, nous devons décider comment mettre en œuvre la vérification de la charge utile.
Cordialement
Santiago