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

בקשות שנשלחות אל FCM משרת האפליקציה או מהסביבה המהימנה חייבות לקבל הרשאה. חשוב לשים לב להבדלים החשובים הבאים בין ה-API הקודם של HTTP לבין הרשאת ה-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 משתמשת בחשבון השירות המוגדר כברירת מחדל כדי לקבל פרטי כניסה להרשאת בקשות, והיא מאפשרת בדיקה מקומית גמישה באמצעות משתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS. כדי לבצע אוטומציה מלאה של תהליך ההרשאה, צריך להשתמש ב-ADC יחד עם ספריות השרת של Admin SDK.

אם האפליקציה פועלת בסביבת שרת שאינה של Google, תצטרכו להוריד קובץ JSON של חשבון שירות מהפרויקט ב-Firebase. כל עוד יש לכם גישה למערכת קבצים שמכילה את קובץ המפתח הפרטי, תוכלו להשתמש במשתנה הסביבה 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 הפסיק ליצור מפתחות שרת מדור קודם. מפתחות השרת הקודמים ימשיכו לפעול, אבל מומלץ להשתמש במקום זאת בגרסת המפתח החדשה יותר שמסומנת בתווית Server key ב מסוף Firebase.

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

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

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

  • Authorization: key=YOUR_SERVER_KEY
    חשוב לוודא שזהו מפתח השרת, שהערך שלו זמין בכרטיסייה Cloud Messaging בחלונית Settings במסוף 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\"]}"

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

מתן הרשאה לחיבור 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 מדור קודם כולל רשימה של כל הפרמטרים שההודעה יכולה להכיל.