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

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

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

הכניסה של Google Application Default Credentials (ADC) מתבצעת לפי הסדר הבא:

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

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

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 בחלונית הגדרות במסוף 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" : {
    ...
  },
}

במאמר יצירת בקשות שליחה מוסבר בפירוט איך יוצרים בקשות שליחה. ב-Legacy HTTP Protocol Reference מוצגת רשימה של כל הפרמטרים שההודעה שלכם יכולה להכיל.

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

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