Warum ist es wichtig, die Entwickler-Payload mit In-App-Abrechnung festzulegen?


78

Ich verwende Version 3 der In-App-Abrechnungs-API. Ich habe einen einzelnen, verwalteten, nicht verbrauchbaren Artikel. Ich habe diese Funktion noch nicht in meiner App veröffentlicht, daher möchte ich vor dem Kauf über den Inhalt der Kaufnutzlast entscheiden.

Aus "Best Practices für Sicherheit" :

Legen Sie die Entwickler-Payload-Zeichenfolge fest, wenn Sie Kaufanfragen stellen

Mit der In-App-Abrechnungs-API der Version 3 können Sie beim Senden Ihrer Kaufanfrage an Google Play ein Zeichenfolgentoken für Entwickler-Nutzdaten einfügen. In der Regel wird dies verwendet, um ein Zeichenfolgentoken zu übergeben, das diese Kaufanforderung eindeutig identifiziert. Wenn Sie einen Zeichenfolgenwert angeben, gibt Google Play diese Zeichenfolge zusammen mit der Kaufantwort zurück. Wenn Sie anschließend Fragen zu diesem Kauf stellen, gibt Google Play diese Zeichenfolge zusammen mit den Kaufdetails zurück.

Sie sollten ein Zeichenfolgentoken übergeben, mit dem Ihre Anwendung den Benutzer identifizieren kann, der den Kauf getätigt hat, damit Sie später überprüfen können, ob dies ein legitimer Kauf dieses Benutzers ist. Für Verbrauchsartikel können Sie eine zufällig generierte Zeichenfolge verwenden. Für nicht Verbrauchsartikel sollten Sie jedoch eine Zeichenfolge verwenden, die den Benutzer eindeutig identifiziert.

Wenn Sie die Antwort von Google Play zurückerhalten, stellen Sie sicher, dass die Payload-Zeichenfolge des Entwicklers mit dem Token übereinstimmt, das Sie zuvor mit der Kaufanfrage gesendet haben. Als weitere Sicherheitsmaßnahme sollten Sie die Überprüfung auf Ihrem eigenen sicheren Server durchführen.

Zu Recht oder zu Unrecht habe ich beschlossen, keine "weiteren Sicherheitsvorkehrungen" zu treffen, um einen Server für die Kaufüberprüfung einzurichten. Und ich speichere keine eigenen Aufzeichnungen über den Kauf - ich rufe immer die Abrechnungs-API auf. Gibt es wirklich einen Grund für mich, diese Nutzlastüberprüfung durchzuführen? Die Überprüfungs-API selbst überprüft mit Sicherheit die Identität eines Benutzers, bevor ein Artikel als gekauft gemeldet wird. Wenn ein Angreifer ein Gerät (entweder die App oder die Google Play-API) kompromittiert hat, sehe ich keinen Vorteil darin, eine zusätzliche Überprüfung durchzuführen die Identität des Benutzers auf dem Gerät, wo es leicht umgangen werden kann. Oder gibt es einen Grund dafür, an den ich nicht denke?

Antworten:


70

Wenn Sie keine Aufzeichnungen führen, können Sie nicht überprüfen, ob Sie das erhalten haben, was Sie gesendet haben. Wenn Sie also der Nutzlast des Entwicklers etwas hinzufügen, können Sie entweder darauf vertrauen, dass es legitim ist (was eine vernünftige Annahme ist, wenn die Signatur überprüft wird), oder es nicht vollständig vertrauen und es nur als Referenz verwenden, jedoch nicht zur Überprüfung des Lizenzstatus usw. Wenn Sie beispielsweise die Benutzer-E-Mail speichern, können Sie den Wert verwenden, anstatt sie zur erneuten Eingabe aufzufordern. Dies ist etwas benutzerfreundlicher, aber Ihre App wird nicht beschädigt, wenn sie nicht vorhanden ist.

Persönlich denke ich, dass dieser ganze Teil der „Best Practices“ verwirrend ist und versucht, Sie dazu zu bringen, die Arbeit zu erledigen, die die API wirklich tun sollte. Da der Kauf an ein Google-Konto gebunden ist und der Play Store diese Informationen offensichtlich speichert, sollten Sie dies nur in den Kaufdetails angeben. Um eine ordnungsgemäße Benutzer-ID zu erhalten, sind zusätzliche Berechtigungen erforderlich, die Sie nicht hinzufügen müssen, um die Mängel der IAB-API zu beheben.

Kurz gesagt, verwenden Sie nur die Entwickler-Payload, es sei denn, Sie haben einen eigenen Server und eine spezielle Add-On-Logik. Sie sollten in Ordnung sein, solange die IAB v3-API funktioniert (was zu diesem Zeitpunkt leider ein ziemlich großes "Wenn" ist).


4
Fühlen Sie sich eineinhalb Jahre nach Ihrer ersten Antwort immer noch genauso? Ich bin mir nicht sicher, ob seitdem hinter den Kulissen Änderungen an der API vorgenommen wurden ... und ich kann nicht sagen, dass ich derzeit der Dokumentation von Google vertraue.
Alex Lockwood

6
Ich denke immer noch, dass IAP die Sicherheit transparent bereitstellen sollte und die Verwendung der Entwickler-Payload nicht erforderlich sein sollte. Vielleicht tut es das jetzt, aber ich habe es eine ganze Weile nicht mehr angeschaut (oder sogar benutzt). Meine Apps verwenden immer noch den ursprünglichen IAP, hauptsächlich, weil sie Kaufbenachrichtigungen bereitstellen, die ich auf meinem eigenen Server verfolgen kann, was der "neue" IAP nicht tut.
Nikolay Elenkov

2
Ich denke, es ist natürlich notwendig, auf dem Server zu validieren, was V3 ziemlich schwierig macht, wenn Sie keinen Benutzer haben, der mit einer Art Konto-ID (Ihrer eigenen oder einer 3-Parteien-Partei) "angemeldet" ist. Vielleicht haben Sie API V2 ausprobiert, ABER ... Wir planen, den In-App-Abrechnungsdienst Version 2 am 27. Januar 2015 zu deaktivieren. Danach können Benutzer keine In-App-Artikel und Abonnements mehr über die Version 2-API erwerben. Wir empfehlen Ihnen dringend, Ihre Apps bis November 2014 auf die Version 3-API zu migrieren, damit Benutzer ausreichend Zeit haben, ihre Apps auf die neue Version zu aktualisieren.
Inteist

@ Nikolay Elenkov, was ist dein Vorschlag für jetzt? Ich stimme Ihnen zu, dass diese bewährte Methode auf Googles Seite stehen sollte.
Stuckedoverflow

30

Sie sollten ein Zeichenfolgentoken übergeben, mit dem Ihre Anwendung den Benutzer identifizieren kann, der den Kauf getätigt hat ...

Wenn Ihre Anwendung eine eigene Benutzeranmeldung und -identität bereitstellt, die sich von den Google-Konten unterscheidet, mit denen das Telefon verbunden ist, müssen Sie die Nutzdaten des Entwicklers verwenden, um den Kauf an eines Ihrer Konten anzuhängen, die den Kauf getätigt haben. Andernfalls könnte jemand das Konto in Ihrer App wechseln und von gekauften Inhalten profitieren.

z.B

Angenommen, unsere App hat ein Login für BenutzerA und BenutzerB. Und das Android-Google-Konto des Telefons ist X.

  1. userA meldet sich bei unserer App an und erwirbt eine lebenslange Mitgliedschaft. Die Kaufdaten werden unter Google-Konto X gespeichert.
  2. Benutzer A meldet sich ab und Benutzer B meldet sich bei unserer App an. Jetzt erhält UserB auch den Vorteil einer lebenslangen Mitgliedschaft, da das Android-Google-Konto immer noch X ist.

Um einen solchen Missbrauch zu vermeiden, binden wir einen Kauf an ein Konto. Im obigen Beispiel setzen wir die Entwicklernutzlast als "BenutzerA", wenn BenutzerA den Kauf tätigt. Wenn sich Benutzer B anmeldet, stimmt die Nutzlast nicht mit dem angemeldeten Benutzer (Benutzer B) überein, und wir ignorieren den Kauf. Daher kann Benutzer B keine Vorteile aus einem von Benutzer A getätigten Kauf ziehen.


Gute Antwort. Aber was ist, wenn wir keinen Anmeldemechanismus haben? Dann nutzen wir die Nutzlast einfach nicht?
Tasomaniac

7
Nachdem ich mir wegen dieses Problems mit der Benutzer-ID eine Weile am Kopf gekratzt habe, denke ich, dass das, worauf Sie hinweisen, möglicherweise die tatsächliche Absicht der Nutzlastzeichenfolge ist. Es wird in der Google-Dokumentation einfach sehr schlecht erklärt.
Pooks

Also, Benutzer Google Mail wird den Trick tun und kann verwendet werden alsdeveloperPaylod
Sami Eltamawy

3
@keybee Das ist genau der Punkt. In dem von Ihnen erwähnten Fall müssen wir, wenn wir keine Dev-Payload verwenden, UserB Premium-Funktionen bereitstellen, wenn die In-App-Abrechnung "Sie haben diesen Artikel bereits" zurückgibt (da wir nicht wissen können, ob UserB das Produkt erstellt hat) der Kauf an erster Stelle). Wenn Benutzer B auf demselben Gerät kaufen muss, auf dem Benutzer A gekauft hat, muss Benutzer B zu einem eigenen Google-Konto wechseln und den Kauf tätigen.
Therealsachin

3
@therealsachin Ich erhalte dies, aber wenn ich auf meinem Server nachschaue und Benutzer B blockiere, hat er keine Möglichkeit, eine Mitgliedschaft bei einem anderen Konto zu erwerben, da Google Play zuerst mit dem primären Konto prüft, sodass 2 Benutzer auf demselben Gerät dies nicht tun Arbeit. Dies kann jedoch nur dann ein Problem sein, wenn userA aus irgendeinem Grund ein weiteres Konto benötigt. Er wird niemals in der Lage sein, einen weiteren Einkauf mit demselben Google-Konto zu tätigen, auch nicht mit unterschiedlichen Nutzdaten. - Der Idealfall wäre für mich, dass ich im Falle einer neuen Nutzlast wieder ein Abonnement kaufen kann.
Keybee

21

Es gibt auch einen anderen Ansatz für die Verarbeitung von Nutzdaten für Entwickler. Wie Nikolay Elenkov sagte, ist es zu viel Aufwand, eine Benutzer-ID zu benötigen und zusätzliche Berechtigungen für das Benutzerprofil für Ihre App festzulegen. Dies ist also kein guter Ansatz. Sehen wir uns also an, was Google in der neuesten Version der TrivialDrive-Beispiel-App in In-App Billing v3-Beispielen sagt:

  • WARNUNG: Das lokale Generieren einer zufälligen Zeichenfolge beim Starten eines Kaufs und das Überprüfen dieser Zeichenfolge scheint ein guter Ansatz zu sein. Dies schlägt jedoch fehl, wenn der Benutzer einen Artikel auf einem Gerät kauft und Ihre App dann auf einem anderen Gerät verwendet Auf dem anderen Gerät haben Sie keinen Zugriff auf die ursprünglich generierte Zufallszeichenfolge.

Die zufällige Zeichenfolge ist also keine gute Idee, wenn Sie den gekauften Artikel auf einem anderen Gerät überprüfen möchten. Sie sagen jedoch nicht, dass dies keine gute Idee für die Überprüfung der Kaufantwort ist. Ich würde sagen - verwenden Sie die Entwickler-Nutzdaten nur zur Überprüfung des Kaufs, indem Sie eine zufällige eindeutige Zeichenfolge senden, speichern Sie sie in den Einstellungen / in der Datenbank und überprüfen Sie diese Entwickler-Nutzdaten in der Kaufantwort. Wenn Sie das Inventar (In-App-Käufe) beim Start der Aktivität abfragen möchten, überprüfen Sie nicht die Nutzdaten der Entwickler, da dies auf einem anderen Gerät passieren kann, auf dem diese zufällige eindeutige Zeichenfolge nicht gespeichert ist. So sehe ich das.


4
Danke, ich implementiere diesen Ansatz (und habe ihn positiv bewertet :), weil es sich nach einem guten Kompromiss anhört, aber ich denke, es gibt ein Problem mit der beschriebenen Logik. Wenn die Nutzlastüberprüfung beim Kauf fehlschlägt, glaubt Google Play immer noch, dass Sie den Artikel besitzen. Sie müssen also nur die App neu starten, das Inventar wird gelesen, und ohne Nutzlastüberprüfung erhalten Sie den Artikel. Eine Lösung besteht darin, den Artikel zu konsumieren, wenn die Überprüfung der Nutzlast beim Kauf fehlschlägt. Dann haben Sie jedoch das Geld des Benutzers genommen, was zu unangenehmen E-Mails führen kann, falls dies jemals unschuldig geschieht ...
Georgie

Wenn Sie die Geräte-ID als Nutzlast angeben, können Sie den Verkauf "pro Gerätelizenz" implementieren. Wenn der Benutzer den Kauf auf einem Gerät getätigt hat, kann er ihn nicht auf einem anderen Gerät verwenden. Dies kann beim Verkauf der Vollversion einer Anwendung hilfreich sein, z. Antivirus.
Bancer

Lesen Sie den Kommentar zu @Georgie. Andernfalls werden Sie viel Zeit damit verbringen, herauszufinden, dass dies eine schlechte Idee ist.
Halvor Holsten Strand

16

Es hängt davon ab, wie Sie das überprüfen developerPayload. Es gibt zwei Szenarien: Remote-Überprüfung (mithilfe des Servers) und lokale Überprüfung (auf dem Gerät).

Server

Wenn Sie einen Server zur developerPayloadÜberprüfung verwenden, kann es sich um eine beliebige Zeichenfolge handeln, die sowohl auf dem Gerät als auch auf dem Server leicht berechnet werden kann. Sie sollten in der Lage sein, den Benutzer zu identifizieren, der die Anforderung ausgeführt hat. Unter der Annahme, dass jeder Benutzer das entsprechende hat accountId, developerPayloadkann das als Kombination mit purchaseId(SKU-Name) wie folgt berechnet werden :

MD5(purchaseId + accountId)


Gerät

developerPayload sollte keine Benutzer-E-Mail sein . Ein gutes Beispiel dafür, warum Sie E-Mail nicht als Nutzlast verwenden sollten, ist der Google for Work-Dienst. Benutzer können ihre mit dem Konto verknüpfte E-Mail-Adresse ändern. Die einzige Konstante ist accountId. In den meisten Fällen sind E-Mails in Ordnung (z. B. sind Google Mail-Adressen derzeit unveränderlich), aber denken Sie daran, sie für die Zukunft zu entwerfen.

Möglicherweise verwenden mehrere Benutzer dasselbe Gerät. Sie müssen also unterscheiden können, wer der Eigentümer des Elements ist. Bei der Geräteüberprüfung developerPayloadhandelt es sich um eine Zeichenfolge, die den Benutzer eindeutig identifiziert, z.

MD5(purchaseId + accountId)


Fazit

Im Allgemeinen kann das developerPayloadin beiden Fällen nur das sein accountId. Für mich sieht es nach Sicherheit durch Dunkelheit aus . Der MD5 (oder ein anderer Hashing-Algorithmus) purchaseIdist nur eine Möglichkeit, die Nutzdaten zufälliger zu gestalten, ohne explizit zu zeigen, dass wir die ID des Kontos verwenden. Der Angreifer müsste die App dekompilieren, um zu überprüfen, wie sie berechnet wird. Wenn die App für Sie noch besser verschleiert ist.

Die Nutzlast bietet keine Sicherheit . Es kann leicht mit dem "Geräte" -Ansatz gefälscht werden und ohne Aufwand bei der "Server" -Prüfung. Denken Sie daran, die Signaturprüfung mit Ihrem öffentlichen Schlüssel zu implementieren, der in der Google Publisher-Kontokonsole verfügbar ist.

* Ein unverzichtbarer Blog-Beitrag über die Verwendung der Konto-ID anstelle von E-Mail.


1
Was ist accountId? & Wie bekomme ich die accountId? Ist es möglich, dieselbe Konto-ID für mehrere Google Play-Konten (während Sie das Konto wechseln) zu pflegen, um weitere Informationen zu erhalten ? github.com/googlesamples/android-play-billing/issues/2
Sarath Kumar

5

In dem Google IO-Video über IAB v3, das der Autor des Trivial Drive-Beispiels selbst gegeben hat, wurde dies gegen Ende des Videos kurz angesprochen. Dies dient dazu, Wiederholungsangriffe zu verhindern, z. B. wenn der Angreifer den Datenverkehr abhört, das Paket mit einem erfolgreichen Kauf stiehlt und dann versucht, das Paket auf seinem eigenen Gerät wiederzugeben. Wenn Ihre App die Identität des Käufers nicht über die Entwicklungsnutzlast (idealerweise auf Ihrem Server) überprüft, bevor Sie den Premium-Inhalt (idealerweise auch von Ihrem Server) freigeben, ist der Angreifer erfolgreich. Die Signaturüberprüfung kann dies nicht erkennen, da das Paket intakt ist.

Meiner Meinung nach scheint dieser Schutz ideal für Apps mit Online-Konto-Konnektivität wie Clash of Clans zu sein (Nutzlast kommt natürlich herein, da Sie ohnehin Benutzer identifizieren müssen), insbesondere wenn Hacking das Multiplayer-Gameplay mit weitreichenden Effekten außer einem einfachen lokalisierten Fall von Piraterie beeinträchtigt . Im Gegensatz dazu ist dieser Schutz nicht sehr nützlich, wenn clientseitige Hacks auf der apk den Premium-Inhalt bereits entsperren können.

(Wenn der Angreifer versucht, die Nutzdaten zu fälschen, sollte die Signaturüberprüfung fehlschlagen.)


Kann ich Firebase mit Google-Anmeldung und Echtzeitdatenbank mit den Feldern account_id und developer_payload verwenden, die in der Echtzeit-Datenbank gespeichert sind und diese überprüfen, während der Benutzer die App öffnet (mit zusätzlicher gemeinsamer Präferenz für die Offline-Funktion)?
Dhaval Jotaniya

5

Ende 2018 Update: Die offizielle Google Play Billing Library macht das absichtlich nicht verfügbar developerPayload. Von hier aus :

Das Feld "DeveloperPayload" ist ein Legacy-Feld, das beibehalten wird, um die Kompatibilität mit alten Implementierungen zu gewährleisten. Wie auf der Seite "In-App-Abrechnungsprodukte kaufen" ( https://developer.android.com/training/in-app-billing/purchase-iab) erwähnt -products.html ) ist dieses Feld nicht immer verfügbar, wenn Aufgaben im Zusammenhang mit der In-App-Abrechnung ausgeführt werden. Und da die Bibliothek so konzipiert wurde, dass sie das aktuellste Entwicklungsmodell darstellt, haben wir beschlossen, developerPayload in unserer Implementierung nicht zu unterstützen, und wir haben nicht vor, dieses Feld in die Bibliothek aufzunehmen.

Wenn Sie eine wichtige Implementierung Ihrer In-App-Abrechnungslogik auf DeveloperPayload verlassen, empfehlen wir Ihnen, diesen Ansatz zu ändern, da dieses Feld irgendwann (oder in Kürze) veraltet sein wird. Der empfohlene Ansatz besteht darin, Ihr eigenes Backend zu verwenden, um wichtige Details Ihrer Bestellungen zu validieren und zu verfolgen. Weitere Informationen finden Sie auf der Seite Sicherheit und Design ( https://developer.android.com/google/play/billing/billing_best_practices.html ).


Damit ist die Frage für mich
geklärt

3

Ich kämpfte mit diesem. Da ein Google Play-Konto nur eines der "verwalteten" Elemente besitzen kann, aber mehrere Geräte haben kann (ich habe drei), funktioniert der obige Kommentar von jemandem, dass Sie ein "pro Gerät" verkaufen, nicht Sie können es auf das erste Gerät installieren und auf kein anderes ... Wenn Sie ein Premium-Upgrade kaufen, sollte es auf allen Ihren Handys / Tablets funktionieren.

Ich verachte den Gedanken, die E-Mail-Adresse des Benutzers zu erhalten, aber ich habe wirklich keine andere zuverlässige Methode gefunden. Also greife ich zum ersten Konto, das mit "google.com" in der Kontenliste übereinstimmt (yep, eine Berechtigung zum Hinzufügen zu Ihrem Manifest), und hashe es dann sofort, damit es nicht mehr als E-Mail-Adresse verwendet werden kann, sondern eine "eindeutige" Adresse enthält " Zeichen. Das sende ich als Developer Payload. Da die meisten Leute ihr Gerät mit ihrer Google Play-ID aktivieren, gibt es eine gute Chance, dass alle drei Geräte das gleiche Token erhalten (mit dem gleichen Hash-Algorithmus auf jedem Gerät).

Es funktioniert sogar auf KitKat mit mehreren "Benutzern". (Meine Entwickler-ID befindet sich bei einem Benutzer, meine Test-ID bei einem anderen Benutzer und jeder Benutzer in seiner eigenen Sandbox.)

Ich habe es auf sechs Geräten mit insgesamt 3 Benutzern getestet, und die Geräte jedes Benutzers haben denselben Hash zurückgegeben, und die verschiedenen Benutzer haben alle unterschiedliche Hashes, die den Richtlinien entsprechen.

Zu keinem Zeitpunkt speichere ich die E-Mail-Adresse des Benutzers. Sie wird direkt aus dem Code übergeben, um die Kontonamen an die Hash-Funktion zu senden, und nur der Hash wird auf dem Heap gespeichert.

Es gibt wahrscheinlich noch eine bessere Lösung, die die Privatsphäre der Benutzer noch mehr respektiert, aber bisher habe ich sie nicht gefunden. Ich werde eine sehr klare Beschreibung der Verwendung der E-Mail-Adresse des Benutzers in meine Datenschutzrichtlinie aufnehmen, sobald die App veröffentlicht ist.


6
Das ist alles großartig, erfordert aber ACCOUNTS-Berechtigungen, was hier unnötig übertrieben ist. Warum um alles in der Welt konnte Google keinen Hash des Kontos erstellen, mit dem ein Kauf zugänglich gemacht wurde ... Das wäre die sauberste Lösung dafür. Jetzt ist es einfach "kaputt".
Inteist

Ich habe etwas Ähnliches gemacht, aber jetzt, bei Android 6, muss die App den Benutzer bitten, die Kontaktberechtigung zu erteilen, was für den Benutzer eine schreckliche Erfahrung ist, wenn er die App zum ersten Mal startet. Vielleicht implementiere ich stattdessen eine Option zum Wiederherstellen von Käufen. Wenn Sie sich das erste google.com-Konto schnappen, können Probleme auftreten, wenn der Nutzer mehr als ein Konto auf seinem Telefon hat und Konten neu anordnet (z. B. Konto A löschen und später erneut hinzufügen, aber jetzt ist es nicht das erste Konto). . Es kommt vor, wenn auch zugegebenermaßen selten. Dann müssen Sie auch die Kontoauswahl verwenden! Yuch!
Snark

1

Dies reagiert häufig auf eine Produktdefinition (Ihre Anwendung). Zum Beispiel für Abonnements. Kann derselbe Benutzer das Abonnement auf allen Geräten verwenden, über die er verfügt? Wenn die Antwort ja ist. Wir haben die Nutzlast nicht überprüft.

Für Verbrauchsmaterialien. Angenommen, ein Kauf in Ihrer Anwendung ergibt 10 virtuelle Münzen. Kann der Benutzer diese Münzen auf verschiedenen Geräten verwenden? 4 auf einem Gerät und 6 auf einem anderen? Wenn wir nur auf dem Gerät arbeiten möchten, das den Kauf getätigt hat, müssen wir die Nutzdaten beispielsweise mit einer selbst generierten Zeichenfolge überprüfen und lokal speichern.

Basierend auf diesen Fragen müssen wir entscheiden, wie die Nutzlastprüfung implementiert werden soll.

Grüße

Santiago

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.