Autoryzuj żądania wysył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 FCM HTTP v1 API 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 aplikacji Google (w środowiskach serwerów Google) lub ręcznie uzyskać wymagane dane uwierzytelniające z pliku klucza prywatnego JSON wygenerowanego dla konta usługi. Jeśli do wysyłania wiadomości używasz pakietu 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
  • Krótkotrwały token dostępu OAuth 2.0 pozyskany z konta usługi

Jeśli Twoja aplikacja działa w Compute Engine, Google Kubernetes Engine, App Engine lub Cloud Functions (w tym Cloud Functions dla Firebase), użyj domyślnego uwierzytelniania aplikacji (ADC). ADC używa Twojego obecnego domyślnego konta usługi do uzyskiwania danych logowania do autoryzowania żądań, a ADC umożliwia elastyczne testowanie lokalne za pomocą zmiennej środowiskowej GOOGLE_APPLICATION_CREDENTIALS. Aby w pełni zautomatyzować proces autoryzacji, używaj ADC razem z bibliotekami serwera pakietu Admin SDK.

Jeśli Twoja aplikacja działa w środowisku serwera innym niż Google, musisz pobrać plik JSON konta usługi ze swojego projektu Firebase. Jeśli masz dostęp do systemu plików zawierającego plik klucza prywatnego, możesz używać zmiennej środowiskowej GOOGLE_APPLICATION_CREDENTIALS do autoryzowania żądań z użyciem tych danych uzyskanych ręcznie. Jeśli nie masz takiego dostępu, musisz odwołać się do pliku konta usługi w swoim kodzie. Należy to robić z dużą ostrożnością ze względu na ryzyko ujawnienia danych logowania.

Podaj dane logowania za pomocą ADC

Funkcja domyślnego uwierzytelniania aplikacji Google (ADC) sprawdza Twoje dane logowania w tej kolejności:

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

  2. Jeśli zmienna środowiskowa nie jest ustawiona, ADC używa domyślnego konta usługi udostępnianego przez Compute Engine, Google Kubernetes Engine, App Engine i Cloud Functions dla aplikacji działających w tych usługach.

  3. Jeśli ADC nie może użyć tych danych, system zgłasza błąd.

Poniższy przykładowy kod pakietu Admin SDK ilustruje tę strategię. W przykładzie nie określono bezpośrednio danych logowania do 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 lub 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(),
});

Podaj dane logowania ręcznie

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 zaufanego środowiska. Jeśli programujesz kod lokalnie lub wdrażasz aplikację lokalnie, możesz autoryzować żądania do serwera za pomocą danych logowania uzyskanych z tego konta usługi.

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

Za pomocą 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 tworzenia tokenów dostępu

Jeśli nie korzystasz z pakietu Admin SDK, który automatycznie obsługuje autoryzację, musisz wygenerować token dostępu i dodać go, aby wysyłać żądania.

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

Po wygaśnięciu tokena dostępu metoda odświeżania tokena jest wywoływana automatycznie w celu pobrania zaktualizowanego tokena 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;

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 do nawiązania połączenia.

Migracja starszych kluczy serwera

Od marca 2020 r. usługa FCM przestała tworzyć starsze klucze serwera. Istniejące starsze klucze serwera będą nadal działać, ale zalecamy korzystanie z nowszej wersji klucza o nazwie Klucz serwera w konsoli Firebase.

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

Autoryzacja żą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=YOUR_SERVER_KEY
    Upewnij się, że chodzi o klucz serwera, którego wartość jest dostępna na karcie Komunikacja w chmurze panelu Ustawienia w konsoli Firebase. Klucze Androida, platformy Apple oraz 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 właściwość Content-Type, przyjmuje się, że jest to zwykły tekst.

Przykład:

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

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

Szczegółowe informacje o tworzeniu żądań wysyłania znajdziesz w artykule o tworzeniu żądań wysyłania. Omówienie starszych protokołów HTTP zawiera listę wszystkich parametrów, które może zawierać wiadomość.

Sprawdzanie poprawnoś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, oznacza to, że klucz serwera jest nieprawidłowy.

Autoryzacja połączenia XMPP

XMPP zapewnia stałe, asynchroniczne i dwukierunkowe połączenie z serwerami FCM. To połączenie może służyć do wysyłania i odbierania wiadomości między Twoim 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. Aby przetestować funkcje na kontach użytkowników nieprodukcyjnych, połącz się z serwerem w wersji przedprodukcyjnej pod adresem fcm-xmpp.googleapis.com:5236 (zwróć uwagę na inny port).

Regularne testy w wersji przedprodukcyjnej (w mniejszym środowisku, w którym są uruchamiane najnowsze kompilacje FCM) pomagają odizolować rzeczywistych 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 ma 2 ważne wymagania:

  • Musisz zainicjować połączenie TLS. Pamiętaj, że FCM nie obsługuje obecnie rozszerzenia STARTTLS.
  • FCM wymaga mechanizmu uwierzytelniania SASL PLAIN, który używa <your_FCM_Sender_Id>@fcm.googleapis.com (identyfikator nadawcy FCM) 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 jakimkolwiek momencie nie uda się nawiązać połączenia, musisz natychmiast połączyć się ponownie. Po rozłączeniu, które następuje po uwierzytelnieniu, nie trzeba wycofywać się. Do każdego identyfikatora nadawcy FCM dopuszcza 2500 równoległych połączeń.

Poniżej znajdziesz fragmenty kodu, które pokazują, jak przeprowadzić uwierzytelnianie i autoryzację połączenia XMPP z FCM.

Serwer XMPP

Serwer XMPP żąda połączenia 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 wysyła żądanie 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 odpowiedzieć, korzystając z 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: FCM nie używa powiązanego zasobu podczas routingu wiadomości.

Szczegółowe informacje o tworzeniu żądań wysyłania znajdziesz w artykule o tworzeniu żądań wysyłania. Źródło protokołu XMPP zawiera listę wszystkich parametrów, które może zawierać wiadomość.