アプリのサーバー側でのライセンス確認の追加

Google Play ストアからユーザーがアプリの正規コピーを購入またはダウンロードしたことを確認する際、パブリッシャーが管理しているサーバー側でライセンス確認のチェックを行うことをおすすめします。

このガイドでは、サーバー側のライセンス確認プロセスの各段階と、そのチェックの実施に関するおすすめの方法について説明します。

プロセスの概要

図 1 に、アプリ、Google Play、プライベート サーバーの間での情報の流れを示します。

データフロー図
図 1. アプリと Google Play 間、アプリとプライベート サーバー間のデータの流れ
  1. アプリから Google Play へのリクエストで、特定のユーザーがアプリの正規コピーを購入またはダウンロードしたかどうかの問い合わせが行われます。
  2. Google Play からアプリへのレスポンスとして、「レスポンス データ オブジェクト」ResponseData 型のオブジェクト)が送られます。このオブジェクトは、ユーザーがアプリの正規コピーを購入またはダウンロードしたかどうかを示す署名付きの情報です。
  3. アプリから、パブリッシャー側で管理するプライベート サーバーに対して、レスポンス データの内容を確認するようリクエストします。
  4. プライベート サーバーからアプリへのレスポンスとして、ユーザーが実際にアプリの正規コピーを購入またはダウンロードしたかどうかを示すステータスが送られます。サーバーから「成功」メッセージが送られた場合は、レスポンスの検証を行い、その後でライセンスを必要とするリソースの使用をユーザーに許可します。

レスポンス データは Google Play によって署名され、プライベート サーバーでチェックされるため、アプリを実行しているデバイス上でレスポンス オブジェクトが変更されることはありません。サーバーを利用して正規ユーザーのみにリソースの使用を許可することで、不正なユーザーによる使用を有効に防止できます。

次のセクションでは、サーバー側のライセンス確認を行う場合に追加で考慮すべき事項を示します。

リプレイ攻撃への対策

自分のライセンス ステータスに関する Google Play からのレスポンスを受け取ったユーザーは、そのレスポンス データをコピーして複数回使用したり、他のユーザーに与えたりする可能性があります。与えられたユーザーが、レスポンス データを自分のリクエストに偽造して、アプリのプライベート サーバーに送信するおそれがあります。このような行為は「リプレイ攻撃」と呼ばれます。

リプレイ攻撃が成功する可能性を減らすには、プライベート サーバーにリクエストを送る前に以下の対策を行います。

  • レスポンス データに含まれるタイムスタンプを確認し、レスポンスが Google Play によって最近生成されたことを確認します。

  • アプリからプライベート サーバーに同じレスポンス データが送られる回数を減らすため、指数バックオフなど、サーバー リクエストに対するレート制限をかけます。

  • プライベート サーバーで Google Play からのレスポンス データの内容を確認する前に、プライベート サーバーに対して最初の認証ベースのリクエストを行います。この最初のリクエストでは、ユーザーの認証情報をサーバーに送信し、サーバーからは「ノンス」(使い捨ての数値)を付けて応答させるようにします。そして、プライベート サーバーへの次のリクエストにはこのノンスを含め、ライセンス確認データを要求します。適切なノンス値を選択する方法の詳細については、適切なノンス値の生成セクションをご覧ください。

適切なノンス値の生成

次のいずれかの手法を使用して、推測が困難なノンス値を作成します。

  • ユーザーの ID に基づいてハッシュ値を生成する。
  • ユーザーごとにランダムな値を生成する。このランダム値を、そのユーザーの属性の一部としてプライベート サーバーに保存する。

プライベート サーバーからのレスポンス データの検証

プライベート サーバーからアプリに送信されたレスポンス データを確認するとき、License Verification Library(LVL)のレスポンスが偽造されていないかどうか検証します。プライベート サーバーからのレスポンス データに含まれる署名を、前の手順でアプリが Google Play から受け取った鍵と比較することで検証します。

また、署名されている部分は、LVL 固有のブロックのみということも重要です。つまり、プライベート サーバーからのレスポンス データの中で、アプリで信用すべきなのはその部分のみとなります。