التحقّق من الطلبات من 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 في المثال السابق هي الرمز المميز لتفويض الحامل. هذا رمز مشفّر أنشأته Google. يعتمد نوع رمز التمكين وقيمة الحقل audience على نوع جمهور المصادقة الذي اخترته عند ضبط تطبيق Chat.

إذا كنت قد نفّذت تطبيق Chat باستخدام Cloud Functions أو Cloud Run، ستتولى خدمة Cloud IAM عملية التحقّق من الرمز المميّز تلقائيًا. ما عليك سوى إضافة حساب خدمة Google Chat كمُشغِّل مفوَّض. إذا كان تطبيقك ينفِّذ خادم HTTP الخاص به، يمكنك التحقّق من رمز المرور المميّز باستخدام مكتبة عملاء واجهة برمجة تطبيقات Google مفتوحة المصدر:

إذا لم يتم إثبات صحة الرمز المميّز لتطبيق Chat، يجب أن تُجيب خدمتك عن الطلب باستخدام رمز استجابة HTTPS 401 (Unauthorized).

مصادقة الطلبات باستخدام Cloud Functions أو Cloud Run

في حال تنفيذ منطق الدالة باستخدام Cloud Functions أو Cloud Run، يجب اختيار عنوان URL لنقطة نهاية HTTP في حقل جمهور المصادقة في تطبيق Chat إعدادات الاتصال والتأكّد من أنّ عنوان URL لنقطة نهاية HTTP في الإعدادات يتطابق مع عنوان URL لنقطة نهاية Cloud Function أو Cloud Run.

بعد ذلك، عليك تفويض حساب خدمة Google Chat chat@system.gserviceaccount.com كمُستخدِم.

توضّح الخطوات التالية كيفية استخدام دوال Cloud (الجيل الأول):

وحدة التحكّم

بعد نشر الدالة على Google Cloud:

  1. في وحدة تحكّم Google Cloud، انتقِل إلى صفحة Cloud Functions:

    الانتقال إلى Cloud Functions

  2. في قائمة Cloud Functions، انقر على مربّع الاختيار بجانب الدوال التي تتلقّى الطلبات. (لا تنقر على الدالة نفسها).

  3. انقر على الأذونات في أعلى الشاشة. تفتح لوحة الأذونات.

  4. انقر على إضافة مدير.

  5. في الحقل العناصر الرئيسية الجديدة، أدخِل chat@system.gserviceaccount.com.

  6. اختَر الدور Cloud Functions > مسوّد دوال Cloud من القائمة المنسدلة اختيار دور.

  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. في وحدة تحكّم Google Cloud، انتقِل إلى صفحة Cloud Run:

    الانتقال إلى Cloud Run

  2. في قائمة خدمات Cloud Run، انقر على مربّع الاختيار بجانب دالّة الاستقبال. (لا تنقر على الدالة نفسها.)

  3. انقر على الأذونات في أعلى الشاشة. تفتح لوحة الأذونات.

  4. انقر على إضافة مدير.

  5. في الحقل العناصر الرئيسية الجديدة، أدخِل chat@system.gserviceaccount.com.

  6. اختَر الدور Cloud Run > Cloud Run Invoker من القائمة المنسدلة اختيار دور.

  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 باستخدام رمز تعريف

إذا تم ضبط حقل Authentication Audience (جمهور المصادقة) في إعداد الاتصال في تطبيق Chat على عنوان URL لنقطة نهاية HTTP، يكون الرمز المميّز لحامل البطاقة في الطلب هو رمز تعريف OpenID Connect (OIDC) الموقَّع من Google. تم ضبط الحقل email على chat@system.gserviceaccount.com. يتم ضبط حقل جمهور المصادقة على عنوان URL الذي ضبطته Google Chat لإرسال الطلبات إلى تطبيق Chat. على سبيل المثال، إذا كانت نقطة النهاية التي تم ضبطها لتطبيق Chat هي https://example.com/app/، يكون حقل جمهور المصادقة في الرمز المميّز لرقم التعريف هو https://example.com/app/.

توضِّح العيّنات التالية كيفية التأكّد من أنّ رمز المرور المميّز قد أصدرته Google Chat وكان موجهًا إلى تطبيقك باستخدام مكتبة عملاء Google OAuth.

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

العقدة/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 لرقم المشروع

في حال ضبط حقل Authentication Audience (جمهور المصادقة) ضمن إعداد الاتصال في تطبيق Chat على Project Number، يكون الرمز المميّز لحامل البطاقة في الطلب هو رمز JSON المميّز للويب (JWT) الموقَّع ذاتيًا، ويكون صادرًا وموقَّعًا من قِبل chat@system.gserviceaccount.com. يتم ضبط الحقل audience على رقم مشروع Google Cloud الذي استخدمته لإنشاء تطبيق Chat. على سبيل المثال، إذا كان رقم مشروع Cloud لتطبيق Chat هو 1234567890، سيكون الحقل audience في JWT هو 1234567890.

توضّح النماذج التالية كيفية التحقّق من أنّ الرمز المميّز للحامل قد تم إصداره من خلال Google Chat ويستهدف مشروعك باستخدام مكتبة عملاء Google OAuth.

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

بايثون/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;
}