التحقّق من الطلبات من 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 Run، تتولّى Cloud IAM التحقّق من الرمز المميّز تلقائيًا. عليك إضافة حساب خدمة Google Chat كمستدعي مُفوَّض. إذا كان تطبيقك ينفّذ خادم HTTP خاصًا به، يمكنك التحقّق من الرمز المميّز للوصول باستخدام مكتبة عميل Google API مفتوحة المصدر:

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

المصادقة على الطلبات باستخدام دوال Cloud Run

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

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

وحدة التحكّم

بعد نشر الدالة أو الخدمة على 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 باستخدام رمز تعريف

إذا تم ضبط حقل "جمهور المصادقة" لإعداد اتصال تطبيق 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/.

هذه هي طريقة المصادقة المقترَحة إذا لم تكن نقطة نهاية HTTP مستضافة على خدمة تتيح المصادقة المستندة إلى IAM (مثل Cloud Run). باستخدام هذه الطريقة، تحتاج خدمة HTTP إلى معلومات عن عنوان URL لنقطة النهاية التي يتم تشغيلها عليها، ولكنها لا تحتاج إلى معلومات عن رقم مشروع Cloud.

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

جافا

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.

لا يُنصح باستخدام طريقة المصادقة هذه إلا إذا كنت تفضّل استخدام رقم مشروع Cloud للتحقّق من الطلبات بدلاً من عنوان URL لنقطة نهاية HTTP. على سبيل المثال، إذا كنت تريد تغيير عنوان URL لنقطة النهاية بمرور الوقت مع الاحتفاظ برقم مشروع Cloud نفسه، أو إذا كنت تريد استخدام نقطة النهاية نفسها لأرقام مشاريع Cloud متعددة وأردت مقارنة حقل audience بقائمة أرقام مشاريع Cloud.

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

جافا

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