開発
開発
プラットフォームを選択

Meta Quest構成証明API

更新日時: 2025/10/29

概要

構成証明APIは、不正な修正、セキュリティ侵害、繰り返される重度の悪用に対して安全性を確保し、不正利用を防止するのに役立ちます。

オペレーティングシステムの制限

構成証明APIは、Androidプラットフォーム上で構築されたアプリ専用です。

対応デバイス

構成証明APIに対応しているのは、Meta Quest 2、Meta Quest Pro、Meta Quest 3、Meta Quest 3Sだけです。

仕組み

このアプリ構成証明APIは、安全なアプリ環境を提供しながら、開発者による統合の摩擦を軽減することを目指します。APIには、以下の使用状況について判断するのに役立つ構成証明トークンが用意されています。
  • 正規のアプリバイナリ: Meta Horizonストアで認められた、変更の加えられていないアプリバイナリを使用しているかどうかを判断
  • 正規のMetaデバイス: 変更や改ざんの加えられていないMeta Questヘッドセットでアプリが動作しているかどうかを判断
改ざんされたアプリなど、潜在的なリスクや詐欺的なやり取りを検知することで、アプリサーバーは適切に対処し、作業内容や知的財産を海賊行為、不正行為、攻撃、不正アクセス、外部データの不正利用から守ることができます。
構成証明APIの呼び出しフローについて、下図で簡単に順を追って説明します。
Attestation API Call Flow
: このプロセスの間はクライアント側の構成証明APIが構成証明サーバーと通信する必要があります。そのため、構成証明APIの呼び出しを成功させるためにWi-Fi接続が必須になりますので十分ご留意ください。アプリクライアントは、API呼び出しを開始する前にWi-Fi接続を確認する必要があります。
アプリ構成証明APIを適切に統合するため、APIを呼び出す一連の手順を理解することが重要です。詳しい内容は以下のとおりです。
  • ノンスの生成 - アプリサーバーがchallenge_nonceを生成し、アプリクライアントに送信します。このチャレンジノンスは、プロセスの重要な要素です。これはサーバー側で生成されるもので、リプレイ攻撃を防ぐために同じチャレンジノンスを再利用しないことが重要です。
  • 構成証明APIの呼び出し - アプリクライアントは構成証明APIの中央インターフェイス(ovr_DeviceApplicationIntegrity_GetIntegrityToken(const char *challenge_nonce))を使用して、構成証明トークンを取得します。この関数の入力challenge_nonceは、アプリサーバーから受け取ります。
  • セキュリティシグナル - 構成証明APIは必要なセキュリティシグナルを収集し、Meta構成証明サーバーに転送します。ステップ3とステップ4にあるプロセスは、一点鎖線で示されています。これは、アプリクライアントが直接関与することなく、これらのステップがバックグラウンドで発生することを意味します。
  • トークンの生成 - 受け取ったセキュリティシグナルに基づいて、構成証明サーバーが構成証明トークンを生成します。プロセスのセキュリティと信頼性を強化するため、このトークンには構成証明サーバーによって暗号化方式で署名されます。
  • トークンの受け取り - 構成証明APIが構成証明トークンを受け取り、アプリクライアントに送信します。
  • サービスリクエスト - Meta Questアプリが構成証明トークンを受け取ると、認証を受けるために、このトークンを独自のアプリサーバーに送り返す必要があります。認証プロセスは、セキュリティ強化のため、クライアント側ではなくサーバー側で実施されます。アプリクライアントは、サービスリクエストに構成証明トークンを含めて、アプリサーバーに送信します。ここでは、アプリサーバーがこのトークンを使って、クライアントが改ざんされていないかどうかを判断することが極めて重要になります。
  • トークン認証リクエスト - サービスリクエストを受け取ると、アプリサーバーはトークン認証リクエストを構成証明サーバーに送信します。
  • トークンの認証 - 構成証明サーバーはトークンを検証し、その結果をトークンのクレームとともにアプリサーバーに送り返します。トークンが無効な場合はエラーメッセージが送信され、有効な場合はトークンのクレームが送信されます。
  • サービスの提供 - アプリサーバーはトークンの認証結果をもとに、アプリクライアントに対してサービスを提供するかどうかを決定します。トークンが正常に認証されると、サーバーがアプリクライアントからのサービスリクエストに応じます。

構成証明APIとネイティブアプリの統合

構成証明APIをネイティブアプリに統合するには、アプリのPlatform SDKをダウンロードする必要があります。
Oculus Platform SDKに移動して、Platform SDKをダウンロードしてください。ご使用のPlatform SDKおよびMeta Horizon OSシステムがどちらもv55以降であることをご確認ください。
一般的なPlatform SDKのAPI統合に関する概要は、こちらのAPIリファレンスページをご参照ください。構成証明APIを統合するためのコードスニペットの例を以下に示します。
#include <iostream>
#include <random>
#include <vector>
#include <algorithm>

#include "OVR_Platform.h"

// Base64 Url encoding
std::string base64UrlEncode(const std::vector<uint8_t>& data) {
    static const std::string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
    std::string result;

    int val = 0, valb = -6;
    for (uint8_t c : data) {
        val = (val<<8) + c;
        valb += 8;
        while (valb >= 0) {
            result.push_back(chars[(val>>valb)&0x3F]);
            valb -= 6;
        }
    }
    if (valb > -6) result.push_back(chars[((val<<8)>>(valb+8))&0x3F]);
    while (result.size() % 4) result.push_back('=');

    return result;
}

// The "challenge_nonce" parameter must be a non-wrapping Base64URL-encoded
// string, formed from a random byte array by the application server.
std::string getChallengeNonceFromAppServer() {
    std::random_device rd;
    std::vector<uint8_t> randomNonce(16);
    std::generate(randomNonce.begin(), randomNonce.end(), [&]() { return rd(); });

    // Convert to Base64 string
    // The length of the challenge_nonce must range from 22 to 172 characters.
    std::string challenge_nonce = base64UrlEncode(randomNonce);

    return challenge_nonce;
}


void SampleCode() {
   std::string challenge_nonce = getChallengeNonceFromAppServer();
   // Calling the Attestation API
   ovr_DeviceApplicationIntegrity_GetIntegrityToken(challenge_nonce.c_str());

   // Get message response from message queue
   while(true) { // Can set a poll timer here
       // Pop messages off of the message queue
       ovrMessageHandle message = ovr_PopMessage();
       while (message != nullptr) {
           // First check for errors
           if (ovr_Message_IsError(message)) {
               ovrErrorHandle errorHandle = ovr_Message_GetError(message);
               const char* errorMessage = ovr_Error_GetMessage(errorHandle);
               // handle the error
           }

           // Get the message type
           ovrMessageType messageType = ovr_Message_GetType(message);
           // Handle the response
           if (messageType == ovrMessage_DeviceApplicationIntegrity_GetIntegrityToken) {
               const char*  attestation_token = ovr_Message_GetString(message);
               // Send the Attestation token to the app server for token verification
           } else {
               // In this example, we are disregarding all other message types, thus,
               // we will simply ignore them.
           }

          ovr_FreeMessage(message);
          return;
       }
   }
}
上記のコードは、ネイティブアプリにおける構成証明APIの使い方の実例です。この手順に従ってサンプルコードを活用することで、ネイティブプロジェクトに構成証明APIを効果的に組み込むことができます。
challenge_nonceパラメーターは、アプリサーバーによりランダムなバイト配列から作成された、ラッピングなしのBase64URLエンコード文字列でなければなりません。使用可能な文字数は22~172文字です。構成証明トークンが返されたら、それをアプリサーバーに送信して認証を受ける必要があります。

トークンの認証

アプリサーバーがアプリクライアントから構成証明トークンを受け取ったら、次のステップとしてトークンの認証を行います。認証は、RESTful APIを介して構成証明サーバーに構成証明トークンを送信することで行います。そのためには、以下の手順に従って操作します。
  1. Meta Questの開発者ダッシュボードに移動します。
  2. アプリを選択します。
  3. 左側のナビゲーションで、[Development (開発)] > [API]を選択します。
  4. [App Credentials (アプリ認証情報)] のセクションで、アクセストークンをコピーします。アクセストークンはOC|App_ID|App_Secretの形式を使用します。
  5. 次のエンドポイントで、{access_token}パラメーターをそのアクセストークンに置き換え、{attestation_token}パラメーターを検証対象のアプリクライアントから受け取った構成証明トークンに置き換えます。
     https://graph.oculus.com/platform_integrity/verify?token=<attestation_token>&access_token=<access_token>
  6. 構成証明トークンの認証に成功すると、構成証明サーバーから成功を知らせる以下のような応答が届きます。
     {
       "data": [
         {
             "message": "success",
             "claims": "<base64url_encoded_claim>"
         }
       ]
     }
    
    {base64url_encoded_claim}は、認証済み構成証明トークンのクレームを表すBase64URLエンコード文字列です。
    構成証明トークンの署名が無効な場合、構成証明サーバーは以下のような応答を返します。
     {
       "data": [
         {
             "message": "invalid signature"
         }
       ]
     }
    
    この応答は、無効な署名により、構成証明トークンを認証できなかったことを示しています。アプリサーバーは、不正利用されている可能性があるものとしてクライアントを扱う必要があり、アプリクライアントからのサービスリクエストを却下することもできます。アプリのセキュリティを維持するためには、アプリサーバーがこうしたシナリオを適切に処理することが重要です。
    構成証明トークンは、デフォルトで24時間有効です。トークンの検証プロセス中に、トークンの有効期限が切れた場合、構成証明サーバーは以下のエラーメッセージを返します。
     {
       "data": [
         {
             "message": "token expired"
         }
       ]
     }
    
    パフォーマンスのオーバーヘッドとAPIの呼び出し頻度を最小限に抑えるため、アプリクライアントは構成証明トークンを一定期間キャッシュすることができます。ただし、有効期限切れのトークンが使用されないよう、この期間はトークンの有効期間よりも短くする必要があります。このキャッシュ戦略により、安全な通信の確保とアプリの効率的なパフォーマンス維持を最適なバランスで実現できます。

トークンのクレーム

構成証明トークンがMeta構成証明サーバーで正常に検証されると、Base64URLエンコードされたトークンが構成証明サーバーからアプリサーバーへ送信されます。そのトークンをBase64URLデコードすることで、アプリサーバーは一連のクレームを取得します。クレームの例を以下に示します。
{
  "request_details": {
    "exp": 1684606153,
    "nonce": "JMxMPp1H6kCxGzPRsjKFLw==",
    "timestamp": 1684519753
  },
  "app_state": {
    "app_integrity_state": "NotEvaluated",
    "package_cert_sha256_digest": [
      "c8a2e9bccf597c2fb6dc66bee293fc13f2fc47ec77bc6b2b0d52c11f51192ab8"
    ],
    "package_id": "com.example.name123",
    "version": "1"
  }
  "device_state": {
    "device_integrity_state": "NotTrusted",
    "unique_id": "cd81cd7e7e0525f99442ab6392117e89759e8872852de0495aa58f22bd8a1253",
  }
}
このクレームには「request_details」、「app_state」、「device_state」という3つのセクションがあります。

リクエストの詳細

request_detailsセクションには、リクエストに関する情報が含まれます。各フィールドの詳細は以下のとおりです。
  • timestamp: トークンが作成されたUTC時刻(秒単位)です。
  • exp: トークンの有効期限を示すUTC時刻で、デフォルトではトークンの作成後24時間に設定されています。
  • ノンス: ovr_DeviceApplicationIntegrity_GetIntegrityToken(const char *challenge_nonce) APIを呼び出す際に呼び出し元が提供したchallenge_nonceと全く同じ文字列です。
トークンを受け取ると、アプリサーバーは潜在的なリプレイ攻撃を防ぐため、リクエストの詳細のノンスを検証する必要があります。
Replay Attack (リプレイ攻撃)とは、攻撃者が有効なトークンを傍受し、その後のリクエストで再利用するセキュリティ侵害のことです。これは、トークンが不正利用された場合によく発生します。これに対処するため、システムはノンス検証を利用します。
このAPIのコンテキストでは、トークンを受け取った後、アプリサーバーがovr_DeviceApplicationIntegrity_GetIntegrityToken(const char *challenge_nonce) APIに渡されたchallenge_nonceとトークンのクレームに返されるnonce thatが一致していることを検証することが重要です。これらが同一でない場合、トークンが再利用されている可能性があります。この場合、アプリサーバーはこのトークンを無効なものとして扱い、対象クライアントに対するアプリ固有のサービスを拒否する必要があります。また、アプリサーバーはノンスを1回のみ使用できるようにすることが非常に重要です。同じノンスを何度も再利用すると、リプレイ攻撃が発生する可能性があります。システムの安全性を確保し、潜在的なリプレイ攻撃を防ぐため、再利用はせずに、使用ごとに一意のノンスを生成する必要があります。

アプリの状態

app_stateには、アプリの構成証明情報が含まれます。各フィールドの詳細は以下のとおりです。
  • app_integrity_state: このフィールドには、Meta QuestアプリがMeta Questストアを通じて正規にインストールされたかどうかが示されます。正規のインストールの場合はStoreRecognized、不正インストールの場合はNotRecognized、識別不能なアプリの場合はNotEvaluatedが返されます。
  • package_cert_sha256_digest: このフィールドには、すべてのパッケージ証明書の署名に使われたSHA2-256ハッシュが表示されます。アプリ開発者がアプリパッケージへの署名に使用する証明書が複数ある(証明書チェーンがある)場合、ハッシュも複数表示されることがあります。アプリサーバーは、返されたハッシュと既知の証明書の署名ハッシュを比較することができます。
  • package_id: このフィールドには、アプリ開発者が提供したパッケージの名前が表示されます。パッケージ名の形式は、com.example.name123です。
  • version: このフィールドには、アプリ開発者が提供したパッケージのバージョンが表示されます。

デバイスの状態

device_stateのセクションは、デバイスの構成証明についての情報を提供します。各フィールドの詳しい説明を以下に示します。
  • device_integrity_state: このフィールドは、Meta Questデバイスの信頼性に関するインサイトを提供します。指定可能な値は次の3つです。
    • Advanced: デバイスのブートローダーがロックされており、起動されたAndroid OSは有効なシステムイメージであり、システムへの不正アクセスや改ざんの兆候は確認されていない。
    • Basic: デバイスのブートローダーはロックされており、起動されたAndroid OSは有効なシステムイメージとなっているが、他のシステム整合性チェックの一部に失敗している。これは、起動以降にシステムが侵害された可能性を示唆するもので、例えばルート化されている場合などが該当します。
    • NotTrusted: デバイスのブートローダーがロック解除されているか、起動したAndroid OSイメージが有効なシステムイメージではない。
  • unique_id: この識別子はアプリごとにユニークであり、同じデバイスの異なるアプリが確実に別個のIDを持つようにします。ランダムな文字列として生成され、特定のアプリのためにデバイスをユニークに識別するものとなります。ユーザーのプライバシーを保護し、長期にわたるデバイストラッキングを阻止するため、unique_idは30日ごとに更新されます。しかし、このほぼ1か月の期間内であれば、アプリはこのIDをハードウェア禁止行為検出のために活用することができます。
: トークンのクレームを処理する際は、実行中に新しいクレームによってアプリの機能が中断されないようにする必要があります。そのため、トークンの処理ロジックを慎重に計画し、それに応じて調整することが重要です。

デバイスのブロック

必要に応じて、構成証明APIを使って、特定のMeta Questデバイスからアプリへのアクセスを禁止することができます。この機能を使用すると、デバイスをブロックする期間を設定することができ、デバイスがアプリへのアクセスをブロックされる期間をコントロールできます。
デバイスのブロックは、全体的な悪用防止戦略において重要な役割を果たし、以下からアプリとユーザーコミュニティを守るのに役立ちます。
  • 不正な修正とセキュリティ侵害: 構成証明APIにより不正に修正されたアプリ(海賊版アプリなど)が検出されたかどうかを判断します。
  • 繰り返される重度の悪用: 特定のMeta Questデバイスから繰り返される重度の悪用が確認されたかを判断します。
全体的なアプリモデレーション戦略の一環として、構成証明APIのデバイスブロック機能とアプリ内レポートシステムを一緒に使用してください。(モデレーションプログラムの設定とレポートおよびガバナンス要件への準拠の方法に関するガイダンスについては、こちらのコンテンツのモデレーションおよびレポートコンプライアンスコースをチェックしてください)。全体的なアプリモデレーション戦略の一環として、構成証明APIのデバイスブロック機能とアプリ内レポートシステムを一緒に使用してください。(モデレーションプログラムの設定とレポートおよびガバナンス要件への準拠の方法に関するガイダンスについては、こちらのコンテンツのモデレーションおよびレポートコンプライアンスコースをチェックしてください)。
: Metaではデバイスのブロックのためのインフラストラクチャは提供しますが、発行されるブロックについては責任を負いません。デバイスのブロック機能は、利用者の側で責任をもってご使用ください。構成証明APIのデバイスブロック機能を適切に使用しない場合、プラットフォーム不正利用ポリシーに違反し、法的処置の対象になることがあります。

仕組み

デバイスのブロック機能は、アプリサービスからMeta構成証明サーバーにブロック対象のデバイスを通知することにより機能します。
  1. デバイスは疑似のunique_idによって識別されます。これは現在の構成証明トークンのdevice_stateセクションから取得されたものです。
  2. アプリサーバーからMeta構成証明サーバーに、デバイスのunique_idとブロック期間が指定されたサーバー間リクエストを送信します。
  3. リクエストに成功すると、Meta構成証明バックエンドによりデバイスが「アプリをブロック」としてマークされます。
  4. このブロックステータスを反映して、その後のデバイスの構成証明トークンにはdevice_banセクションが組み込まれます。
下図に、このプロセスの詳細な呼び出しフローを示します。
Attestation API - Device Ban Status
デバイスのブロックの施行はアプリサーバー側で行われます。
  1. アプリサーバーで構成証明トークンが受信されると、トークンにdevice_banセクションis_banned:trueがあるかどうかがチェックされます。
  2. 条件が満たされている場合、ブロックの施行方法を決定します。
この施行プロセスの次の呼び出しグラフを以下に示します。
Attestation API - Device Ban Enforcement

利用

デバイスブロック機能を利用するために、構成証明APIの現在の実装を変更する必要はありません。構成証明APIの呼び出し時に返される情報の調整が行われ、新しいサーバー間リクエストがデバイスのブロックのためにアクセス可能になり、指定のデバイスが現在ブロックされているかどうかをこのリクエストでチェックします。
デバイスブロック機能を利用するには、アプリに構成証明APIが実装されている必要があります。また、データの使用状況の確認の下で、デバイスブロック機能にアクセスするリクエストを送信する必要があります。このプロセスでは、アプリのデータ使用状況に関する簡単なアンケートに回答します。承認されると、デバイスブロックを利用できるようになります。

デバイスブロック機能へのアクセスをリクエストする方法

  1. 開発者ダッシュボードに移動して、アプリを選択します。
  2. 左側のメニューから、[Requirements (要件)] > [Data Use Checkup (データの使用状況の確認)]に移動します。
  3. [Device Ban (デバイスのブロック)]まで下にスクロールし、右側の[Add (追加)]をクリックします。
  4. フォームに入力し、[Submit (送信)]をクリックします。
  5. アプリレビュー担当者がリクエストを承認すると、その機能を利用できるようになります。
デバイスブロック機能を利用するために、構成証明APIの現在の実装を変更する必要はありません。構成証明APIを呼び出すと、返される情報に調整が行われます。また、次のことを行うための新しいサーバー間リクエストが利用可能になります。
  • デバイスをブロックする
  • 既存のデバイスブロックの残り時間を更新する
  • 既存のデバイスのブロックを解除する
  • 特定のデバイスが現在ブロックされているかどうかを確認する
  • 指定されたブロックが現在アクティブかどうかを確認する
  • アプリのすべてのアクティブなブロックリストを取得する

構成証明トークンのデバイスブロックステータス

デバイスのブロックステータスを取得するには、トークンの認証に従って、通常の構成証明トークンのクエリを実行します。トークンのクレームセクション内で、返される結果には、デバイスがブロックされている場合のみdevice_banセクションが設定されます。ブロックされていない場合、device_banセクションは省略されます。
デバイスがブロックされていない構成証明トークンの例:
{
  "request_details": {
    "exp": 1684606153,
    "nonce": "JMxMPp1H6kCxGzPRsjKFLw==",
    "timestamp": 1684519753
  },
  "app_state": {
    "app_integrity_state": "StoreRecognized",
    "package_cert_sha256_digest": [
      "c8a2e9bccf597c2fb6dc66bee293fc13f2fc47ec77bc6b2b0d52c11f51192ab8"
    ],
    "package_id": "com.example.name123",
    "version": "1"
  }
  "device_state": {
    "device_integrity_state": "Advanced",
    "unique_id": "442ab6392117e89759e8872852de0495aa58f22bd8a1253123123",
  }
}
以下に、現在デバイスがブロックされている構成証明トークンの例を示します。
{
  "request_details": {
    "exp": 1684606153,
    "nonce": "JMxMPp1H6kCxGzPRsjKFLw==",
    "timestamp": 1684519753
  },
  "app_state": {
    "app_integrity_state": "StoreRecognized",
    "package_cert_sha256_digest": [
      "c8a2e9bccf597c2fb6dc66bee293fc13f2fc47ec77bc6b2b0d52c11f51192ab8"
    ],
    "package_id": "com.example.name123",
    "version": "1"
  }
  "device_state": {
    "device_integrity_state": "Advanced",
    "unique_id": "442ab6392117e89759e8872852de0495aa58f22bd8a1253123123",
  }
  "device_ban": {
    "is_banned": true
    "remaining_ban_time": 34 days
  }
}

デバイスブロックの制限

device_stateセクションで返されるunique_idは、構成証明トークンを返す特定のデバイスとトークンをリクエストするアプリにリンクされます。このunique_idは、ユーザーのプライバシーを保護するため、30日ごとに変更されます。この30日の間に、unique_idを手動で使用し、サーバー間リクエストでis_banned:falseを設定してデバイスのブロックを撤回することができます。ブロックの期間を調整することもできます。
しかし、30日が経過してunique_idが変更されると、ブロック期間の調整やブロックの解除を行うには、最初のブロック設定時にサーバー間リクエストを通じて取得したリンクされたban_idを使用しなくてはなりません。元のブロックから30日が経過した場合、そのデバイスに対して新たなブロックを設定するには、そのデバイス固有のunique_idを再度取得する必要があります。
各ブロックのban_idには有効期限がなく、常にその特定のデバイスに紐付けられており、その特定のブロックを変更または解除するためにいつでも使用できます。ただし、デバイスのブロックを解除した場合、またはブロックが設定したブロック期間を過ぎた場合、ban_id は削除されます。

デバイスのブロック方法

ユーザーのデバイスのブロックは、エンドポイント経由のサーバー間リクエストを通してのみ行えます。
  1. トークンの認証を使って構成証明トークンをクエリし、トークンのクレームの「device_state」セクションで「unique_id」を取得します。
  2. 開発者ダッシュボードに移動して、アプリを選択します。
  3. 左側のナビゲーションで、[Development (開発)] > [API]を選択します。
  4. [App Credentials (アプリ認証情報)]のセクションで、アクセストークンを取得します。アクセストークンの形式は、OC/App_ID/App_Secretです。
  5. 次のエンドポイントで、以下のように書き換えます。
  • unique_idに、ステップ1に示す構成証明トークンにある疑似の固有IDを設定。
  • is_bannedに、デバイスをブロックする場合はtrueを、ブロックしない場合はfalseを設定。
    注: このパラメーターは、is_bannedの設定がfalseの場合でも必要ですが、無視されます。
  • remaining_time_in_minuteに、デバイスのブロック時間として0~52560000 (100年)の整数値を設定。
  • access_tokenパラメーターに、ステップ5に示すアクセストークンを設定。
 https://graph.oculus.com/platform_integrity/device_ban?method=POST&unique_id=<unique_id>&is_banned=<is_banned>&remaining_time_in_minute=<remaining_time_in_minute>&access_token=<access_token>
デバイスのブロックリクエストに成功すると、構成証明サーバーから成功を知らせる以下のような応答が届きます。
{
   "message": "Success",
   "ban_id": "NjIxMzI3MTc0MTgzMzkzNw"
}
unique_idが無効な場合、以下のようなエラーメッセージを返します。
{
   "error": {
      "message": "There is no record of this Unique ID. Please check that the Unique ID matches what is given in the Attestation Token and try again. Note that Unique IDs will change every 30 days for each application and device, make sure the Unique ID is up to date.",
      "type": "OCApiException",
      "code": 1,
      "error_data": {


      },
      "error_subcode": 1614026,
      "fbtrace_id": "AUhV19OFsDqs6gTXn7zVybm"
   }
}
unique_idaccess_tokenに格納されたアプリの情報と一致しない場合、以下のようなエラーメッセージを返します。
{
   "error": {
      "message": "The App ID of the Access Token does not match the Unique ID, please check the Unique ID/Access Token and try again",
      "type": "OCApiException",
      "code": 1,
      "error_data": {


      },
      "error_subcode": 1614027,
      "fbtrace_id": "AHBbS8rEDcgajcgpQcqtVO1"
   }
}
remaining_time_in_minuteのインプットが[0, 52560000]の範囲内にない場合、以下のようなエラーメッセージを返します。
{
   "error": {
      "message": "The Remaining Time In Minute field is invalid. Please check that the time inputted is between 0 and 52560000.",
      "type": "OCApiException",
      "code": 1,
      "error_data": {


      },
      "error_subcode": 1614028,
      "fbtrace_id": "AtFBCvCIb4IXSGvvc4GudY8"
   }
}

すべての有効なデバイスブロックIDを取得する方法

アプリの有効なデバイスban_idのクエリを行うには、エンドポイント経由でサーバー対サーバーリクエストを使用します。解除または期限切れとなったブロックのban_idをクエリする方法はありません。
  1. Meta Quest開発者ダッシュボードに移動して、アプリを選択します。
  2. 左側のナビゲーションで、[Development (開発)] > [API]を選択します。
  3. [App Credentials (アプリ認証情報)] のセクションで、アクセストークンをコピーします。これは**OCという形式になっています。
    App_ID
    App_Secret**.
  4. 以下のエンドポイントで、<access_token>パラメーターを、ステップ3で取得したアクセストークンに置き換えます。
https://graph.oculus.com/platform_integrity/device_ban_ids?access_token=<access_token>
デバイスのブロックIDリクエストに成功すると、構成証明サーバーから成功を知らせる以下のような応答が届きます。
{
   "data": [
      {
         "message": "Success",
         "all_ban_ids": [
    {
               "ban_id": "MTI0MjQ3MTc0MDk2NTYwNg",
               "creation_date": "2025-05-27"
            },
            {
               "ban_id": "NTgyOTAyMTc0MDk2NTgyNQ",
               "creation_date": "2025-05-09"
            },
            {
               "ban_id": "ODUyMTk1MTc0NjY1MjUzMw",
               "creation_date": "2025-05-07"
            }
         ]
      }
   ],
   "paging": {
      "cursors": {
         "before": "QVFIUmcwb3MtZAkhkWUhjZAElXQ2tHUXMwbjdjRi1NeUg5aWlIN3liSzZAfN1FmdnVIRkhmSVU3OUtpQ3FweUp3NE1TYWJob3k1NGIzeDRIdjdlMXRZAcWtyWGxn",
         "after": "QVFIUmcwb3MtZAkhkWUhjZAElXQ2tHUXMwbjdjRi1NeUg5aWlIN3liSzZAfN1FmdnVIRkhmSVU3OUtpQ3FweUp3NE1TYWJob3k1NGIzeDRIdjdlMXRZAcWtyWGxn"
      }
   }
}

  • 表示されているban_idは、すべてアプリで有効になっています。各ブロックのban_idは変更されることはなく、有効期限もありません。ブロックが解除された場合、またはブロックの有効期限が切れた場合、ban_idは削除され、以降このエンドポイントから返されなくなります。
  • creation_dateフィールドは、元のブロック作成リクエストの日時(世界標準時)を返します。
  • ページングセクションでは、1ページに表示できる数を超えるブロックがある場合、次のページのban_idに関する情報が表示されます。表示可能なban_idの上限は500件です。ブロックの数に上限はありませんが、このエンドポイントに表示される数には制限があります。ページングの上限に達すると、以下のようにban_id の次のページへのURLリンクが表示されます。ページングの上限に達しない場合、[next (次)]フィールドは省略されます。
{
   "data": [
      {
         "message": "Success",
         "all_ban_ids": [
    {
               "ban_id": "MTI0MjQ3MTc0MDk2NTYwNg",
               "creation_date": "2025-05-27"
            },
            .
		 .
		  <500 ban_ids here>
		 .
		 .
		 .
         ]
      }
   ],
   "paging": {
     "cursors": {
        "before": "QVFIUkIxLS1XNDhSdHJFQXlELXplbnZAINnd6cmc5ZAkhEOVJPU3ViR1F4TFQ4V3N3NWwxV1Y0T05rLWk4NWhKM2dGY2d2aGpaZAERfd0lSOXRYejdWbTJYYUhB",
        "after": "QVFIUjlMcGJuRGxHUFRjT1lLOS04cGdRZAHpPSDFBQnA0aEJOZA3hmeDVaWEVSdXozM2FkOV9jVFhoVy1Jb08xRzlZAOVlROWNvTlNxMUpveUphZAmEzY2ZAHNFJ3"
     },
     "next": "https://graph.oculus.com/platform_integrity/device_ban_ids?access_token=<access_token>&pretty=1&limit=500&after=QVFIUjlMcGJuRGxHUFRjT1lLOS04cGdRZAHpPSDFBQnA0aEJOZA3hmeDVaWEVSdXozM2FkOV9jVFhoVy1Jb08xRzlZAOVlROWNvTlNxMUpveUphZAmEzY2ZAHNFJ3"
  }
}

デバイスのブロックを解除または更新する方法

既存のブロックは、デバイスブロックのリクエストに使用されたのと同じエンドポイントによるサーバー対サーバーリクエストを通じてのみ解除または更新することができます。デバイスのブロックを解除するには、ban_idまたはデバイスのunique_idを使用できます(元のブロックが作成されてから30日以内の場合)。有効なban_idと有効なunique_idの両方を使ってエンドポイントに問い合わせると、エンドポイントはリクエストを完了するためにban_idを使用します。
既存のデバイスブロックを随時解除または更新するには、以下の手順に従います。
  1. 元のブロックリクエストからban_idを取得するか、すべての有効なデバイスブロックIDを取得することで、すべての有効なデバイスブロックのban_idを取得します。
  2. 開発者ダッシュボードに移動して、アプリを選択します。
  3. 左側のナビゲーションで、[Development (開発)] > [API]を選択します。
  4. [App Credentials (アプリ認証情報)]のセクションで、access_tokenを取得します。これは**OCという形式になっています。
    App_ID
    App_Secret**.
  5. 次のエンドポイントで、以下のように書き換えます。
    • <ban_id>に、ステップ1で取得したban_idを設定。
    • <is_banned>trueに設定するとブロックを適用し、falseに設定するとブロックを解除します。
    • <remaining_time_in_minute> に、デバイスのブロック時間を分単位で示す0~52560000 (100年)の整数値を設定。is_bannedtrueに設定されている場合にのみ必要となります。
    • <access_token>に、ステップ4に示すアクセストークンを設定。
https://graph.oculus.com/platform_integrity/device_ban?method=POST&ban_id=<ban_id>&is_banned=<is_banned>&remaining_time_in_minute=<remaining_time_in_minute>&access_token=<access_token>
デバイスのブロック解除リクエストに成功すると、構成証明サーバーから成功を知らせる以下のような応答が届きます。
{
   "message": "Success",
   "ban_id": ""
}

デバイスのブロックが解除されたら、該当するban_id は無効になることにご注意ください。デバイスのブロック更新リクエストに成功すると、構成証明サーバーから成功を知らせる以下のような応答が届きます。
{
   "message": "Success",
   "ban_id": "NjIxMzI3MTc0MTgzMzkzNw"
}
ban_idが無効な場合、以下のようなエラーメッセージを返します。
{
   "error": {
      "message": "There is no record of this ban_id. Please check the ban_id and try again. If you don't know the specific ban_id, query the Device Ban IDs endpoint to see a list of all the ban_ids currently active for your application.",
      "type": "OCApiException",
      "code": -1,
      "error_data": {


      },
      "error_subcode": 1614033,
      "fbtrace_id": "AzBdHW5FhJ8xtfLLzQr90Gz"
   }
}
ban_idaccess_tokenに格納されたアプリの情報と一致しない場合、以下のようなエラーメッセージを返します。
​​{
   "error": {
      "message": "The App ID of the Access Token does not match the Ban ID, please check the Ban ID/Access Token and try again",
      "type": "OCApiException",
      "code": -1,
      "error_data": {


      },
      "error_subcode": 1614036,
      "fbtrace_id": "AIp_qT4f8skiZrs1NI2xPjN"
   }
}
元のブロックリクエストから30日未満の場合、既存のデバイスのブロックを解除または更新するためにunique_idを使用することもできます。
  1. トークンの認証を使って構成証明トークンをクエリし、トークンのクレームの「device_state」セクションで「unique_id」を取得します。
  2. 開発者ダッシュボードに移動して、アプリを選択します。
  3. 左側のナビゲーションで、[Development (開発)] > [API]を選択します。
  4. [App Credentials (アプリ認証情報)]のセクションで、access_tokenを取得します。これは**OCという形式になっています。
    App_ID
    App_Secret**.
  5. 次のエンドポイントで、以下のように書き換えます。
    • <unique_id>に、ステップ1に示す構成証明トークンにある疑似の固有IDを設定。
    • <is_banned>trueに設定するとブロックを適用し、falseに設定するとブロックを解除します。
    • <remaining_time_in_minute> に、デバイスのブロック時間を分単位で示す0~52560000 (100年)の整数値を設定。is_bannedtrueに設定されている場合にのみ必要となります。
    • <access_token>に、ステップ4に示すアクセストークンを設定。
https://graph.oculus.com/platform_integrity/device_ban?method=POST&unique_id=<unique_id>&is_banned=<is_banned>&remaining_time_in_minute=<remaining_time_in_minute>&access_token=<access_token>
デバイスのブロック解除リクエストに成功すると、構成証明サーバーから成功を知らせる以下のような応答が届きます。
{
   "message": "Success",
   "ban_id": ""
}

デバイスのブロックが解除されたら、該当するban_id は無効になることにご注意ください。デバイスに既存のブロック設定がない場合、かつis_bannedfalseに設定されている場合、以下の例のような成功応答が返されます。
{
   "message": "Success",
   "ban_id": ""
}
デバイスのブロック更新リクエストに成功すると、構成証明サーバーから成功を知らせる以下のような応答が届きます。
{
   "message": "Success",
   "ban_id": "NjIxMzI3MTc0MTgzMzkzNw"
}
unique_idが無効な場合、unique_idaccess_tokenに保存されているアプリ情報と一致しない場合、またはremaining_time_in_minuteフィールドが範囲外の場合、デバイスのブロック方法に示されているエラーが発生します。

デバイスブロックステータスのクエリ方法

デバイスブロックステータスのクエリを行うには、エンドポイント経由でサーバー対サーバーリクエストを使用します。有効なban_idを使用してブロックステータスをクエリするか、有効なunique_idを使用して特定のデバイスのブロックステータスをクエリすることもできます。有効なban_idと有効なunique_idの両方を使ってエンドポイントに問い合わせると、エンドポイントはリクエストを完了するためにban_idを使用します。
ban_idを使用して、ブロックのステータスを確認するには、以下の手順に従います。
  1. 元のブロックリクエストからban_idを取得するか、(このガイドの)手順に従って、すべての有効なデバイスブロックのban_idを取得します。
  2. Meta Quest開発者ダッシュボードに移動して、アプリを選択します。
  3. 左側のナビゲーションで、[Development (開発)] > [API]を選択します。
  4. アプリ認証情報セクションで、アクセストークン(形式は**OC)をコピーします。
    App_ID
    App_Secret**.
  5. 次のエンドポイントで、以下のように書き換えます。
    • <ban_id>パラメーターに、ステップ1で取得した**ban_id**を設定。
    • <access_token>パラメーターに、ステップ4に示すアクセストークンを設定
 https://graph.oculus.com/platform_integrity/device_ban_status?unique_id =<unique_id>&access_token=<access_token>
デバイスのブロックリクエストに成功すると、構成証明サーバーから成功を知らせる以下のような応答が届きます。
{
   "data": [
      {
         "message": "Success",
         "is_banned": true,
         "remaining_time_in_minute": 12
      }
   ]
}
unique_idが無効な場合、以下のようなエラーメッセージを返します。
{
   "error": {
      "message": "There is no record of this Unique ID. Please check that the Unique ID matches what is given in the Attestation Token and try again. Note that Unique IDs will change every 30 days for each application and device, make sure the Unique ID is up to date.",
      "type": "OCApiException",
      "code": 1,
      "error_data": {


      },
      "error_subcode": 1614026,
      "fbtrace_id": "AUhV19OFsDqs6gTXn7zVybm"
   }
}
unique_idaccess_tokenに格納されたアプリの情報と一致しない場合、以下のようなエラーメッセージを返します。
{
   "error": {
      "message": "The App ID of the Access Token does not match the Unique ID, please check the Unique ID/Access Token and try again",
      "type": "OCApiException",
      "code": 1,
      "error_data": {


      },
      "error_subcode": 1614027,
      "fbtrace_id": "AHBbS8rEDcgajcgpQcqtVO1"
   }
}

APIの設定

統合をよりパーソナライズされたものにするため、ニーズや用途に応じて、構成証明APIを調整できます。
構成証明APIを設定するには、Meta Horizon開発者ダッシュボードをご確認ください。アプリを選択します。左側のナビゲーションで、[Settings (設定)]をクリックします。[Attestation API (構成証明API)]タブが表示され、以下の設定が可能になります。
  • Device Integrity State Bypass: これはデフォルトで有効になっています。これが有効になっている場合、Metaの内部テストデバイスでは、構成証明トークンのdevice_state内のdevice_integrity_stateが常にAdvancedに設定されます。これは、アプリサーバーがNotTrustedデバイス上でサービスをブロックする場合に特に便利です。このバイパス機能を使えば、アプリをMetaのデバイス上でシームレスにテストできるため、Metaの内部テストチームによる効率的なサポートが可能になります。これは特に、予備ビルドリリースの評価において有効です。
  • Token Expiration Duration: この設定により、構成証明トークンの寿命が決まります。デフォルトの有効期限は24時間です。期間が短いと、デバイスやアプリの不正アクセスを検出するための所要時間が短縮されてセキュリティは強化されますが、必要になる構成証明のチェックの頻度は高くなります。逆に期間が長いと、アプリへの負荷は減りますが、侵害された場合に不正アクセスが拡大するリスクが高くなります。

APIの使用制約

構成証明APIをアプリに統合する際には、以下のAPIの使用制約を念頭に置きましょう。

レート制限

最適なパフォーマンスを維持し、公正な利用を確保するため、デバイスが行えるAPIの呼び出し回数にはレート制限が設けられています。これにより、デバイスごとの1時間あたりリクエストは100件、1日あたりリクエストは200件に制限されています。したがって、これらのレート制限を考慮してアプリを設計する必要があります。このAPIを通じて取得した構成証明トークンの有効期間は、それぞれ24時間です。
レート制限に達しないようにするために、アプリにトークンキャッシュを実装することをおすすめします。有効期間内にトークンを保存し、再利用することで、APIの呼び出し頻度を減らすことができ、レート制限に達するリスクも最小限に抑えられます。

APIのベストプラクティス

​​​簡単に回避できない方法で構成証明APIが使われるようにするには、以下のベストプラクティスに従ってください。

構成証明トークンはサーバーサイドバックエンドでのみ検証する

​​​構成証明トークンがクライアント側で検証される場合、再パッケージ化されたAPKなどの侵害されたクライアントは、検証ルーチンを容易に無効化することができます。代わりに、構成証明トークンをクライアントアプリからサーバーバックエンドに送信し、検証する必要があります。

構成証明APIエラーを安全に処理する

​​​クライアント側のGetIntegrityToken APIは、構成証明トークンを返す代わりに、時折エラーまたは例外を返すことがあります。これは、一時的な環境要因、インフラの障害、不良なネットワーク接続など、さまざまな理由によって発生する可能性があります。​​​しかし、このようなエラーは、不正なデバイスやアプリでの悪意のある活動によっても引き起こされる可能性があります。アクティブな攻撃は、さまざまな方法で、異なるエラーメッセージや誤解を招くエラーメッセージを表示して、システムが異常に動作するように設計されている可能性があります。侵害されたアプリやシステムは、構成上、構成証明APIへの呼び出しを完全に取り除いたりブロックしたりするように設定することもできます。​​​: 指数的バックオフ再試行戦略を使用することをおすすめします。何度再試行しても構成証明トークンを取得できない場合、バックエンドはこの失敗を、device_integrityNotTrustedとなる有効な構成証明の判決と同じように扱う必要があります。

トークンを安全に検証する

​​​Metaのトークン認証サービスを利用して、トークンの署名が本物であることを確認してください。​​​トークンのクレームを受け取ったら、さらに検証します。
  • exp (トークン有効期限)が24時間以内である
  • nonceが構成証明APIリクエストで使われるchallenge_nonceと同じである
  • timestampが最新である(数分以内)
  • app_integrity_stateはパッケージがHorizonストアからインストールされていることを示している
  • package_cert_sha256_digestハッシュが想定どおりである
  • device_integrityAdvancedまたは少なくともBasicである

    challenge_nonceに一意の要素を含める

    ​​​リプレイ攻撃を防ぐため、チャレンジノンスは一度だけ使い、一意の要素を含める必要があります。
  • サーバーサイドのバックエンドで、悪意のあるユーザーが予測できない、グローバルに一意の値を作成する。これは、暗号的に安全な新しいランダムな番号か、取引IDなどの既存のユニークなトークンになります。この値をサーバー側のユーザーセッションに保存し、クライアントアプリにも送信して、challenge_nonceとして使用されます。
  • 検証済み構成証明クレームを受け取ったら、クレーム内のノンスが保管済みのchallenge_nonceと一致することを確認する。保存された一意の値は、単一の構成証明クレームの検証にのみ使われるため、破棄してください。

    challenge_nonceに機密性の高いリクエストをバインドする

    ​​​構成証明APIは、機密性の高い取引を保護するために使うと最も価値が高まります。そのようなアクションを特定し、構成証明APIを使って保護することで、ユーザーはアクションが実行される前に課題を課されるかブロックされます。​​​これを実現するために、以下のような大まかな設計を検討してください。
  • サーバーサイドのバックエンドは、固有の値を生成して(前のセクションに従って)、クライアントアプリに送信し、その記録を保持する。
  • クライアント側のアプリは、バックエンドに高額の取引リクエストを送信する準備をしながら、重要なリクエストパラメーターのダイジェストを計算する。
    • 例: リクエストの詳細(アクセストークンCookie、ユーザーID、取引データなど)を含む、シリアル化されたリクエストフォーマット
  • このハッシュは、バックエンドからクライアントに送信されるユニークな値と組み合わされ、構成証明APIのchallenge_nonceとして使用される。
  • クライアント側のアプリは、構成証明トークンをこのリクエストの一部として含めた上で、高価値のリクエストをバックエンドに送信する。
  • サーバーサイドのバックエンドがこのリクエストを受け取ると、構成証明トークンがMetaサーバーに送信され、検証が行われる。構成証明トークンの検証後、Metaサーバーはクレームの詳細を返す。
  • バックエンドは、受信したリクエストのパラメーターと保存された一意の値を組み合わせて、期待されるノンスを計算し、構成証明クレームのノンスと比較する。これらが異なる場合、構成証明リクエストが改ざんされた可能性があります。

    バイナリブロックの代わりにアカウント制限を選択する

    ​​​構成証明のクレームを検証できないエラーがある場合や、不正利用の可能性があることを示している場合は、単にユーザーを記録したりブロックしたりするのではなく、さまざまな結果を返すようにします。これにより、システムを迂回することが困難になります。例えば、ユーザーが不正使用の可能性があるとフラグされた場合、アクセスを許可するものの利用可能なアクションに制限を課すか、CAPTCHAのような強化認証を強制することを検討してください。
ナビゲーションロゴ
日本語
© 2026 Meta