Autoryzowanie żądań wysłania

Żądania wysyłane do FCM z serwera aplikacji lub zaufanego środowiska muszą być autoryzowane. Zwróć uwagę na te ważne różnice między autoryzacją w starszym interfejsie HTTP API i interfejsie HTTP API w wersji 1:

  • Interfejs API HTTP w wersji 1 FCM autoryzuje żądania za pomocą krótkotrwałego tokena dostępu OAuth 2.0. Aby utworzyć ten token, możesz użyć domyślnych danych logowania do aplikacji Google (w środowiskach serwerów Google) lub ręcznie uzyskać wymagane dane logowania z pliku JSON z kluczem prywatnym wygenerowanym dla konta usługi. Jeśli do wysyłania wiadomości używasz funkcji Firebase Admin SDK, biblioteka sama zajmie się tokenem.
  • Wycofane starsze protokoły mogą używać tylko długotrwałych kluczy API uzyskanych z konsoli Firebase.

Autoryzowanie żądań wysyłania HTTP v1

W zależności od szczegółów środowiska serwera użyj kombinacji tych strategii, aby autoryzować żądania serwera do usług Firebase:

  • Domyślne uwierzytelnianie aplikacji Google (ADC)
  • plik JSON konta usługi;
  • Ograniczony czasowo token dostępu OAuth 2.0 utworzony na podstawie konta usługi

Jeśli aplikacja działa w usłudze Compute Engine, Google Kubernetes Engine, App Engine lub Cloud Functions (w tym Cloud Functions for Firebase), użyj domyślnych poświadczeń aplikacji (ADC). ADC używa istniejącego domyślnego konta usługi do uzyskiwania danych logowania na potrzeby autoryzacji żądań. Pozwala też na elastyczne testowanie lokalne za pomocą zmiennej środowiskowej GOOGLE_APPLICATION_CREDENTIALS. Aby w pełni zautomatyzować proces autoryzacji, użyj ADC razem z bibliotekami serwera Admin SDK.

Jeśli aplikacja działa w środowisku serwera spoza Google, musisz pobrać plik JSON konta usługi z Twojego projektu Firebase. Jeśli masz dostęp do systemu plików zawierającego plik klucza prywatnego, możesz użyć zmiennej środowiskowej GOOGLE_APPLICATION_CREDENTIALS, aby autoryzować żądania za pomocą tych danych logowania uzyskanych ręcznie. Jeśli nie masz dostępu do takich plików, musisz w kodze odwoływać się do pliku konta usługi. Należy to robić z bardzo dużą ostrożnością ze względu na ryzyko ujawnienia danych logowania.

Podawanie danych logowania za pomocą ADC

Domyślne uwierzytelnianie aplikacji Google (ADC) sprawdza Twoje poświadczenia w takim porządku:

  1. ADC sprawdza, czy ustawiona jest zmienna środowiskowa GOOGLE_APPLICATION_CREDENTIALS. Jeśli zmienna jest ustawiona, ADC używa pliku konta usługi, do którego ona wskazuje.

  2. Jeśli zmienna środowiskowa nie jest ustawiona, ADC używa domyślnego konta usługi, które Compute Engine, Google Kubernetes Engine, App Engine i Cloud Functions udostępniają aplikacjom działającym w tych usługach.

  3. Jeśli ADC nie może użyć żadnego z tych danych logowania, system wyświetla błąd.

Przykładowy kod pakietu SDK administratora ilustruje tę strategię. Przykład nie zawiera wyraźnego określenia danych logowania aplikacji. Jednak ADC może znaleźć te dane logowania w sposób domyślny, o ile zmienna środowiskowa jest ustawiona lub aplikacja działa w kontekście Compute Engine, Google Kubernetes Engine, App Engine lub funkcji Cloud.

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

Ręczne podawanie danych logowania

Projekty Firebase obsługują konta usługi Google, których możesz używać do wywoływania interfejsów API serwera Firebase z serwera aplikacji lub z zaufanego środowiska. Jeśli kod tworzysz lokalnie lub wdrażasz aplikację lokalnie, możesz użyć danych logowania uzyskanych za pomocą tego konta usługi, aby autoryzować żądania serwera.

Aby uwierzytelnić konto usługi i zezwolić mu na dostęp do usług Firebase, musisz wygenerować plik klucza prywatnego w formacie JSON.

Aby wygenerować plik klucza prywatnego dla konta usługi:

  1. W konsoli Firebase otwórz Ustawienia > Konta usługi.

  2. Kliknij Wygeneruj nowy klucz prywatny, a następnie potwierdź, klikając Wygeneruj klucz.

  3. Bezpiecznie przechowuj plik JSON zawierający klucz.

Podczas autoryzacji za pomocą konta usługi masz 2 możliwości przekazania danych logowania do aplikacji. Możesz ustawić zmienną środowiskową GOOGLE_APPLICATION_CREDENTIALS lub w kodzie wyraźnie podać ścieżkę do klucza konta usługi. Pierwsza opcja jest bezpieczniejsza i zdecydowanie zalecana.

Aby ustawić zmienną środowiskową:

Ustaw zmienną środowiskową GOOGLE_APPLICATION_CREDENTIALS na ścieżkę do pliku JSON zawierającego klucz konta usługi. Ta zmienna dotyczy tylko bieżącej sesji powłoki, więc jeśli otworzysz nową sesję, musisz ponownie ustawić zmienną.

Linux lub macOS

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

Windows

W PowerShell:

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

Po wykonaniu powyższych czynności aplikacja domyślne dane logowania (ADC) może domyślnie określić Twoje dane logowania, co pozwoli Ci używać danych logowania konta usługi podczas testowania lub uruchamiania w środowiskach innych niż Google.

Używanie danych logowania do generowania tokenów dostępu

Jeśli nie używasz pakietu SDK do zarządzania, który automatycznie obsługuje autoryzację, musisz wygenerować token dostępu i dodać go do żądań wysyłania.

Aby pobrać krótkotrwały token dostępu OAuth 2.0, użyj danych logowania Firebase wraz z biblioteką Google Auth Library w preferowanym języku:

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

W tym przykładzie biblioteka klienta interfejsu Google API uwierzytelnia żądanie za pomocą tokena sieciowego JSON (JWT). Więcej informacji znajdziesz w artykule Tokeny sieciowe JSON.

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

Gdy token dostępu wygaśnie, metoda odświeżania tokena zostanie wywołana automatycznie, aby pobrać zaktualizowany token dostępu.

Aby autoryzować dostęp do FCM, poproś o zakres https://www.googleapis.com/auth/firebase.messaging.

Aby dodać token dostępu do nagłówka żądania HTTP:

Dodaj token jako wartość nagłówka Authorization w formacie 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;

Autoryzowanie żądań wysyłania w ramach starszego protokołu

.

W przypadku starszego protokołu HTTP każde żądanie musi zawierać klucz serwera z karty Komunikacja w chmurze w panelu Ustawienia konsoli Firebase. W przypadku XMPP musisz użyć tego samego klucza serwera, aby nawiązać połączenie.

Migracja starszych kluczy serwera

Od marca 2020 r. FCM nie tworzy już starszych kluczy serwera. Dotychczasowe starsze klucze serwera będą nadal działać, ale zalecamy używanie nowszej wersji klucza o nazwie Klucz serwera konsoliFirebase.

Jeśli chcesz usunąć dotychczasowy klucz serwera, możesz to zrobić w konsoli Google Cloud.

Autoryzowanie żądań HTTP

Żądanie wiadomości składa się z 2 części: nagłówka HTTP i treści HTTP. Nagłówek HTTP musi zawierać te nagłówki:

  • Authorization: key=TWÓJ_KLUCZ_SERWERA
    Upewnij się, że jest to klucz serwera, którego wartość jest dostępna na karcie Cloud Messaging w panelu Ustawienia konsoli Firebase. Klucze Androida, platformy Apple i przeglądarki są odrzucane przez FCM.
  • Content-Type: application/json dla JSON; application/x-www-form-urlencoded;charset=UTF-8 dla zwykłego tekstu.
    Jeśli pominiesz parametr Content-Type, zostanie domyślnie przyjęte, że format jest zwykłym tekstem.

Przykład:

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

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

Więcej informacji o tworzeniu żądań wysyłania znajdziesz w artykule Tworzenie żądań wysyłania. Przewodnik po starszym protokole HTTP zawiera listę wszystkich parametrów, które może zawierać wiadomość.

Sprawdzanie ważności klucza serwera

Jeśli podczas wysyłania wiadomości otrzymujesz błędy uwierzytelniania, sprawdź ważność klucza serwera. Na przykład w systemie Linux uruchom to polecenie:

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\"]}"

Jeśli otrzymasz kod stanu HTTP 401, Twój klucz serwera jest nieprawidłowy.

Autoryzowanie połączenia XMPP

.

Dzięki XMPP możesz utrzymywać trwałe, asynchroniczne, dwukierunkowe połączenie z serwerami FCM. Połączenie to umożliwia wysyłanie i odbieranie wiadomości między serwerem a urządzeniami użytkowników połączonymi z FCM.

Do zarządzania długotrwałym połączeniem z FCM możesz używać większości bibliotek XMPP. Punkt końcowy XMPP działa w czasie fcm-xmpp.googleapis.com:5235. Podczas testowania funkcji z użytkownikami spoza środowiska produkcyjnego należy połączyć się z serwerem w środowisku przedprodukcyjnym pod adresem fcm-xmpp.googleapis.com:5236 (zwróć uwagę na inny port).

Regularne testowanie w środowisku przedprodukcyjnym (mniejszym środowisku, w którym działają najnowsze wersje FCM) jest korzystne, ponieważ pozwala oddzielić prawdziwych użytkowników od kodu testowego. Urządzenia testowe i kod testowy łączące się z fcm-xmpp.googleapis.com:5236 powinny używać innego identyfikatora nadawcy FCM, aby uniknąć ryzyka wysyłania wiadomości testowych do użytkowników w produkcji lub wysyłania wiadomości z produkcji do użytkowników w ramach połączeń testowych.

Połączenie musi spełniać 2 ważne wymagania:

  • Musisz zainicjować połączenie TLS (Transport Layer Security). Uwaga: FCM nie obsługuje obecnie rozszerzenia STARTTLS.
  • FCM wymaga mechanizmu uwierzytelniania SASL PLAIN za pomocą <your_FCM_Sender_Id>@fcm.googleapis.com (FCM identyfikator nadawcy) i klucza serwera jako hasła. Te wartości są dostępne na karcie Cloud Messaging w panelu Ustawienia konsoli Firebase.

Jeśli w jakimś momencie połączenie zostanie przerwane, natychmiast je nawiążesz. Po rozłączeniu, które nastąpiło po uwierzytelnieniu, nie trzeba wycofywać się z połączenia. W przypadku każdego identyfikatora nadawcyFCM dozwolone są 2500 połączeń równoległych.

Poniższe fragmenty kodu pokazują, jak przeprowadzić uwierzytelnianie i autoryzację w przypadku połączenia XMPP z usługą FCM.

Serwer XMPP

Serwer XMPP prosi o połączenie z FCM

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

FCM

FCM otwiera połączenie i wymaga mechanizmu uwierzytelniania, w tym metody 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>

Serwer XMPP

Serwer XMPP musi odpowiadać przy użyciu metody uwierzytelniania PLAIN, podając klucz serwera z karty Komunikacja w chmurze w panelu Ustawienia konsoli Firebase.

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

FCM

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

Serwer XMPP

<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>

Serwer XMPP

<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>

Uwaga: podczas kierowania wiadomości usługa FCM nie używa zasobów powiązanych.

Więcej informacji o tworzeniu żądań wysyłania znajdziesz w artykule Tworzenie żądań wysyłania. Przestarzała specyfikacja protokołu XMPP zawiera listę wszystkich parametrów, które może zawierać wiadomość.