Google Chat থেকে আসা যাচাইকরণ সংক্রান্ত অনুরোধ

HTTP এন্ডপয়েন্টে তৈরি Google Chat অ্যাপের ক্ষেত্রে, এই বিভাগে কীভাবে যাচাই করতে হয় যে আপনার এন্ডপয়েন্টে আসা অনুরোধগুলি Chat থেকে এসেছে তা ব্যাখ্যা করা হয়েছে।

আপনার Chat অ্যাপের এন্ডপয়েন্টে ইন্ট্যার‍্যাকশন ইভেন্ট ডিসপ্যাচ করতে, Google আপনার পরিষেবায় HTTPS অনুরোধ করে। অনুরোধটি যে Google-এর কাছ থেকে আসছে তা যাচাই করতে, Chat প্রতিটি HTTPS অনুরোধের Authorization হেডার (এবং অনুরোধ বডির authorizationEventObject.systemIdToken ফিল্ডে) Google-এর সই করা OpenID Connect (OIDC) ID টোকেন একটি বিয়ারার টোকেন হিসেবে অন্তর্ভুক্ত করে। যেমন:

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

আগের উদাহরণে AbCdEf123456 স্ট্রিংটি হল বিয়ারার অনুমোদন টোকেন। এই ক্রিপ্টোগ্রাফিক টোকেন আপনার Chat অ্যাপের অনন্য, প্রতি-প্রজেক্ট পরিষেবা অ্যাকাউন্ট (service-<var>PROJECT_NUMBER</var>@gcp-sa-gsuiteaddons.iam.gserviceaccount.com) দ্বারা সাইন করা হয় এবং audience ফিল্ডটি আপনার Chat অ্যাপের জন্য কনফিগার করা HTTP এন্ডপয়েন্ট URL-এ সেট করা হয়, যখন Chat অ্যাপ কনফিগার করা হয়।

আপনি Google Cloud কনসোলে Chat API-এর কনফিগারেশন ট্যাবের কানেকশন সেটিংস বিভাগ থেকে আপনার Chat অ্যাপের পরিষেবা অ্যাকাউন্টের ইমেল আইডি কপি করতে পারবেন:

  1. Google Cloud Console-এ, মেনু > API ও পরিষেবা > চালু করা API ও পরিষেবা > Google Chat API > কনফিগারেশন বিকল্পে যান:

    Google Chat API কনফিগারেশনে যান

  2. ইন্টার‍্যাক্টিভ ফিচার > কানেকশন সেটিংস বিকল্পের অধীনে, সার্ভিস অ্যাকাউন্ট ইমেল (service-<var>PROJECT_NUMBER</var>@gcp-sa-gsuiteaddons.iam.gserviceaccount.com) কপি করুন।

আপনি যদি Cloud Run ফাংশন বা Cloud Run ব্যবহার করে আপনার Chat অ্যাপ প্রয়োগ করে থাকেন, তাহলে আপনি Chat অ্যাপের পরিষেবা অ্যাকাউন্টকে Cloud Run Invoker (roles/run.invoker) ভূমিকা দিলে Cloud IAM অটোমেটিক টোকেন যাচাইকরণ হ্যান্ডেল করে। আপনার অ্যাপ যদি নিজস্ব HTTP সার্ভার প্রয়োগ করে, তাহলে আপনি ওপেন সোর্স Google API ক্লায়েন্ট লাইব্রেরি ব্যবহার করে বিয়ারার টোকেন যাচাই করতে পারবেন:

Chat অ্যাপের জন্য টোকেন যাচাই করা না গেলে, আপনার পরিষেবা HTTPS রেসপন্স কোড 401 (Unauthorized) সহ অনুরোধের উত্তর দেবে।

Cloud Run ফাংশন ব্যবহার করে অনুরোধ যাচাই করা

আপনার ফাংশন লজিক Cloud Run ফাংশন বা Cloud Run ব্যবহার করে প্রয়োগ করা হলে, ট্রিগার-এর অধীনে কনফিগার করা HTTP এন্ডপয়েন্ট URL Chat অ্যাপের কানেকশন সেটিংস যেন আপনার Cloud Run ফাংশন এন্ডপয়েন্টের URL-এর সাথে মিলে যায় তা নিশ্চিত করুন।

তারপর, নিম্নলিখিত ধাপগুলি ব্যবহার করে আপনার Chat অ্যাপের পরিষেবা অ্যাকাউন্টকে (service-<var>PROJECT_NUMBER</var>@gcp-sa-gsuiteaddons.iam.gserviceaccount.com, Chat API-এর কানেকশন সেটিংস বিভাগ থেকে কপি করা হয়েছে কনফিগারেশন ট্যাব) ইনভোকার হিসেবে অনুমোদন করুন:

কনসোল

Google Cloud-এ আপনার ফাংশন বা পরিষেবা ডেপ্লয় করার পরে:

  1. Google Cloud Console-এ, Cloud Run পৃষ্ঠায় যান:

    Cloud Run-এ যান

  2. Cloud Run পরিষেবার তালিকায়, গ্রহণকারী ফাংশনের পাশে থাকা চেকবক্সে ক্লিক করুন। (ফাংশনে ক্লিক করবেন না।)

  3. স্ক্রিনের সবচেয়ে উপরে অনুমতি বিকল্পে ক্লিক করুন। অনুমতি প্যানেল খুলে যাবে।

  4. প্রিন্সিপাল যোগ করুন বিকল্পে ক্লিক করুন।

  5. নতুন প্রিন্সিপাল ফিল্ডে, আপনার Chat অ্যাপের পরিষেবা অ্যাকাউন্ট ইমেল আইডি (service-<var>PROJECT_NUMBER</var>@gcp-sa-gsuiteaddons.iam.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:service-PROJECT_NUMBER@gcp-sa-gsuiteaddons.iam.gserviceaccount.com'

নিম্নলিখিত বিষয়গুলি পরিবর্তন করুন:

  • RECEIVING_FUNCTION: আপনার Chat অ্যাপের ফাংশনের নাম।
  • PROJECT_NUMBER: আপনার Chat অ্যাপের পরিষেবা অ্যাকাউন্ট ইমেল আইডিতে থাকা প্রোজেক্ট নম্বর।

ID টোকেন দিয়ে HTTP অনুরোধ প্রমাণীকরণ করা

HTTP এন্ডপয়েন্টের ক্ষেত্রে, অনুরোধে থাকা বিয়ারার অনুমোদন টোকেন হল একটি Google-এর সই করা OpenID Connect (OIDC) আইডি টোকেন। email ফিল্ডটি আপনার Chat অ্যাপের পরিষেবা অ্যাকাউন্টের ইমেল আইডিতে সেট করা আছে (service-<var>PROJECT_NUMBER</var>@gcp-sa-gsuiteaddons.iam.gserviceaccount.com), এবং audience ফিল্ডটি অনুরোধ পাওয়ার জন্য কনফিগার করা HTTP এন্ডপয়েন্ট URL-এ সেট করা আছে। যেমন, আপনার চ্যাট অ্যাপের কনফিগার করা এন্ডপয়েন্ট https://example.com/app/ হলে, ID টোকেনের audience ফিল্ড https://example.com/app/ হবে।

আপনার HTTP এন্ডপয়েন্ট যদি IAM-ভিত্তিক যাচাইকরণ (যেমন, Cloud Run) কাজ করে এমন কোনও পরিষেবায় হোস্ট করা না থাকে, তাহলে এই যাচাইকরণ পদ্ধতি সাজেস্ট করা হয়।

নিচে দেওয়া নমুনা থেকে বোঝা যায় যে কীভাবে যাচাই করা যায় যে আপনার Chat অ্যাপের জন্য Google-এর দ্বারা বিয়ারার টোকেন ইস্যু করা হয়েছে এবং Google OAuth ক্লায়েন্ট লাইব্রেরি ব্যবহার করে আপনার অ্যাপের এন্ডপয়েন্টকে টার্গেট করা হয়েছে:

Java

java/chat/secured-app/src/main/java/com/google/chat/app/secured/App.java
/**
 * Determine whether a Google Workspace add-on request is legitimate.
 * 
 * @param event Event sent from Google Workspace add-on
 * @param authorization Authorization header from the request
 * @return {boolean} Whether the request is legitimate
 */
private boolean verifyAddOnRequest(JsonNode event, String authorization) throws Exception {
  JsonFactory factory = JacksonFactory.getDefaultInstance();

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

  String bearer = authorization.substring("Bearer ".length(), authorization.length());
  GoogleIdToken idToken = GoogleIdToken.parse(factory, bearer);
  return idToken != null
    && verifier.verify(idToken)
    && idToken.getPayload().getEmailVerified()
    && idToken.getPayload().getEmail().equals(SERVICE_ACCOUNT_EMAIL);
}

Python

python/chat/secured-app/main.py
def verifyAddOnRequest() -> bool:
  """Determine whether a Google Workspace add-on request is legitimate.

  Args:
    request: Request sent from Google Workspace add-on

  Returns:
    Whether the request is legitimate
  """
  try:
    bearer = request.headers.get('Authorization')[len("Bearer "):]
    token = id_token.verify_oauth2_token(bearer, requests.Request(), HTTP_ENDPOINT)
    return token['email'] == SERVICE_ACCOUNT_EMAIL

  except:
    return False

Node.js

node/chat/secured-app/index.js
/**
 * Determine whether a Google Workspace add-on request is legitimate.
 * 
 * @param {Object} req Request sent from Google Workspace add-on
 * @return {boolean} Whether the request is legitimate
 */
async function verifyAddOnRequest(req) {
  try {
    const authorization = req.headers.authorization;
    const idToken = authorization.substring('Bearer '.length, authorization.length);
    const ticket = await new OAuth2Client().verifyIdToken({idToken, audience: HTTP_ENDPOINT});
    return ticket.getPayload().email_verified
        && ticket.getPayload().email === SERVICE_ACCOUNT_EMAIL;
  } catch (unused) {
    return false;
  }
}

অ্যাড-অন নয় এমন চ্যাট অ্যাপ: Google Chat থেকে আসা অনুরোধ যাচাই করা

Google Workspace অ্যাড-অন নয় এমন Chat অ্যাপের ক্ষেত্রে নিম্নলিখিত ডকুমেন্টেশন প্রযোজ্য। অ্যাড-অন নয় এমন কোনও Chat অ্যাপ মাইগ্রেট করতে, Google Chat অ্যাপকে Google Workspace অ্যাড-অনে কনভার্ট করুন লিঙ্ক দেখুন।

কানেকশন সেটিংস-এর অধীনে HTTP এন্ডপয়েন্ট URL-এর সাথে কনফিগার করা হয়নি এমন চ্যাট অ্যাপের ক্ষেত্রে, বিয়ারার টোকেনের ধরন এবং audience ফিল্ডের ভ্যালু নির্ভর করে চ্যাট অ্যাপ কনফিগার করার সময় আপনার বেছে নেওয়া প্রমাণীকরণ অডিয়েন্সের ধরনের উপর এবং শেয়ার করা পরিষেবা অ্যাকাউন্ট chat@system.gserviceaccount.com দিয়ে অনুরোধে সই করা হয়।

Cloud Run ফাংশন ব্যবহার করে অনুরোধ যাচাই করা (অ্যাড-অন নয় এমন চ্যাট অ্যাপ)

আপনার ফাংশন লজিক Cloud Run ফাংশন ব্যবহার করে প্রয়োগ করা হলে, আপনাকে Chat অ্যাপের কানেকশন সেটিংয়ের অডিয়েন্সের প্রমাণীকরণ ফিল্ডে HTTP এন্ডপয়েন্ট URL বেছে নিতে হবে এবং কনফিগারেশনে HTTP এন্ডপয়েন্ট URL যেন Cloud Run ফাংশন এন্ডপয়েন্টের URL-এর সাথে মিলে যায় তা নিশ্চিত করতে হবে।

তারপরে, নিম্নলিখিত ধাপগুলি ব্যবহার করে আপনাকে Google Chat পরিষেবা অ্যাকাউন্টকে chat@system.gserviceaccount.com ইনভোকার হিসেবে অনুমোদন করতে হবে:

কনসোল

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 অ্যাপের ফাংশনের নাম লিখুন।

ID টোকেন (অ্যাড-অন নয় এমন চ্যাট অ্যাপ) দিয়ে HTTP অনুরোধ প্রমাণীকরণ করা

অ্যাড-অন নয় এমন চ্যাট অ্যাপের কানেকশন সেটিংসে অনুমোদনকারী অডিয়েন্স ফিল্ড HTTP এন্ডপয়েন্ট URL হিসেবে সেট করা থাকলে, অনুরোধে বিয়ারার অনুমোদন টোকেন হল Google-এর সই করা OpenID Connect (OIDC) আইডি টোকেন। email ফিল্ড chat@system.gserviceaccount.com হিসেবে সেট করা আছে। যাচাইকরণ অডিয়েন্স ফিল্ডটি সেই URL-এ সেট করা আছে যেখানে আপনি Google Chat কনফিগার করেছেন যাতে এটি আপনার চ্যাট অ্যাপে অনুরোধ পাঠাতে পারে। এই চ্যাট অ্যাপটি কোনও অ্যাড-অন নয়। যেমন, আপনার Chat অ্যাপের কনফিগার করা এন্ডপয়েন্ট https://example.com/app/ হলে, ID টোকেনের অনুমোদনকারী অডিয়েন্স ফিল্ড https://example.com/app/ হবে।

নিচে দেওয়া নমুনা থেকে বোঝা যায় যে Google OAuth ক্লায়েন্ট লাইব্রেরি ব্যবহার করে কীভাবে যাচাই করা যায় যে বিয়ারার টোকেনটি Google Chat ইস্যু করেছে এবং সেটি আপনার 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 অ্যাপ তৈরি করতে ব্যবহার করেছেন। যেমন, আপনার Chat অ্যাপের ক্লাউড প্রোজেক্ট নম্বর 1234567890 হলে, JWT-এর audience ফিল্ডে 1234567890 থাকবে।

নিচের নমুনা থেকে বোঝা যায় যে 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();

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