אישור בקשות שליחה

בקשות שנשלחות אל FCM משרת האפליקציה או מהסביבה המהימנה חייבות לקבל הרשאה. שימו לב להבדלים החשובים הבאים בין HTTP API מדור קודם שהוצא משימוש לבין הרשאת API ב-HTTP v1:

  • ממשק ה-API של FCM HTTP v1 מאשר בקשות באמצעות אסימון גישה לטווח קצר מסוג OAuth 2.0. כדי ליצור את האסימון הזה, אפשר להשתמש ב-Application Default Credentials של Google (בסביבות שרת של Google) ו/או לקבל באופן ידני את פרטי הכניסה הנדרשים מקובץ מפתח פרטי בפורמט JSON שנוצר לחשבון שירות. אם אתם משתמשים ב-Firebase Admin SDK כדי לשלוח הודעות, הספרייה מטפלת באסימון בשבילכם.
  • הפרוטוקולים מדור קודם שהוצאו משימוש יכולים להשתמש רק במפתחות API לטווח ארוך שהתקבלו ממסוף Firebase.

הרשאה לשליחת בקשות HTTP v1

בהתאם לפרטים של סביבת השרת, אפשר להשתמש בשילוב של אסטרטגיות האלה כדי לאשר בקשות מהשרת לשירותי Firebase:

  • Google Application Default Credentials (ADC)
  • קובץ JSON של חשבון שירות
  • אסימון גישה לטווח קצר מסוג OAuth 2.0 שמבוסס על חשבון שירות

אם האפליקציה שלכם פועלת ב-Compute Engine,‏ Google Kubernetes Engine,‏ App Engine או ב-Cloud Functions (כולל Cloud Functions for Firebase), השתמשו ב-Application Default Credentials ‏(ADC). ADC משתמש בחשבון השירות הקיים שמוגדר כברירת מחדל כדי לקבל את פרטי הכניסה לאישור בקשות, ו-ADC מאפשר בדיקה מקומית גמישה באמצעות משתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS. כדי לבצע אוטומציה מלאה של תהליך ההרשאה, צריך להשתמש ב-ADC יחד עם ספריות השרת של Admin SDK.

אם האפליקציה פועלת בסביבת שרת שאינה של Google, צריך להוריד מפרויקט Firebase קובץ JSON עם חשבון שירות. כל עוד יש לכם גישה למערכת קבצים שמכילה את קובץ המפתח הפרטי, תוכלו להשתמש במשתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS כדי לאשר בקשות באמצעות פרטי הכניסה האלה שהתקבלו באופן ידני. אם אין לכם גישה לקובץ כזה, עליכם להפנות לקובץ של חשבון השירות בקוד – וצריך לעשות זאת בזהירות רבה בגלל הסיכון לחשיפת פרטי הכניסה שלכם.

איך מספקים פרטי כניסה באמצעות ADC

השירות Application Default Credentials‏ (ADC) של Google מחפש את פרטי הכניסה שלכם בסדר הבא:

  1. ADC בודק אם משתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS מוגדר. אם המשתנה מוגדר, חיפוש פרטי הכניסה ב-ADC מתבצע באמצעות קובץ חשבון השירות שהמשתנה מצביע אליו.

  2. אם משתנה הסביבה לא מוגדר, חיפוש פרטי הכניסה ב-ADC מתבצע באמצעות חשבון השירות שמוגדר כברירת מחדל ב-Compute Engine, ב-Google Kubernetes Engine, ב-App Engine וב-Cloud Functions לאפליקציות שפועלות בשירותים האלה.

  3. אם המערכת של ADC לא מצליחה להשתמש באף אחד מפרטי הכניסה האלה, המערכת תציג הודעת שגיאה.

דוגמת הקוד הבאה של Admin SDK ממחישה את האסטרטגיה הזו. בדוגמה לא צוינו באופן מפורש פרטי הכניסה של האפליקציה. עם זאת, ADC יכול למצוא את פרטי הכניסה באופן משתמע כל עוד משתנה הסביבה מוגדר, או כל עוד האפליקציה פועלת ב-Compute Engine, ב-Google Kubernetes Engine, ב-App Engine או ב-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(),
});

איך מספקים פרטי כניסה באופן ידני

פרויקטים ב-Firebase תומכים בחשבונות שירות של Google, שבאמצעותם אפשר לבצע קריאה ל-API של שרת Firebase משרת האפליקציה או מסביבה מהימנה. אם אתם מפתחים קוד באופן מקומי או פורסים את האפליקציה בארגון, תוכלו להשתמש בפרטי הכניסה שהתקבלו דרך חשבון השירות הזה כדי לאשר בקשות מהשרת.

כדי לאמת חשבון שירות ולהעניק לו הרשאת גישה לשירותי Firebase, צריך ליצור קובץ מפתח פרטי בפורמט JSON.

כדי ליצור קובץ מפתח פרטי לחשבון השירות:

  1. במסוף Firebase, פותחים את Settings (הגדרות) > Service Accounts (חשבונות שירות).

  2. לוחצים על Generate New Private Key (יצירת מפתח פרטי חדש) ואז על Generate Key (יצירת מפתח) כדי לאשר.

  3. מאחסנים באופן מאובטח את קובץ ה-JSON שמכיל את המפתח.

כשאתם נותנים הרשאה דרך חשבון שירות, יש לכם שתי אפשרויות למסור את פרטי הכניסה לאפליקציה. תוכלו להגדיר את משתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS, או להעביר באופן מפורש את הנתיב למפתח של חשבון השירות בקוד. האפשרות הראשונה מאובטחת יותר ומומלצת מאוד.

כדי להגדיר את משתנה הסביבה:

מגדירים את משתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS לנתיב של קובץ ה-JSON שמכיל את המפתח של חשבון השירות. המשתנה הזה חל רק על סשן המעטפת הנוכחי, כך שאם פותחים סשן חדש, צריך להגדיר את המשתנה שוב.

Linux או macOS

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

Windows

באמצעות PowerShell:

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

אחרי שתשלימו את השלבים שלמעלה, השירות Application Default Credentials (ADC) יוכל לקבוע באופן משתמע את פרטי הכניסה שלכם, כך שתוכלו להשתמש בפרטי הכניסה של חשבון השירות בזמן בדיקה או הפעלה בסביבות שאינן של Google.

שימוש בפרטי כניסה כדי ליצור אסימוני גישה

אלא אם אתם משתמשים ב-Admin SDK, שמטפל באימות באופן אוטומטי, תצטרכו ליצור את אסימון הגישה ולהוסיף אותו לבקשות לשליחה.

משתמשים בפרטי הכניסה ל-Firebase יחד עם ספריית האימות של Google בשפה המועדפת עליכם כדי לאחזר אסימון גישה לטווח קצר מסוג OAuth 2.0:

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

בדוגמה הזו, ספריית הלקוח של Google API מאמתת את הבקשה באמצעות אסימון אינטרנט מסוג JSON‏ (JWT). תוכלו לקרוא מידע נוסף בקטע אסימוני אינטרנט בפורמט 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();
}

אחרי שהתוקף של אסימון הגישה יפוג, שיטת הרענון של האסימון תופעל באופן אוטומטי כדי לאחזר אסימון גישה מעודכן.

כדי לתת הרשאת גישה ל-FCM, צריך לבקש את ההיקף https://www.googleapis.com/auth/firebase.messaging.

כדי להוסיף את אסימון הגישה לכותרת של בקשת HTTP:

מוסיפים את האסימון כערך של הכותרת Authorization בפורמט 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;

אישור בקשות שליחה של פרוטוקולים מדור קודם

בפרוטוקול HTTP הקודם, כל בקשה חייבת לכלול את מפתח השרת מהכרטיסייה Cloud Messaging בחלונית Settings במסוף Firebase. ב-XMPP, צריך להשתמש באותו מפתח שרת כדי ליצור חיבור.

העברת מפתחות שרת מדור קודם

החל ממרץ 2020, FCM הפסיק ליצור מפתחות שרת מדור קודם. מפתחות השרת הקודמים ימשיכו לפעול, אבל מומלץ להשתמש במקום זאת בגרסת המפתח החדשה יותר שמסומנת בתווית מפתח שרת במסוף Firebase.

אם רוצים למחוק מפתח שרת קיים מדור קודם, אפשר לעשות זאת במסוף Google Cloud.

הרשאה לבקשות HTTP

בקשת הודעה מורכבת משני חלקים: כותרת ה-HTTP וגוף ה-HTTP. כותרת ה-HTTP חייבת לכלול את הכותרות הבאות:

  • Authorization: key=YOUR_SELLER_KEY
    מוודאים שזהו מפתח ה-server, שהערך שלו זמין בכרטיסייה Cloud Messaging בחלונית הגדרות במסוף Firebase. מפתחות של Android, פלטפורמת Apple ומפתחות דפדפן נדחים על ידי FCM.
  • Content-Type: application/json ל-JSON,‏ application/x-www-form-urlencoded;charset=UTF-8 לטקסט פשוט.
    אם משמיטים את Content-Type, המערכת מניחה שהפורמט הוא טקסט פשוט.

לדוגמה:

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

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

במאמר יצירת בקשות שליחה מוסבר בפירוט איך יוצרים בקשות שליחה. החומר העזר בנושא פרוטוקול HTTP מדור קודם כולל רשימה של כל הפרמטרים שההודעה יכולה להכיל.

בדיקת התוקף של מפתח שרת

אם מופיעות שגיאות אימות כששולחים הודעות, צריך לבדוק את התוקף של מפתח השרת. לדוגמה, ב-Linux, מריצים את הפקודה הבאה:

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

אם קיבלתם קוד מצב 401 HTTP, מפתח השרת שלכם לא חוקי.

מתן הרשאה לחיבור XMPP

באמצעות XMPP אפשר לשמור על חיבור עקבי, אסינכרוני דו-כיווני לשרתי FCM. אפשר להשתמש בחיבור כדי לשלוח ולקבל הודעות בין השרת שלכם לבין המכשירים של המשתמשים שמחוברים ל-FCM.

אפשר להשתמש ברוב ספריות ה-XMPP כדי לנהל חיבור לטווח ארוך אל FCM. נקודת הקצה של XMPP פועלת ב-fcm-xmpp.googleapis.com:5235. כשבודקים את הפונקציונליות למשתמשים ללא ייצור, צריך להתחבר לשרת טרום-ייצור ב-fcm-xmpp.googleapis.com:5236 (שימו לב ליציאה השונה).

מומלץ לבצע בדיקות באופן קבוע בסביבת טרום-ייצור (סביבה קטנה יותר שבה פועלים גרסאות ה-build האחרונות של FCM) כדי לבודד משתמשים אמיתיים מקוד הבדיקה. במכשירי בדיקה ובקוד בדיקה שמתחברים אל fcm-xmpp.googleapis.com:5236 צריך להשתמש במזהה שולח FCM שונה כדי למנוע סיכונים של שליחת הודעות בדיקה למשתמשים בסביבת הייצור או שליחת הודעות מ-upstream מתעבורת נתונים בסביבת הייצור דרך חיבורי בדיקה.

לחיבור יש שתי דרישות חשובות:

  • צריך ליזום חיבור Transport Layer Security‏ (TLS). לתשומת ליבכם: FCM לא תומך כרגע בתוסף STARTTLS.
  • FCM מחייב מנגנון אימות SASL PLAIN באמצעות <your_FCM_Sender_Id>@fcm.googleapis.com (FCM מזהה השולח) ומפתח השרת בתור הסיסמה. הערכים האלה זמינים בכרטיסייה Cloud Messaging בחלונית Settings במסוף Firebase.

אם החיבור נכשל בשלב כלשהו, צריך להתחבר מחדש באופן מיידי. אין צורך לבצע נסיגה אחרי ניתוק שמתרחש אחרי האימות. לכל מזהה שולח, FCM מאפשר 2,500 חיבורים במקביל.

בקטעי הקוד הבאים מוסבר איך לבצע אימות והרשאה לחיבור XMPP אל FCM.

שרת XMPP

שרת ה-XMPP מבקש חיבור אל FCM

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

FCM

FCM פותח את החיבור ומבקש מנגנון אימות, כולל השיטה 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

שרת ה-XMPP צריך להשיב באמצעות שיטת האימות PLAIN, ולספק את מפתח השרת מהכרטיסייה Cloud Messaging בחלונית Settings במסוף 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"/>

שרת 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>

שרת 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>

הערה: FCM לא משתמש במשאב המקושר בזמן ניתוב הודעות.

במאמר יצירת בקשות שליחה מוסבר בפירוט איך יוצרים בקשות שליחה. החומר העזר בנושא פרוטוקול XMPP מדור קודם כולל רשימה של כל הפרמטרים שההודעה יכולה להכיל.