以前の FCM API から HTTP v1 に移行する

HTTP と XMPP に非推奨の FCM レガシー API を使用しているアプリは、できるだけ早く HTTP v1 API に移行する必要があります。これらの API を使用したメッセージ(アップストリーム メッセージを含む)の送信は、2023 年 6 月 20 日に非推奨となっており、2024 年 7 月 22 日にサービスを停止します

詳しくは、影響を受ける機能をご覧ください。

継続的なサポートと新機能を利用できることに加え、HTTP v1 API は次のような点で従来の API よりメリットがあります。

  • アクセス トークンの利用によるセキュリティの強化: HTTP v1 API では、OAuth2 セキュリティ モデルに準じた有効期間の短いアクセス トークンを使用します。アクセス トークンが漏洩した場合でも、悪用される時間は有効期限が切れるまでの 1 時間程度しかありません。更新トークンは、以前の API で使用していたセキュリティ キーほど頻繁に送信されないため、捕捉される可能性が非常に低くなります。

  • プラットフォーム間メッセージのカスタマイズ効率の向上: HTTP v1 API では、すべてのターゲット インスタンスに適用される共通キーとプラットフォーム間メッセージのカスタマイズを可能にするプラットフォーム固有のキーをメッセージ本文に設定します。これを利用して「オーバーライド」を作成し、クライアント プラットフォームごとにわずかに異なるペイロードを 1 つのメッセージで送信できます。

  • クライアント プラットフォームの新しいバージョンに対応可能な高い拡張性と将来性: HTTP v1 API は、Apple プラットフォーム、Android、ウェブで利用可能なメッセージング オプションを完全にサポートしています。各プラットフォームの JSON ペイロードには独自の定義済みブロックが含まれているため、FCM では必要に応じて新しいバージョンや新しいプラットフォームに合わせて API を拡張できます。

サーバー エンドポイントを更新する

HTTP v1 API のエンドポイント URL は、次の点で以前のエンドポイントと異なります。

  • パスの /v1 の部分でバージョンが区別されます。
  • アプリ用の Firebase プロジェクトのプロジェクト ID が /projects/myproject-ID/ の形式でパスに含まれます。この ID は、Firebase コンソールの [プロジェクトの設定] の [全般] タブで確認できます。
  • send メソッドを :send として明示的に指定します。

HTTP v1 用のサーバー エンドポイントに更新するには、送信リクエストのヘッダーのエンドポイントに上記の要素を追加します。

これまでの HTTP リクエスト

POST https://fcm.googleapis.com/fcm/send

これまでの XMPP リクエスト

以前の XMPP メッセージは、次のエンドポイントへの接続を介して送信されます。

fcm-xmpp.googleapis.com:5235

変更後

POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send

送信リクエストの承認を更新する

以前のリクエストで使用されていたサーバーキー文字列の代わりに、HTTP v1 送信リクエストには OAuth 2.0 アクセス トークンが必要です。Admin SDK を使用してメッセージを送信している場合は、ライブラリでトークンが処理されます。未加工プロトコルを使用している場合は、このセクションの説明に従ってトークンを取得し、Authorization: Bearer <valid Oauth 2.0 token> としてヘッダーに追加します。

変更前

Authorization: key=AIzaSyZ-1u...0GBYzPu7Udno5aA

変更後

Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

サーバー環境の詳細に応じて、Firebase サービスへのサーバー リクエストを認可するために、これらの戦略の組み合わせを使用します。

  • Google アプリケーションのデフォルト認証情報(ADC)
  • サービス アカウントの JSON ファイル
  • サービス アカウントから派生した、有効期間が短い OAuth 2.0 アクセス トークン

アプリケーションが Compute EngineGoogle Kubernetes EngineApp Engine、Cloud Functions(Cloud Functions for Firebase を含む)のいずれかで実行されている場合は、アプリケーションのデフォルト認証情報(ADC)を使用してください。ADC では既存のデフォルト サービス アカウントを使用してリクエストを認可するための認証情報を取得します。また、環境変数 GOOGLE_APPLICATION_CREDENTIALS を使用して、柔軟なローカルテストも実現します。認可フローを最大限に自動化するには、ADC を Admin SDK サーバー ライブラリと一緒に使用してください。

アプリケーションが Google 以外のサーバー環境で実行されている場合、Firebase プロジェクトからサービス アカウントの JSON ファイルをダウンロードする必要があります。秘密鍵ファイルが含まれているファイル システムにアクセスできる場合は、環境変数 GOOGLE_APPLICATION_CREDENTIALS を使用して、手動で取得した認証情報でリクエストを認可できます。こうしたファイル アクセス権がない場合は、サービス アカウント ファイルをコード内で参照する必要があります。この操作は、認証情報が流出する危険性があるため、細心の注意を払って行ってください。

ADC を使用して認証情報を提供する

Google アプリケーションのデフォルト認証情報(ADC)では、以下の順番で認証情報が確認されます。

  1. ADC が、環境変数 GOOGLE_APPLICATION_CREDENTIALS が設定されているかどうかを確認します。変数が設定されている場合、ADC はその変数が指しているサービス アカウント ファイルを使用します。

  2. 環境変数が設定されていない場合、ADC はサービスで実行されているアプリケーションに応じて、Compute EngineGoogle Kubernetes EngineApp Engine、Cloud Functions によって提供されているデフォルトのサービス アカウントを使用します。

  3. ADC が上記のどの認証情報も使用できない場合、エラーが発生します。

次の Admin SDK サンプルコードは、これらのプロセスを表しています。このサンプルでは、アプリケーション認証情報は明示的には指定されていません。ただし、環境変数が設定されているか、アプリケーションが Compute EngineGoogle Kubernetes EngineApp Engine、Cloud Functions のいずれかで実行されている限り、ADC は認証情報を暗黙的に検出できます。

Node.js

admin.initializeApp({
  credential: admin.credential.applicationDefault(),
});

Java

FirebaseOptions options = FirebaseOptions.builder()
    .setCredentials(GoogleCredentials.getApplicationDefault())
    .setDatabaseUrl("https://<DATABASE_NAME>.firebaseio.com/")
    .build();

FirebaseApp.initializeApp(options);

Python

default_app = firebase_admin.initialize_app()

Go

app, err := firebase.NewApp(context.Background(), nil)
if err != nil {
	log.Fatalf("error initializing app: %v\n", err)
}

C#

FirebaseApp.Create(new AppOptions()
{
    Credential = GoogleCredential.GetApplicationDefault(),
});

認証情報を手動で提供する

Firebase プロジェクトでは Google サービス アカウントがサポートされています。これを使用して、アプリサーバーまたは信頼できる環境から Firebase サーバー API を呼び出せます。コードをローカルで開発している、または アプリケーションをオンプレミスでデプロイしている場合、このサービス アカウントで取得した認証情報を使用してサーバー リクエストを認可することができます。

サービス アカウントを認証して Firebase サービスへのアクセスを認可するには、秘密鍵ファイルを JSON 形式で生成する必要があります。

サービス アカウント用の秘密鍵ファイルを生成するには:

  1. Firebase コンソールで、[設定] > [サービス アカウント] を選択します。

  2. [新しい秘密鍵の生成] をクリックし、[キーを生成] をクリックして確定します。

  3. キーを含む JSON ファイルを安全に保管します。

サービス アカウントを介して認可する場合、アプリケーションの認証情報を指定するには 2 つの選択肢があります。GOOGLE_APPLICATION_CREDENTIALS 環境変数を設定することも、サービス アカウント キーへのパスをコード内で明示的に示すこともできます。 1 つ目の選択肢のほうが安全であるため、そちらを強くおすすめします。

環境変数を設定するには:

環境変数 GOOGLE_APPLICATION_CREDENTIALS を、サービス アカウント キーが含まれる JSON ファイルのファイルパスに設定します。 この変数は現在のシェル セッションにのみ適用されるので、新しいセッションを開く場合は、変数を再度設定してください。

Linux または macOS

export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/service-account-file.json"

Windows

PowerShell を使用する場合:

$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\service-account-file.json"

上記の手順を完了すると、アプリケーションのデフォルト認証情報(ADC)は認証情報を暗黙的に判別し、Google 以外の環境でテストまたは実行する際にサービス アカウントの認証情報を使用できるようになります。

認証情報を使用してアクセス トークンを作成する

次に示すように、有効期間の短い OAuth 2.0 アクセス トークンを取得するために、使用する言語の Google 認証ライブラリと一緒に Firebase 認証情報を使用します。

node.js

 function getAccessToken() {
  return new Promise(function(resolve, reject) {
    const key = require('../placeholders/service-account.json');
    const jwtClient = new google.auth.JWT(
      key.client_email,
      null,
      key.private_key,
      SCOPES,
      null
    );
    jwtClient.authorize(function(err, tokens) {
      if (err) {
        reject(err);
        return;
      }
      resolve(tokens.access_token);
    });
  });
}

この例では、Google API クライアント ライブラリはリクエストを JSON Web Token(JWT)で認証します。詳細については、JSON Web Token をご覧ください。

Python

def _get_access_token():
  """Retrieve a valid access token that can be used to authorize requests.

  :return: Access token.
  """
  credentials = service_account.Credentials.from_service_account_file(
    'service-account.json', scopes=SCOPES)
  request = google.auth.transport.requests.Request()
  credentials.refresh(request)
  return credentials.token

Java

private static String getAccessToken() throws IOException {
  GoogleCredentials googleCredentials = GoogleCredentials
          .fromStream(new FileInputStream("service-account.json"))
          .createScoped(Arrays.asList(SCOPES));
  googleCredentials.refresh();
  return googleCredentials.getAccessToken().getTokenValue();
}

アクセス トークンが期限切れになると、更新されたアクセス トークンを取得するために、トークンの更新メソッドが自動的に呼び出されます。

FCM へのアクセスを認可するには、スコープ https://www.googleapis.com/auth/firebase.messaging をリクエストします。

アクセス トークンを HTTP リクエスト ヘッダーに追加するには:

トークンを Authorization ヘッダーの値として Authorization: Bearer <access_token> の形式で追加します。

node.js

headers: {
  'Authorization': 'Bearer ' + accessToken
}

Python

headers = {
  'Authorization': 'Bearer ' + _get_access_token(),
  'Content-Type': 'application/json; UTF-8',
}

Java

URL url = new URL(BASE_URL + FCM_SEND_ENDPOINT);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestProperty("Authorization", "Bearer " + getServiceAccountAccessToken());
httpURLConnection.setRequestProperty("Content-Type", "application/json; UTF-8");
return httpURLConnection;

送信リクエストのペイロードを更新する

FCM HTTP v1 では、JSON メッセージ ペイロードの構造が大幅に変更されています。異なるクライアント プラットフォームで受信されたメッセージが正しく処理されるための変更が主ですが、プラットフォームに合わせてメッセージ フィールドをより柔軟にカスタマイズできるようになっています(このカスタマイズは「オーバーライド」とも言います)。

HTTP v1 の理解を深めるには、このセクションで紹介する例に加えて、プラットフォーム間でのメッセージのカスタマイズAPI リファレンスをご確認ください。

例: シンプルな通知メッセージ

ここでは、title フィールド、body フィールド、data フィールドのみを含む非常にシンプルな通知ペイロードを比較し、以前のペイロードと HTTP v1 ペイロードの基本的な違いを示します。

変更前

{
  "to": "/topics/news",
  "notification": {
    "title": "Breaking News",
    "body": "New news story available."
  },
  "data": {
    "story_id": "story_12345"
  }
}

変更後

{
  "message": {
    "topic": "news",
    "notification": {
      "title": "Breaking News",
      "body": "New news story available."
    },
    "data": {
      "story_id": "story_12345"
    }
  }
}

例: ネストされた JSON データ

以前の Messaging API とは異なり、HTTP v1 API では data フィールドでネストされた JSON 値はサポートされていません。 JSON から文字列への変換が必要です。

変更前

{
  ...
  "data": {
    "keysandvalues": {"key1": "value1", "key2": 123}
  }
}

変更後

{
  "message": {
   ...
    "data": {
      "keysandvalues": "{\"key1\": \"value1\", \"key2\": 123}"
    }
  }
}

例: 複数のプラットフォームをターゲットにする

マルチプラットフォーム ターゲティングを有効にする場合、以前の API ではバックエンドでオーバーライドを実行しました。これとは対照的に、HTTP v1 には、プラットフォーム間の相違をはっきりと可視的に示すプラットフォーム固有のキーブロックが用意されています。そのため、次の例で示すように、常に 1 つのリクエストで複数のプラットフォームをターゲットにできます。

変更前

// Android
{
  "to": "/topics/news",
  "notification": {
    "title": "Breaking News",
    "body": "New news story available.",
    "click_action": "TOP_STORY_ACTIVITY"
  },
  "data": {
    "story_id": "story_12345"
  }
}
// Apple
{
  "to": "/topics/news",
  "notification": {
    "title": "Breaking News",
    "body": "New news story available.",
    "click_action": "HANDLE_BREAKING_NEWS"
  },
  "data": {
    "story_id": "story_12345"
  }
}

変更後

{
  "message": {
    "topic": "news",
    "notification": {
      "title": "Breaking News",
      "body": "New news story available."
    },
    "data": {
      "story_id": "story_12345"
    },
    "android": {
      "notification": {
        "click_action": "TOP_STORY_ACTIVITY"
      }
    },
    "apns": {
      "payload": {
        "aps": {
          "category" : "NEW_MESSAGE_CATEGORY"
        }
      }
    }
  }
}

例: プラットフォーム オーバーライドによるカスタマイズ

HTTP v1 API を使用すると、メッセージのクロスプラットフォーム ターゲティングが簡単にできるだけでなく、プラットフォームに合わせてメッセージを柔軟にカスタマイズすることもできます。

変更前

// Android
{
  "to": "/topics/news",
  "notification": {
    "title": "Breaking News",
    "body": "Check out the Top Story.",
    "click_action": "TOP_STORY_ACTIVITY"
  },
  "data": {
    "story_id": "story_12345"
  }
}
// Apple
{
  "to": "/topics/news",
  "notification": {
    "title": "Breaking News",
    "body": "New news story available.",
    "click_action": "HANDLE_BREAKING_NEWS"
  },
  "data": {
    "story_id": "story_12345"
  }
}

変更後

{
  "message": {
    "topic": "news",
    "notification": {
      "title": "Breaking News",
      "body": "New news story available."
    },
    "data": {
      "story_id": "story_12345"
    },
    "android": {
      "notification": {
        "click_action": "TOP_STORY_ACTIVITY",
        "body": "Check out the Top Story"
      }
    },
    "apns": {
      "payload": {
        "aps": {
          "category" : "NEW_MESSAGE_CATEGORY"
        }
      }
    }
  }
}

例: 特定のデバイスをターゲットに設定する

HTTP v1 API を使用して特定のデバイスをターゲットにするには、to キーではなく、token キーでデバイスの現在の登録トークンを指定します。

変更前

  { "notification": {
      "body": "This is an FCM notification message!",
      "title": "FCM Message"
    },
    "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
  }

変更後

{
   "message":{
      "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
      "notification":{
        "body":"This is an FCM notification message!",
        "title":"FCM Message"
      }
   }
}

FCM HTTP v1 API のその他の例や詳細については、以下をご覧ください。