Mengizinkan permintaan kirim

Permintaan yang dikirim ke FCM dari server aplikasi atau lingkungan tepercaya harus diberi otorisasi. Perhatikan perbedaan penting antara otorisasi HTTP API lama yang sudah tidak digunakan lagi dan HTTP v1 API:

  • FCM HTTP v1 API mengizinkan permintaan dengan token akses OAuth 2.0 yang berumur pendek. Untuk membuat token ini, Anda dapat menggunakan Kredensial Default Aplikasi Google (di lingkungan server Google) dan/atau secara manual mendapatkan kredensial yang diperlukan dari file kunci pribadi JSON yang dihasilkan untuk akun layanan. Jika Anda menggunakan Firebase Admin SDK untuk mengirim pesan, library akan menangani token tersebut untuk Anda.
  • Protokol lama yang sudah tidak digunakan lagi hanya dapat menggunakan kunci API yang berumur panjang dari Firebase console.

Mengizinkan permintaan kirim HTTP v1

Tergantung detail lingkungan server Anda, gunakan kombinasi strategi ini untuk mengizinkan permintaan server ke layanan Firebase:

  • Kredensial Default Aplikasi (ADC) Google
  • File JSON akun layanan
  • Token akses OAuth 2.0 berumur pendek yang berasal dari akun layanan

Jika aplikasi Anda berjalan di Compute Engine, Google Kubernetes Engine, App Engine, atau Cloud Functions (termasuk Cloud Functions for Firebase), gunakan Kredensial Default Aplikasi (ADC). ADC menggunakan akun layanan default yang sudah ada untuk mendapatkan kredensial guna mengizinkan permintaan, dan ADC memungkinkan pengujian lokal fleksibel melalui variabel lingkungan GOOGLE_APPLICATION_CREDENTIALS. Untuk otomatisasi alur otorisasi sepenuhnya, gunakan ADC bersama dengan library server Admin SDK.

Jika aplikasi Anda berjalan pada lingkungan server non-Google, Anda harus mendownload file JSON akun layanan dari project Firebase. Selama memiliki akses ke sistem file yang berisi file kunci pribadi, Anda dapat menggunakan variabel lingkungan GOOGLE_APPLICATION_CREDENTIALS untuk mengizinkan permintaan dengan kredensial yang diperoleh secara manual ini. Jika tidak memiliki akses ke file tersebut, Anda harus merujuk file akun layanan dalam kode Anda. Lakukan ini dengan sangat hati-hati karena dapat berisiko mengekspos kredensial Anda.

Memberikan kredensial dengan ADC

Kredensial Default Aplikasi (ADC) Google memeriksa kredensial Anda dengan urutan sebagai berikut:

  1. ADC memeriksa apakah variabel lingkungan GOOGLE_APPLICATION_CREDENTIALS ditetapkan. Jika variabel ditetapkan, ADC akan menggunakan file akun layanan yang ditunjuk variabel.

  2. Jika variabel lingkungan tidak ditetapkan, ADC akan menggunakan akun layanan default yang disediakan Compute Engine, Google Kubernetes Engine, App Engine, dan Cloud Functions untuk aplikasi yang berjalan pada layanan tersebut.

  3. Jika ADC tidak dapat menggunakan salah satu dari kredensial di atas, sistem akan melemparkan error.

Contoh kode Admin SDK berikut menggambarkan strategi ini. Contoh ini tidak secara eksplisit menentukan kredensial aplikasi. Namun, ADC secara implisit dapat menemukan kredensial asalkan variabel lingkungan ditetapkan, atau asalkan aplikasi berjalan di Compute Engine, Google Kubernetes Engine, App Engine, atau 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(),
});

Memberikan kredensial secara manual

Project Firebase mendukung akun layanan Google, yang dapat Anda gunakan untuk memanggil API server Firebase dari server aplikasi atau lingkungan tepercaya. Jika Anda mengembangkan kode secara lokal atau men-deploy aplikasi secara lokal, gunakan kredensial yang diperoleh melalui akun layanan ini untuk mengizinkan permintaan server.

Untuk mengautentikasi akun layanan dan memberinya akses ke layanan Firebase, Anda harus membuat file kunci pribadi dalam format JSON.

Untuk membuat file kunci pribadi untuk akun layanan Anda:

  1. Di Firebase console, buka Settings > Service Accounts.

  2. Klik Generate New Private Key, lalu konfirmasikan dengan mengklik Generate Key.

  3. Simpan dengan aman file JSON yang memuat kunci tersebut.

Saat Anda memberi otorisasi melalui akun layanan, ada dua opsi untuk menyediakan kredensial ke aplikasi. Anda dapat menetapkan variabel lingkungan GOOGLE_APPLICATION_CREDENTIALS, atau secara eksplisit meneruskan jalur ke kunci akun layanan dalam kode. Opsi pertama lebih aman dan sangat direkomendasikan.

Untuk menetapkan variabel lingkungan:

Tetapkan variabel lingkungan GOOGLE_APPLICATION_CREDENTIALS ke jalur file JSON yang berisi kunci akun layanan Anda. Variabel ini hanya berlaku untuk sesi shell Anda saat ini. Jadi, jika Anda membuka sesi baru, tetapkan variabel kembali.

Linux atau macOS

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

Windows

Dengan PowerShell:

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

Setelah Anda menyelesaikan langkah-langkah di atas, Kredensial Default Aplikasi (ADC) secara implisit dapat menentukan kredensial Anda, sehingga Anda dapat menggunakan kredensial akun layanan saat menguji atau beroperasi di lingkungan non-Google.

Menggunakan kredensial untuk membuat token akses

Jika tidak menggunakan Admin SDK yang menangani otorisasi secara otomatis, Anda harus membuat token akses dan menambahkannya ke permintaan kirim.

Gunakan kredensial Firebase Anda beserta Library Google Auth untuk bahasa pilihan Anda saat mengambil token akses OAuth 2.0 yang berumur pendek:

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

Dalam contoh ini, library klien Google API mengautentikasi permintaan dengan token web JSON, atau yang disebut JWT. Untuk informasi lebih lanjut, baca token web 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();
}

Setelah masa berlaku token akses berakhir, metode refresh token akan otomatis dipanggil untuk mengambil token yang telah diperbarui.

Untuk mengizinkan akses ke FCM, minta cakupan https://www.googleapis.com/auth/firebase.messaging.

Untuk menambahkan token akses ke header permintaan HTTP:

Tambahkan token sebagai nilai header Authorization dalam format 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;

Mengizinkan permintaan kirim protokol lama

Dengan protokol HTTP lama, setiap permintaan harus berisi kunci server dari tab Cloud Messaging pada panel Settings di Firebase console. Untuk XMPP, Anda harus menggunakan kunci server yang sama untuk membuat koneksi.

Memigrasikan kunci server lama

Mulai Maret 2020, FCM berhenti membuat kunci server lama. Kunci server lama yang ada akan terus berfungsi, tetapi sebaiknya gunakan versi kunci yang lebih baru yang bernama Server key di Firebase console.

Jika Anda ingin menghapus kunci server lama, Anda dapat melakukannya di Google Cloud console.

Mengizinkan permintaan HTTP

Permintaan pesan terdiri dari dua bagian: header HTTP dan isi HTTP. Header HTTP harus berisi header berikut ini:

  • Authorization: key=YOUR_SERVER_KEY
    Pastikan ini adalah kunci server yang nilainya tersedia di tab Cloud Messaging pada panel Settings di Firebase console. Kunci Android, platform Apple, dan browser ditolak oleh FCM.
  • Content-Type: application/json untuk JSON; application/x-www-form-urlencoded;charset=UTF-8 untuk teks biasa.
    Jika Content-Type tidak disertakan, formatnya diasumsikan sebagai teks biasa.

Contoh:

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

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

Lihat Membuat Permintaan Kirim untuk detail selengkapnya mengenai pembuatan permintaan kirim. Referensi Protokol HTTP Lama menyediakan daftar semua parameter yang dapat dimuat di pesan Anda.

Memeriksa validitas kunci server

Jika Anda menerima error autentikasi saat mengirim pesan, periksa validitas Kunci server. Misalnya, pada Linux, jalankan perintah berikut:

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

Jika Anda menerima kode status HTTP 401, berarti Kunci server Anda tidak valid.

Mengizinkan koneksi XMPP

Dengan XMPP, Anda dapat mempertahankan koneksi persisten, asinkron, dan dua arah ke server FCM. Koneksi ini dapat digunakan untuk mengirim dan menerima pesan antara server Anda dan perangkat pengguna yang terhubung ke FCM.

Anda dapat menggunakan sebagian besar library XMPP untuk mengelola koneksi yang berumur panjang ke FCM. Endpoint XMPP berjalan pada fcm-xmpp.googleapis.com:5235. Saat menguji fungsi dengan pengguna nonproduksi, Anda harus terhubung ke server praproduksi di fcm-xmpp.googleapis.com:5236 (perhatikan port yang berbeda).

Pengujian rutin di praproduksi (lingkungan lebih kecil tempat build FCM terbaru berjalan) bermanfaat untuk mengisolasi pengguna nyata dari kode uji. Perangkat pengujian dan kode uji coba yang terhubung ke fcm-xmpp.googleapis.com:5236 harus menggunakan ID pengirim FCM yang berbeda untuk menghindari risiko pengiriman pesan uji coba kepada pengguna produksi atau pengiriman pesan upstream dari traffic produksi melalui koneksi pengujian.

Koneksi memiliki dua syarat penting:

  • Anda harus memulai koneksi Transport Layer Security (TLS). Perlu diperhatikan bahwa saat ini FCM tidak mendukung ekstensi STARTTLS.
  • FCM memerlukan mekanisme autentikasi SASL PLAIN yang menggunakan <your_FCM_Sender_Id>@fcm.googleapis.com (ID pengirim FCM) dan Kunci server sebagai sandinya. Nilai-nilai ini tersedia di tab Cloud Messaging pada panel Settings di Firebase console.

Jika koneksi gagal, Anda harus segera menghubungkan ulang. Tidak perlu melakukan back-off jika pemutusan koneksi terjadi sesudah autentikasi. FCM mengizinkan 2.500 koneksi secara paralel untuk setiap ID pengirim.

Cuplikan berikut menggambarkan cara menjalankan autentikasi dan otorisasi untuk koneksi XMPP ke FCM.

Server XMPP

Server XMPP meminta koneksi ke FCM

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

FCM

FCMmembuka koneksi dan meminta mekanisme autentikasi, yang mencakup metode 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>

Server XMPP

Server XMPP harus merespons menggunakan metode autentikasi PLAIN, yang menyediakan kunci server dari tab Cloud Messaging pada panel Settings di Firebase console.

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

FCM

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

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

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

Catatan: FCM tidak menggunakan resource terikat saat menentukan rute pesan.

Lihat Membuat Permintaan Kirim untuk detail selengkapnya mengenai pembuatan permintaan kirim. Referensi Protokol XMPP Lama menyediakan daftar semua parameter yang dapat dimuat di pesan Anda.