التحقّق من الطلبات من 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 API:

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

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

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

بعد ذلك، عليك منح حساب خدمة Google Chat chat@system.gserviceaccount.com الإذن كمنفّذ.

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

وحدة التحكّم

بعد نشر الدالة على Google Cloud، اتّبِع الخطوات التالية:

  1. في Google Cloud Console، انتقِل إلى صفحة Cloud Functions:

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

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

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

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

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

  6. اختَر الدور 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. في Google Cloud Console، انتقِل إلى صفحة 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 Functions أو Cloud Run). باستخدام هذه الطريقة، تحتاج خدمة HTTP إلى معلومات حول عنوان URL لنقطة النهاية التي يتم تشغيلها فيها، ولكنّها لا تحتاج إلى معلومات حول رقم مشروع Cloud.

توضّح النماذج التالية كيفية التحقّق من أنّ الرمز المميز لحامل الشهادة صادر عن 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

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

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