Sendeanfragen autorisieren

Anfragen, die von Ihrem App-Server oder einer vertrauenswürdigen Umgebung an FCM gesendet werden, müssen autorisiert sein. Beachten Sie die folgenden wichtigen Unterschiede zwischen der eingestellten Legacy-HTTP API und der HTTP v1 API-Autorisierung:

  • Die FCM HTTP v1 API autorisiert Anfragen mit einem kurzlebigen OAuth 2.0-Zugriffstoken. Zum Erstellen dieses Tokens kannst du die Standardanmeldedaten der Google-Anwendung (in Google-Serverumgebungen) verwenden und/oder die erforderlichen Anmeldedaten manuell aus einer JSON-Datei mit dem privaten Schlüssel abrufen, die für ein Dienstkonto generiert wurde. Wenn Sie die Firebase Admin SDK zum Senden von Nachrichten verwenden, wird das Token von der Bibliothek für Sie verwaltet.
  • Die verworfenen Legacy-Protokolle können nur langlebige API-Schlüssel verwenden, die über die Firebase-Konsole abgerufen wurden.

Sendeanfragen für HTTP v1 autorisieren

Je nach Details Ihrer Serverumgebung können Sie eine Kombination dieser Strategien verwenden, um Serveranfragen an Firebase-Dienste zu autorisieren:

  • Standardanmeldedaten für Google-Anwendungen (Application Default Credentials, ADC)
  • Eine JSON-Datei für das Dienstkonto
  • Ein kurzlebiges OAuth 2.0-Zugriffstoken, das von einem Dienstkonto abgeleitet wurde

Wenn Ihre Anwendung auf Compute Engine, Google Kubernetes Engine, App Engine oder Cloud Functions (einschließlich Cloud Functions for Firebase) ausgeführt wird, verwenden Sie Standardanmeldedaten für Anwendungen (Application Default Credentials, ADC). ADC verwendet Ihr vorhandenes Standarddienstkonto, um Anmeldedaten zur Autorisierung von Anfragen abzurufen. Außerdem ermöglicht ADC flexible lokale Tests über die Umgebungsvariable GOOGLE_APPLICATION_CREDENTIALS. Für eine umfassende Automatisierung des Autorisierungsablaufs sollten Sie ADC mit Admin SDK-Serverbibliotheken verwenden.

Wenn Ihre Anwendung in einer Serverumgebung ausgeführt wird, die nicht zu Google gehört, müssen Sie eine JSON-Datei für das Dienstkonto aus Ihrem Firebase-Projekt herunterladen. Solange Sie Zugriff auf ein Dateisystem mit der privaten Schlüsseldatei haben, können Sie die Umgebungsvariable GOOGLE_APPLICATION_CREDENTIALS verwenden, um Anfragen mit diesen manuell abgerufenen Anmeldedaten zu autorisieren. Wenn Sie keinen solchen Dateizugriff haben, müssen Sie in Ihrem Code auf die Dienstkontodatei verweisen. Dies sollte aufgrund des Risikos, dass Ihre Anmeldedaten offengelegt werden, mit äußerster Vorsicht erfolgen.

Anmeldedaten mit ADC bereitstellen

Bei Standardanmeldedaten für Google-Anwendungen (Application Default Credentials, ADC) wird in der folgenden Reihenfolge nach Ihren Anmeldedaten gesucht:

  1. ADC prüft, ob die Umgebungsvariable GOOGLE_APPLICATION_CREDENTIALS festgelegt ist. Ist dies der Fall, wird die Dienstkontodatei, auf die die Variable verweist, für die Anmeldedaten verwendet.

  2. Wenn die Umgebungsvariable nicht festgelegt ist, verwendet ADC das Standarddienstkonto, das von Compute Engine, Google Kubernetes Engine, App Engine und Cloud Functions für Anwendungen bereitgestellt wird, die für diese Dienste ausgeführt werden.

  3. Wenn die Anmeldedaten weder im ersten noch im zweiten Schritt ermittelt werden können, löst das System einen Fehler aus.

Das folgende Codebeispiel für das Admin SDK veranschaulicht diese Strategie. In diesem Beispiel werden die Anmeldedaten für die Anwendung nicht explizit angegeben. Sie können aber im Rahmen dieses Vorgehens von ADC implizit ermittelt werden, sofern die Umgebungsvariable festgelegt ist oder die Anwendung in Compute Engine, Google Kubernetes Engine, App Engine oder Cloud Functions ausgeführt wird.

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(),
});

Anmeldedaten manuell angeben

Firebase-Projekte unterstützen Google-Dienstkonten, mit denen Sie Firebase-Server-APIs von Ihrem App-Server oder einer vertrauenswürdigen Umgebung aus aufrufen können. Wenn Sie Code lokal entwickeln oder Ihre Anwendung vor Ort bereitstellen, können Sie über dieses Dienstkonto abgerufene Anmeldedaten verwenden, um Serveranfragen zu autorisieren.

Wenn Sie ein Dienstkonto authentifizieren und autorisieren möchten, auf Firebase-Dienste zuzugreifen, müssen Sie eine private Schlüsseldatei im JSON-Format generieren.

So generieren Sie eine Datei mit einem privaten Schlüssel für Ihr Dienstkonto:

  1. Öffnen Sie in der Firebase-Konsole Einstellungen > Dienstkonten.

  2. Klicke auf Neuen privaten Schlüssel generieren und bestätige die Aktion mit einem Klick auf Schlüssel generieren.

  3. Speichern Sie die JSON-Datei mit dem Schlüssel sicher.

Bei der Autorisierung über ein Dienstkonto haben Sie zwei Möglichkeiten, die Anmeldedaten für Ihre Anwendung bereitzustellen. Sie können entweder die Umgebungsvariable GOOGLE_APPLICATION_CREDENTIALS festlegen oder den Pfad zum Dienstkontoschlüssel explizit im Code übergeben. Die erste Option ist sicherer und wird dringend empfohlen.

So legen Sie die Umgebungsvariable fest:

Legen Sie die Umgebungsvariable GOOGLE_APPLICATION_CREDENTIALS auf den Pfad der JSON-Datei fest, die Ihren Dienstkontoschlüssel enthält. Diese Variable gilt nur für Ihre aktuelle Shellsitzung. Wenn Sie eine neue Sitzung öffnen, müssen Sie die Variable noch einmal festlegen.

Linux oder macOS

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

Windows

Mit PowerShell:

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

Nachdem Sie die oben genannten Schritte ausgeführt haben, können Standardanmeldedaten für Anwendungen (Application Default Credentials, ADC) Ihre Anmeldedaten implizit ermitteln. So können Sie die Anmeldedaten des Dienstkontos verwenden, wenn Sie Tests in Umgebungen ausführen, die nicht von Google stammen.

Anmeldedaten zum Generieren von Zugriffstokens verwenden

Sofern Sie nicht das Admin SDK verwenden, das die Autorisierung automatisch verarbeitet, müssen Sie das Zugriffstoken generieren und hinzufügen, um Anfragen zu senden.

Verwenden Sie Ihre Firebase-Anmeldedaten zusammen mit der Google-Authentifizierungsbibliothek für Ihre bevorzugte Sprache, um ein kurzlebiges OAuth 2.0-Zugriffstoken abzurufen:

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);
    });
  });
}

In diesem Beispiel authentifiziert die Google API-Clientbibliothek die Anfrage mit einem JSON-Webtoken (JWT). Weitere Informationen finden Sie unter JSON Web Tokens.

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();
}

Nach Ablauf des Zugriffstokens wird die Tokenaktualisierungsmethode automatisch aufgerufen, um ein aktualisiertes Zugriffstoken abzurufen.

Fordern Sie den Bereich https://www.googleapis.com/auth/firebase.messaging an, um den Zugriff auf FCM zu autorisieren.

So fügen Sie das Zugriffstoken einem HTTP-Anfrageheader hinzu:

Fügen Sie das Token als Wert des Headers Authorization im Format Authorization: Bearer <access_token> hinzu:

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;

Sendeanfragen des alten Protokolls autorisieren

Beim alten HTTP-Protokoll muss jede Anfrage den Serverschlüssel aus dem Tab Cloud Messaging des Bereichs Einstellungen der Firebase-Konsole enthalten. Bei XMPP müssen Sie denselben Serverschlüssel verwenden, um eine Verbindung herzustellen.

Legacy-Serverschlüssel migrieren

Seit März 2020 werden von FCM keine Legacy-Serverschlüssel mehr erstellt. Vorhandene alte Serverschlüssel funktionieren weiterhin. Wir empfehlen jedoch, stattdessen die neuere Version des Schlüssels zu verwenden, der in der Firebase-Konsole als Serverschlüssel gekennzeichnet ist.

Wenn Sie einen vorhandenen Legacy-Serverschlüssel löschen möchten, können Sie dies in der Google Cloud Console tun.

HTTP-Anfragen autorisieren

Eine Nachrichtenanfrage besteht aus zwei Teilen: dem HTTP-Header und dem HTTP-Text. Der HTTP-Header muss die folgenden Header enthalten:

  • Authorization: key=YOUR_SERVER_KEY
    Achten Sie darauf, dass dies der Serverschlüssel ist, dessen Wert im Bereich Einstellungen der Firebase Console auf dem Tab Cloud Messaging verfügbar ist. Android-, Apple-Plattform- und Browserschlüssel werden von FCM abgelehnt.
  • Content-Type: application/json für JSON; application/x-www-form-urlencoded;charset=UTF-8 für Nur-Text.
    Wenn Sie Content-Type weglassen, wird davon ausgegangen, dass das Format Nur-Text ist.

Beispiel:

Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{
  "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
  "data" : {
    ...
  },
}

Ausführliche Informationen zum Erstellen von Sendeaufträgen finden Sie unter Sendeaufträge erstellen. Die Referenz zum alten HTTP-Protokoll enthält eine Liste aller Parameter, die Ihre Nachricht enthalten kann.

Gültigkeit eines Serverschlüssels prüfen

Wenn Sie beim Senden von Nachrichten Authentifizierungsfehler erhalten, prüfen Sie die Gültigkeit Ihres Serverschlüssels. Führen Sie unter Linux beispielsweise den folgenden Befehl aus:

api_key=YOUR_SERVER_KEY

curl --header "Authorization: key=$api_key" \
     --header Content-Type:"application/json" \
     https://fcm.googleapis.com/fcm/send \
     -d "{\"registration_ids\":[\"ABC\"]}"

Wenn du den HTTP-Statuscode 401 erhältst, ist dein Serverschlüssel ungültig.

XMPP-Verbindung autorisieren

Mit XMPP können Sie eine dauerhafte, asynchrone, bidirektionale Verbindung zu FCM-Servern aufrechterhalten. Über die Verbindung können Nachrichten zwischen Ihrem Server und den mit FCM verbundenen Geräten Ihrer Nutzer gesendet und empfangen werden.

Sie können die meisten XMPP-Bibliotheken verwenden, um eine langlebige Verbindung zu FCM zu verwalten. Der XMPP-Endpunkt wird unter fcm-xmpp.googleapis.com:5235 ausgeführt. Wenn Sie die Funktionalität mit nicht produktionsnahen Nutzern testen, sollten Sie stattdessen eine Verbindung zum Pre-Production-Server unter fcm-xmpp.googleapis.com:5236 herstellen (beachten Sie den anderen Port).

Regelmäßige Tests in der Vorproduktion (einer kleineren Umgebung, in der die neuesten FCM-Builds ausgeführt werden) sind hilfreich, um echte Nutzer von Testcode zu isolieren. Für Testgeräte und Testcode, die eine Verbindung zu fcm-xmpp.googleapis.com:5236 herstellen, sollte eine andere FCM-Sender-ID verwendet werden, um zu vermeiden, dass Testnachrichten an Produktionsnutzer oder Upstream-Nachrichten aus dem Produktionstraffic über Testverbindungen gesendet werden.

Für die Verbindung gelten zwei wichtige Anforderungen:

  • Sie müssen eine TLS-Verbindung (Transport Layer Security) initiieren. Beachte, dass FCM die STARTTLS-Erweiterung derzeit nicht unterstützt.
  • FCM erfordert einen SASL PLAIN-Authentifizierungsmechanismus mit <your_FCM_Sender_Id>@fcm.googleapis.com (FCM Absender-ID) und dem Serverschlüssel als Passwort. Diese Werte finden Sie im Bereich Einstellungen der Firebase Console auf dem Tab Cloud Messaging.

Wenn die Verbindung unterbrochen wird, sollten Sie sofort eine neue Verbindung herstellen. Es ist nicht nötig, nach einer Trennung nach der Authentifizierung zurückzufahren. Für jede Absender-ID erlaubt FCM 2.500 parallele Verbindungen.

In den folgenden Snippets wird veranschaulicht, wie die Authentifizierung und Autorisierung für eine XMPP-Verbindung zu FCM durchgeführt wird.

XMPP-Server

Der XMPP-Server fordert eine Verbindung zu FCM an.

<stream:stream to="fcm.googleapis.com"
        version="1.0" xmlns="jabber:client"
        xmlns:stream="http://etherx.jabber.org/streams">

FCM

FCM öffnet die Verbindung und fordert einen Authentifizierungsmechanismus an, einschließlich der Methode PLAIN.

<stream:features>
  <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
    <mechanism>X-OAUTH2</mechanism>
    <mechanism>X-GOOGLE-TOKEN</mechanism>
    <mechanism>PLAIN</mechanism>
  </mechanisms>
</stream:features>

XMPP-Server

Der XMPP-Server muss mit der PLAIN-Authentifizierungsmethode antworten und dabei den Serverschlüssel aus dem Bereich Einstellungen der Firebase-Konsole auf dem Tab Cloud Messaging angeben.

<auth mechanism="PLAIN"
xmlns="urn:ietf:params:xml:ns:xmpp-sasl">MTI2MjAwMzQ3OTMzQHByb2plY3RzLmdjbS5hb
mFTeUIzcmNaTmtmbnFLZEZiOW1oekNCaVlwT1JEQTJKV1d0dw==</auth>

FCM

<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>

XMPP-Server

<stream:stream to="fcm.googleapis.com"
        version="1.0" xmlns="jabber:client"
        xmlns:stream="http://etherx.jabber.org/streams">

FCM

<stream:features>
  <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>
  <session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>
</stream:features>

XMPP-Server

<iq type="set">
  <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"></bind>
</iq>

FCM

<iq type="result">
  <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
    <jid>SENDER_ID@fcm.googleapis.com/RESOURCE</jid>
  </bind>
</iq>

Hinweis: FCM verwendet beim Weiterleiten von Nachrichten nicht die gebundene Ressource.

Ausführliche Informationen zum Erstellen von Sendeaufträgen finden Sie unter Sendeaufträge erstellen. In der Legacy XMPP Protocol Reference (Referenz zum Legacy XMPP-Protokoll) finden Sie eine Liste aller Parameter, die Ihre Nachricht enthalten kann.