web-dev-qa-db-ja.com

アプリ内課金で開発者のペイロードを設定することが重要なのはなぜですか?

アプリ内課金APIのバージョン3を使用しています。管理された単一の非消耗品があります。私はまだアプリでこの機能をリリースしていないので、購入する前に購入ペイロードの内容を決定したいと思います。

"セキュリティのベストプラクティス" から:

購入リクエストを行うときに開発者のペイロード文字列を設定します

アプリ内課金バージョン3 APIを使用すると、購入リクエストをGoogle Playに送信するときに「開発者ペイロード」文字列トークンを含めることができます。通常、これは、この購入リクエストを一意に識別する文字列トークンを渡すために使用されます。文字列値を指定すると、Google Playは購入応答とともにこの文字列を返します。その後、この購入についてクエリを行うと、Google Playはこの文字列と購入の詳細を返します。

アプリケーションが購入したユーザーを識別するのに役立つ文字列トークンを渡す必要があります。これにより、そのユーザーによる正当な購入であることを後で確認できます。消耗品の場合は、ランダムに生成された文字列を使用できますが、非消耗品の場合は、ユーザーを一意に識別する文字列を使用する必要があります。

Google Playから応答を受け取ったら、開発者のペイロード文字列が以前に購入リクエストで送信したトークンと一致することを確認してください。さらにセキュリティ対策として、安全なサーバーで検証を実行する必要があります。

間違いなく、私は購入確認を実行するためにサーバーをセットアップする「さらなるセキュリティ対策」をとることを決定しましたnot。そして、私は自分の購入記録を保存しません-私は常に請求APIを呼び出します。このペイロードの検証を行う理由は本当にありますか?検証API自体は、購入したアイテムを報告する前にユーザーのIDを確実に検証します。攻撃者がデバイス(アプリまたはGoogle Play APIのいずれか)を侵害した場合、追加チェックを行うメリットはありません簡単に回避できるデバイス上のユーザーの識別。それとも、私が考えていないことをこれを行う理由はありますか?

74
Travis

記録を残さないと、受け取ったものが送信したものであることを確認する方法がありません。したがって、開発者のペイロードに何かを追加する場合、それが正当であることを信頼できます(署名が検証する場合は合理的な仮定です)、または完全に信頼せず、参照のみを使用しますが、ライセンスステータスの検証などには使用できませんたとえば、ユーザーのメールを保存する場合、値を入力するように求める代わりに値を使用することができます。

個人的には、この「ベストプラクティス」の部分全体が混乱を招き、APIが実際に行うべき作業を実行しようとしていると思います。購入はGoogleアカウントに関連付けられており、Playストアは明らかにこの情報を保存するので、購入の詳細でこれを提供するだけです。適切なユーザーIDを取得するには、IAB APIの不備を補うためだけに追加する必要のない追加の権限が必要です。

つまり、要するに、独自のサーバーと特別なアドオンロジックがない限り、開発者ペイロードを使用しないでください。 IAB v3 APIが機能する限り、問題ないはずです(残念ながら、この時点では非常に大きな「if」です)。

69
Nikolay Elenkov

アプリケーションが購入したユーザーを識別するのに役立つ文字列トークンを渡す必要があります...

アプリケーションが独自のユーザーログインとIDを提供し、それが電話が接続されているGoogleアカウントと異なる場合、開発者ペイロードを使用して、購入を行ったアカウントの1つに購入を添付する必要があります。そうしないと、誰かがアプリのアカウントを切り替えて、購入したものの恩恵を受けることができます。

例えば.

アプリにuserAとuserBのログインがあるとします。そして、電話のAndroid googleアカウントはXです。

  1. userA、私たちのアプリにログインし、ライフメンバーシップを購入します。購入の詳細は、GoogleアカウントXに保存されます。
  2. userAがログアウトし、userBがアプリにログインします。現在、userBはAndroid googleアカウントはまだXです。

このような誤用を避けるため、購入をアカウントに結び付けます。上記の例では、userAが購入するときに開発者のペイロードを「userA」として設定します。そのため、userBがサインインすると、ペイロードはサインインしたユーザー(userB)と一致しなくなり、購入は無視されます。したがって、userBはuserAが行った購入の恩恵を受けることができません。

26
therealsachin

開発者のペイロード処理に対する別のアプローチもあります。 Nikolay Elenkovが述べたように、ユーザーIDを要求し、アプリにユーザープロファイルの追加のアクセス許可を設定するのはオーバーヘッドが大きすぎるため、これは良いアプローチではありません。 In-App Billing v3サンプルのTrivialDriveサンプルアプリの最新バージョンでGoogleが言っていることを見てみましょう。

  • 警告:ここで購入を開始し、ここで確認するときにランダム文字列をローカルで生成することは良いアプローチのように思えるかもしれませんが、ユーザーが1つのデバイスでアイテムを購入し、別のデバイスでアプリを使用する場合、これは失敗します他のデバイスでは、最初に生成したランダムな文字列にアクセスできません。

そのため、別のデバイスで購入したアイテムを検証する場合、ランダムな文字列はお勧めできませんが、購入レスポンスを検証するためにこれは良いアイデアではないとは言われていません。私は言う-ランダムな一意の文字列を送信して購入を確認するためにのみ開発者ペイロードを使用し、それをプリファレンス/データベースに保存し、購入応答でこの開発者ペイロードを確認します。アクティビティ開始時のインベントリ(アプリ内購入)のクエリに関しては、開発者のペイロードを確認する必要はありません。ランダムな一意の文字列が保存されていない別のデバイスで発生する可能性があります。それは私がそれを見る方法です。

21
Dokker

developerPayloadの検証方法によって異なります。 2つのシナリオがあります:リモート検証(サーバーを使用)とローカル(デバイス上)。

サーバー

developerPayload検証にサーバーを使用している場合、デバイスとサーバーの両方で簡単に計算できる任意の文字列にすることができます。リクエストを実行したユーザーを特定できるはずです。すべてのユーザーに対応するaccountIdがあるとすると、developerPayloadpurchaseId(SKU名)との組み合わせとして次のように計算されます。

MD5(purchaseId + accountId)


デバイス

developerPayloadユーザーのメールアドレスではありません。ペイロードとしてメールを使用しない理由の良い例は、Google for Workサービスです。ユーザーは、アカウントに関連付けられているメールを変更できます。唯一の定数はaccountIdです。ほとんどの場合、メールは問題ありません(たとえば、Gmailアドレスは現時点では不変です)が、将来のために設計することを忘れないでください。

複数のユーザーが同じデバイスを使用する可能性があるため、アイテムの所有者を区別できる必要があります。デバイス検証の場合、developerPayloadはユーザーを一意に識別する文字列です。例:

MD5(purchaseId + accountId)


結論

通常、両方の場合のdeveloperPayloadは、単にaccountIdになります。私にとっては、 セキュリティを介したセキュリティ のように見えます。 MD5(または他のハッシュアルゴリズム)とpurchaseIdは、アカウントのIDを使用していることを明示的に示すことなく、ペイロードをよりランダムにする方法です。攻撃者はアプリを逆コンパイルして、計算方法を確認する必要があります。アプリがさらに難読化されている場合。

ペイロードはセキュリティを提供しません。 「デバイス」アプローチで簡単になりすまし、「サーバー」チェックで手間をかけることはありません。 Googleサイト運営者アカウントコンソールで利用可能な公開鍵を使用して、署名の確認を忘れずに実装してください。

* A 必読 メールではなくアカウントIDの使用に関するブログ投稿。

15
tomrozb

Google IO些細なドライブサンプルの著者自身が与えたIAB v3についてのビデオでは、これはビデオの終わりに向けて簡単に対処されました。たとえば、攻撃者がトラフィックを盗聴するのを防ぐためです、購入に成功したパケットを盗み、自分のデバイスでパケットを再生しようとします。アプリがプレミアムコンテンツをリリースする前に(理想的にはサーバー上で)devペイロードを介して購入者のIDをチェックしない場合サーバーから)、攻撃者は成功しますが、パケットが無傷であるため、署名検証はこれを検出できません。

私の意見では、この保護は一族の衝突のようなオンラインアカウント接続を備えたアプリに最適であると思われます(とにかくユーザーを特定する必要があるため、ペイロードは自然に発生します)。 。対照的に、apkでクライアント側のハッキングが既にプレミアムコンテンツのロックを解除できる場合、この保護はあまり役に立ちません。

(攻撃者がペイロードを偽装しようとすると、署名の検証は失敗します)。

5
Kevin Lee

私はこれに苦労しました。 Google Playアカウントは「管理」アイテムの1つしか所有できませんが、複数のデバイス(私は3つ持っています)を持つことができるため、「デバイスごと」を販売しているという誰かからの上記のコメントは機能しません...それを最初のデバイスに搭載できるようになり、他のデバイスには搭載できなくなります。

私はユーザーのメールアドレスを取得するという概念を軽んじていますが、他の信頼できる方法は実際には見つかりませんでした。そこで、アカウントリストの「google.com」に一致する最初のアカウント(そう、マニフェストに追加する許可)を取得し、すぐにハッシュ化して、メールアドレスとしては使用できないようにしますが、 「トークン。それが開発者ペイロードとして送信するものです。ほとんどの人はGoogle Play IDでデバイスをアクティベートするので、3つのデバイスすべてが同じトークンを取得するのに良いショットがあります(各デバイスで同じハッシュアルゴリズムを使用)。

複数の「ユーザー」がいるキットカットでも動作します。 (私の開発者IDはあるユーザーにあり、私のテストIDは別のユーザーにあり、各ユーザーは自分のサンドボックスにあります)。

合計3人のユーザーを持つ6台のデバイスでテストしましたが、各ユーザーのデバイスは同じハッシュを返し、異なるユーザーはすべて個別のハッシュを持ち、ガイドラインを満たしています。

ユーザーのメールアドレスを保存することはありません。アカウント名を取得するためにコードから直接渡され、ハッシュ関数に渡され、ハッシュのみがヒープに保存されます。

おそらく、ユーザーのプライバシーをより尊重するより良いソリューションがまだそこにありますが、今のところ私はそれを見つけていません。アプリが公開されたら、プライバシーポリシーにユーザーのメールアドレスの使用方法を非常に明確に説明します。

3
Tkraindesigns

2018年後半の更新:公式のGoogle Play請求ライブラリは、意図的にdeveloperPayloadを公開しません。 ここ から:

フィールドdeveloperPayloadはレガシーフィールドであり、古い実装との互換性を維持するために保持されていますが、アプリ内課金製品の購入ページ( https://developer.Android.com/training/in-app-billing /purchase-iab-products.html )、アプリ内課金に関連するタスクを完了するときにこのフィールドが常に使用できるとは限りません。また、ライブラリは最新の開発モデルを表すように設計されているため、実装でdeveloperPayloadをサポートしないことにし、このフィールドをライブラリに含める予定はありません。

DeveloperPayloadでアプリ内課金ロジックの重要な実装に依存している場合は、このアプローチを変更することをお勧めします。このフィールドは、ある時点(またはすぐ)で非推奨になるためです。推奨されるアプローチは、独自のバックエンドを使用して、注文に関する重要な詳細を検証および追跡することです。詳細については、セキュリティと設計ページを確認してください( https://developer.Android.com/google/play/billing/billing_best_practices.html )。

3
Chris Lacy

多くの場合、これは製品定義(アプリケーション)に応答します。たとえば、サブスクリプションの場合。同じユーザーが、所有しているすべてのデバイスでサブスクリプションを使用できますか?答えが「はい」の場合。ペイロードを確認しませんでした。

消耗品用。アプリケーションで購入すると、10個の仮想コインが得られるとします。ユーザーはこれらのコインを異なるデバイスで使用できますか? 1つのデバイスに4つ、別のデバイスに6つ?購入したデバイスでのみ作業したい場合は、たとえば自己生成された文字列でローカルに保存されているペイロードを確認する必要があります。

これらの質問に基づいて、ペイロードチェックを実装する方法を決定する必要があります。

よろしく

サンティアゴ

1
Santiago SR