אימות בקשות מ-Google Chat

באפליקציות של Google Chat שמבוססות על נקודות קצה ב-HTTP, מוסבר כאן איך לוודא שהבקשות לנקודת הקצה שלכם מגיעות מ-Chat.

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

POST
Host: yourappurl.com
Authorization: Bearer AbCdEf123456
Content-Type: application/json
User-Agent: Google-Dynamite

המחרוזת AbCdEf123456 בדוגמה שלמעלה היא ההרשאה למוכ"ז ב-Assistant. זהו אסימון קריפטוגרפי ש-Google מפיקה. סוג הגורם האחראי ואת הערך של audience השדה תלוי בסוג קהל האימות שבחרתם איך מגדירים את אפליקציית Chat.

אם הטמעתם את אפליקציית Chat באמצעות Cloud פונקציות או Cloud Run, Cloud IAM מטפל באימות אסימונים באופן אוטומטי. שלך צריך רק להוסיף את חשבון השירות של Google Chat כ-invoker מורשה. אם האפליקציה מטמיעה שרת HTTP משלה, אפשר לאמת את אסימון בעל החזקה באמצעות ספריית לקוח של Google API בקוד פתוח:

אם האסימון לא מאומת באפליקציית Chat, השירות שלכם צריך להשיב לבקשה עם קוד תגובה מסוג HTTPS‏ 401 (Unauthorized).

אימות בקשות באמצעות Cloud Functions או Cloud Run

אם לוגיק הפונקציה מיושם באמצעות Cloud Functions או Cloud Run, צריך לבחור באפשרות כתובת URL של נקודת קצה מסוג HTTP בשדה Authentication Audience בהגדרת החיבור של אפליקציית Chat, ולוודא שכתובת ה-URL של נקודת הקצה מסוג HTTP בהגדרה תואמת לכתובת ה-URL של נקודת הקצה ב-Cloud Functions או ב-Cloud Run.

לאחר מכן, צריך לתת הרשאה לחשבון השירות של Google Chat chat@system.gserviceaccount.com כגורם מפעיל.

בשלבים הבאים מוסבר איך להשתמש ב-Cloud Functions (דור ראשון):

המסוף

אחרי פריסת הפונקציה ב-Google Cloud:

  1. במסוף Google Cloud, נכנסים לדף Cloud Functions:

    כניסה אל Cloud Functions

  2. ברשימה Cloud Functions, לוחצים על תיבת הסימון שליד מותאמת אישית. (לא לוחצים על הפונקציה עצמה).

  3. לוחצים על הרשאות בחלק העליון של המסך. החלונית Permissions נפתח.

  4. לוחצים על Add principal.

  5. בשדה New principals, מזינים chat@system.gserviceaccount.com.

  6. בתפריט הנפתח Select a role, בוחרים את התפקיד Cloud Functions > Cloud Functions Invoker.

  7. לוחצים על שמירה.

gcloud

משתמשים בפקודה gcloud functions add-iam-policy-binding:

gcloud functions add-iam-policy-binding RECEIVING_FUNCTION \
  --member='serviceAccount:chat@system.gserviceaccount.com' \
  --role='roles/cloudfunctions.invoker'

מחליפים את RECEIVING_FUNCTION בשם שלכם הפונקציה של אפליקציית Chat.

השלבים הבאים מסבירים איך להשתמש בשירותי Cloud Functions (דור שני) או Cloud Run:

המסוף

אחרי שפרסתם את הפונקציה או השירות ב-Google Cloud:

  1. נכנסים לדף Cloud Run במסוף Google Cloud:

    כניסה ל-Cloud Run

  2. ברשימת שירותי Cloud Run, לוחצים על תיבת הסימון שליד מותאמת אישית. (לא לוחצים על הפונקציה עצמה).

  3. לוחצים על הרשאות בחלק העליון של המסך. החלונית Permissions נפתח.

  4. לוחצים על Add principal.

  5. בשדה New principals, מזינים chat@system.gserviceaccount.com.

  6. בוחרים את התפקיד Cloud Run > Cloud Run Invoker מ- בתפריט הנפתח Select a rol.

  7. לוחצים על שמירה.

gcloud

משתמשים בפקודה gcloud functions add-invoker-policy-binding:

gcloud functions add-invoker-policy-binding RECEIVING_FUNCTION \
  --member='serviceAccount:chat@system.gserviceaccount.com'

מחליפים את RECEIVING_FUNCTION בשם שלכם הפונקציה של אפליקציית Chat.

אימות בקשות HTTP באמצעות אסימון מזהה

אם השדה 'קהל לאימות' באפליקציית Chat הגדרת החיבור היא כתובת URL של נקודת קצה (HTTP), אסימון ההרשאה למוכ"ז בבקשה הוא OpenID Connect בחתימה של Google (OIDC) אסימון מזהה. השדה email מוגדר ל-chat@system.gserviceaccount.com. השדה Authentication Audience (קהל האימות) מוגדר לכתובת ה-URL שהגדרתם. Google Chat כדי לשלוח בקשות לאפליקציית Chat. לדוגמה, אם נקודת הקצה שהוגדרה אפליקציית Chat היא https://example.com/app/, ואז השדה Authentication Audience באסימון המזהה הוא https://example.com/app/.

בדוגמאות הבאות מוסבר איך לאמת באמצעות ספריית הלקוח של Google OAuth שאסימון למוכ"ז הונפק על ידי Google Chat וכי הוא מיועד לאפליקציה שלכם.

Java

java/basic-app/src/main/java/com/google/chat/app/basic/App.java
String CHAT_ISSUER = "chat@system.gserviceaccount.com";
JsonFactory factory = JacksonFactory.getDefaultInstance();

GoogleIdTokenVerifier verifier =
    new GoogleIdTokenVerifier.Builder(new ApacheHttpTransport(), factory)
        .setAudience(Collections.singletonList(AUDIENCE))
        .build();

GoogleIdToken idToken = GoogleIdToken.parse(factory, bearer);
return idToken != null
    && verifier.verify(idToken)
    && idToken.getPayload().getEmailVerified()
    && idToken.getPayload().getEmail().equals(CHAT_ISSUER);

Python

python/basic-app/main.py
# Bearer Tokens received by apps will always specify this issuer.
CHAT_ISSUER = 'chat@system.gserviceaccount.com'

try:
    # Verify valid token, signed by CHAT_ISSUER, intended for a third party.
    request = requests.Request()
    token = id_token.verify_oauth2_token(bearer, request, AUDIENCE)
    return token['email'] == CHAT_ISSUER

except:
    return False

Node.js

node/basic-app/index.js
// Bearer Tokens received by apps will always specify this issuer.
const chatIssuer = 'chat@system.gserviceaccount.com';

// Verify valid token, signed by chatIssuer, intended for a third party.
try {
  const ticket = await client.verifyIdToken({
    idToken: bearer,
    audience: audience
  });
  return ticket.getPayload().email_verified
      && ticket.getPayload().email === chatIssuer;
} catch (unused) {
  return false;
}

אימות בקשות באמצעות JWT של מספר פרויקט

אם השדה 'קהל לאימות' באפליקציית Chat הגדרת החיבור מוגדרת ל-Project Number, אסימון ההרשאה למוכ"ז בבקשה הוא בחתימה עצמית אסימון אינטרנט מסוג JSON (JWT), הונפק ונחתם על ידי chat@system.gserviceaccount.com. השדה audience מוגדר למספר הפרויקט ב-Google Cloud שבו השתמשתם כדי לפתח את אפליקציית Chat. לדוגמה, אם מספר הפרויקט ב-Cloud של אפליקציית Chat הוא 1234567890, השדה audience ב-JWT הוא 1234567890.

הדוגמאות הבאות מראות איך לאמת שאסימון למוכ"ז הונפק על ידי Google Chat וטירגוט הפרויקט שלך באמצעות ספריית הלקוח של OAuth של Google.

Java

java/basic-app/src/main/java/com/google/chat/app/basic/App.java
String CHAT_ISSUER = "chat@system.gserviceaccount.com";
JsonFactory factory = JacksonFactory.getDefaultInstance();

GooglePublicKeysManager keyManagerBuilder =
    new GooglePublicKeysManager.Builder(new ApacheHttpTransport(), factory)
        .setPublicCertsEncodedUrl(
            "https://www.googleapis.com/service_accounts/v1/metadata/x509/" + CHAT_ISSUER)
        .build();

GoogleIdTokenVerifier verifier =
    new GoogleIdTokenVerifier.Builder(keyManagerBuilder).setIssuer(CHAT_ISSUER).build();

GoogleIdToken idToken = GoogleIdToken.parse(factory, bearer);
return idToken != null
    && verifier.verify(idToken)
    && idToken.verifyAudience(Collections.singletonList(AUDIENCE))
    && idToken.verifyIssuer(CHAT_ISSUER);

Python

python/basic-app/main.py
# Bearer Tokens received by apps will always specify this issuer.
CHAT_ISSUER = 'chat@system.gserviceaccount.com'

try:
    # Verify valid token, signed by CHAT_ISSUER, intended for a third party.
    request = requests.Request()
    certs_url = 'https://www.googleapis.com/service_accounts/v1/metadata/x509/' + CHAT_ISSUER
    token = id_token.verify_token(bearer, request, AUDIENCE, certs_url)
    return token['iss'] == CHAT_ISSUER

except:
    return False

Node.js

Node/basic-app/index.js
// Bearer Tokens received by apps will always specify this issuer.
const chatIssuer = 'chat@system.gserviceaccount.com';

// Verify valid token, signed by CHAT_ISSUER, intended for a third party.
try {
  const response = await fetch('https://www.googleapis.com/service_accounts/v1/metadata/x509/' + chatIssuer);
  const certs = await response.json();
  await client.verifySignedJwtWithCertsAsync(
    bearer, certs, audience, [chatIssuer]);
  return true;
} catch (unused) {
  return false;
}