Autoryzowanie żądań wysłania

Żądania wysyłane do FCM z serwera aplikacji lub zaufanego środowiska muszą być autoryzowane. Zwróć uwagę na te istotne różnice między wycofanym, starszym interfejsem HTTP API a autoryzacją interfejsu HTTP v1 API:

  • Interfejs API HTTP w wersji 1 FCM autoryzuje żądania za pomocą krótkotrwałego tokena dostępu OAuth 2.0. Aby wygenerować 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 interfejsu Firebase Admin SDK, biblioteka zajmuje się tokenem za Ciebie.
  • Wycofane starsze protokoły mogą korzystać tylko z długotrwałych kluczy interfejsu API uzyskanych z konsoli Firebase.

Autoryzacja wysyłania żądań HTTP w wersji 1

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 Twoja aplikacja działa w środowisku Compute Engine, Google Kubernetes Engine, App Engine lub Cloud Functions (w tym Cloud Functions for Firebase), użyj domyślnego uwierzytelniania 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 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ą, ponieważ istnieje ryzyko ujawnienia danych logowania.

Podawanie danych logowania za pomocą ADC

Domyślne uwierzytelnianie aplikacji Google 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. ADC może jednak domyślnie znajdować dane logowania, o ile skonfigurowana jest zmienna środowiskowa lub aplikacja działa w Compute Engine, Google Kubernetes Engine, App Engine albo Cloud Functions.

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 autoryzować je do dostępu 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 opcje udostępniania danych logowania do aplikacji. Możesz ustawić zmienną środowiskową GOOGLE_APPLICATION_CREDENTIALS lub bezpośrednio przekazać ścieżkę do klucza konta usługi w kodzie. 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 ma zastosowanie tylko do bieżącej sesji powłoki, więc jeśli otworzysz nową sesję, ustaw ją ponownie.

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"

Gdy wykonasz powyższe czynności, domyślne dane uwierzytelniające aplikacji (ADC) będą mogły niejawnie określić Twoje dane logowania. Dzięki temu możesz używać danych logowania do konta usługi podczas testowania lub uruchamiania aplikacji 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.

Użyj danych logowania Firebase w połączeniu z biblioteką uwierzytelniania Google w wybranym języku, aby pobrać token dostępu OAuth 2.0 o krótkim czasie ważności:

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 API Google 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 usługi 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;

Autoryzuj żądania wysyłania wysyłanych za pomocą 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 serwerakonsoliFirebase.

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 w przypadku formatu JSON; application/x-www-form-urlencoded;charset=UTF-8 w przypadku 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ź poprawność swojego klucza serwera. Na przykład w Linuksie uruchom następujące 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.

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

Za pomocą większości bibliotek XMPP możesz zarządzać długotrwałym połączeniem z FCM. Punkt końcowy XMPP działa 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 związanego z wysyłaniem wiadomości testowych do użytkowników produkcyjnych lub wysyłaniem wiadomości wychodzących z ruchu produkcyjnego przez połączenia testowe.

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

  • Musisz zainicjować połączenie TLS. 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 Komunikacja w chmurze w panelu Ustawienia w 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ść.