Google Chat থেকে অনুরোধ যাচাই করুন

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

আপনার চ্যাট অ্যাপের এন্ডপয়েন্টে ইন্টারঅ্যাকশন ইভেন্টগুলি পাঠানোর জন্য, Google আপনার পরিষেবাতে অনুরোধ করে। অনুরোধটি Google থেকে আসছে কিনা তা যাচাই করতে, চ্যাট আপনার এন্ডপয়েন্টে প্রতিটি HTTPS অনুরোধের Authorization শিরোনামে একটি বহনকারী টোকেন অন্তর্ভুক্ত করে। উদাহরণ স্বরূপ:

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

পূর্ববর্তী উদাহরণে স্ট্রিং AbCdEf123456 হল বহনকারী অনুমোদন টোকেন। এটি Google দ্বারা উত্পাদিত একটি ক্রিপ্টোগ্রাফিক টোকেন। বাহক টোকেনের ধরন এবং audience ক্ষেত্রের মান চ্যাট অ্যাপ কনফিগার করার সময় আপনি যে ধরনের প্রমাণীকরণ শ্রোতা নির্বাচন করেছেন তার উপর নির্ভর করে।

আপনি যদি ক্লাউড ফাংশন বা ক্লাউড রান ব্যবহার করে আপনার চ্যাট অ্যাপ প্রয়োগ করে থাকেন, তাহলে ক্লাউড আইএএম স্বয়ংক্রিয়ভাবে টোকেন যাচাইকরণ পরিচালনা করে। আপনাকে শুধুমাত্র Google Chat পরিষেবা অ্যাকাউন্টটি একটি অনুমোদিত আমন্ত্রণকারী হিসেবে যোগ করতে হবে। যদি আপনার অ্যাপটি তার নিজস্ব HTTP সার্ভার প্রয়োগ করে, আপনি একটি ওপেন সোর্স Google API ক্লায়েন্ট লাইব্রেরি ব্যবহার করে আপনার বহনকারী টোকেন যাচাই করতে পারেন:

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

ক্লাউড ফাংশন বা ক্লাউড রান ব্যবহার করে অনুরোধগুলি প্রমাণীকরণ করুন

যদি আপনার ফাংশন লজিক ক্লাউড ফাংশন বা ক্লাউড রান ব্যবহার করে প্রয়োগ করা হয়, তাহলে আপনাকে চ্যাট অ্যাপ সংযোগ সেটিংসের প্রমাণীকরণ শ্রোতা ক্ষেত্রে App URL নির্বাচন করতে হবে এবং কনফিগারেশনে থাকা অ্যাপ URLটি ক্লাউড ফাংশন বা ক্লাউড রানের URL-এর সাথে সামঞ্জস্যপূর্ণ কিনা তা নিশ্চিত করতে হবে। শেষপ্রান্ত।

তারপরে, আপনাকে Google চ্যাট পরিষেবা অ্যাকাউন্ট chat@system.gserviceaccount.com একটি আমন্ত্রণকারী হিসাবে অনুমোদন করতে হবে৷

নিম্নলিখিত ধাপগুলি দেখায় কিভাবে ক্লাউড ফাংশন ব্যবহার করতে হয় (1ম প্রজন্ম):

কনসোল

Google ক্লাউডে আপনার ফাংশন স্থাপন করার পরে:

  1. Google ক্লাউড কনসোলে, ক্লাউড ফাংশন পৃষ্ঠাতে যান:

    ক্লাউড ফাংশনে যান

  2. ক্লাউড ফাংশন তালিকায়, রিসিভিং ফাংশনের পাশের চেকবক্সে ক্লিক করুন। (ফাংশন নিজেই ক্লিক করবেন না।)

  3. স্ক্রিনের শীর্ষে অনুমতিতে ক্লিক করুন। অনুমতি প্যানেল খোলে।

  4. অ্যাড প্রিন্সিপাল ক্লিক করুন।

  5. নতুন প্রিন্সিপাল ফিল্ডে, chat@system.gserviceaccount.com লিখুন।

  6. একটি ভূমিকা নির্বাচন করুন ড্রপ-ডাউন মেনু থেকে ক্লাউড ফাংশন > ক্লাউড ফাংশন ইনভোকার নির্বাচন করুন।

  7. Save এ ক্লিক করুন।

জিক্লাউড

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 প্রতিস্থাপন করুন।

নিম্নলিখিত ধাপগুলি দেখায় কিভাবে ক্লাউড ফাংশন (2য় প্রজন্ম) বা ক্লাউড রান পরিষেবাগুলি ব্যবহার করতে হয়:

কনসোল

Google ক্লাউডে আপনার ফাংশন বা পরিষেবা স্থাপন করার পরে:

  1. Google ক্লাউড কনসোলে, ক্লাউড রান পৃষ্ঠায় যান:

    Cloud Run এ যান

  2. ক্লাউড রান পরিষেবা তালিকায়, প্রাপ্তি ফাংশনের পাশের চেকবক্সে ক্লিক করুন। (ফাংশন নিজেই ক্লিক করবেন না।)

  3. স্ক্রিনের শীর্ষে অনুমতিতে ক্লিক করুন। অনুমতি প্যানেল খোলে।

  4. অ্যাড প্রিন্সিপাল ক্লিক করুন।

  5. নতুন প্রিন্সিপাল ফিল্ডে, chat@system.gserviceaccount.com লিখুন।

  6. ভূমিকা নির্বাচন করুন ড্রপ-ডাউন মেনু থেকে ক্লাউড রান > ক্লাউড রান ইনভোকার নির্বাচন করুন।

  7. Save এ ক্লিক করুন।

জিক্লাউড

gcloud functions add-invoker-policy-binding কমান্ড ব্যবহার করুন:

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

আপনার চ্যাট অ্যাপের ফাংশনের নাম দিয়ে RECEIVING_FUNCTION প্রতিস্থাপন করুন।

একটি অ্যাপ ইউআরএল আইডি টোকেন সহ অনুরোধগুলি প্রমাণীকরণ করুন

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

নিম্নলিখিত নমুনাগুলি দেখায় যে কীভাবে যাচাই করা যায় যে বাহক টোকেনটি Google Chat দ্বারা জারি করা হয়েছে এবং Google OAuth ক্লায়েন্ট লাইব্রেরি ব্যবহার করে আপনার অ্যাপে লক্ষ্য করা হয়েছে৷

জাভা

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;

import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager;
import com.google.api.client.http.apache.ApacheHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.json.JsonFactory;

/** Tool for verifying JWT Tokens for Apps in Google Chat. */
public class JWTVerify {
  // Bearer Tokens received by apps will always specify this issuer.
  static String CHAT_ISSUER = "chat@system.gserviceaccount.com";

  // Intended audience of the token, which is the URL of the app.
  static String AUDIENCE = "https://example.com/app/";

  // Get this value from the request's Authorization HTTPS header.
  // For example, for "Authorization: Bearer AbCdEf123456" use "AbCdEf123456".
  static String BEARER_TOKEN = "AbCdEf123456";

  public static void main(String[] args) throws GeneralSecurityException, IOException {
    JsonFactory factory = new GsonFactory();

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

    GoogleIdToken idToken = GoogleIdToken.parse(factory, BEARER_TOKEN);
    if (idToken == null) {
      System.out.println("Token cannot be parsed");
      System.exit(-1);
    }

    // Verify valid token, signed by CHAT_ISSUER, intended for a third party.
    if (!verifier.verify(idToken)
        || !idToken.getPayload().getEmailVerified()
        || !idToken.getPayload().getEmail().equals(CHAT_ISSUER)) {
      System.out.println("Invalid token");
      System.exit(-1);
    }

    // Token originates from Google and is targeted to a specific client.
    System.out.println("The token is valid");
  }
}

পাইথন

import sys
from google.oauth2 import id_token
from google.auth.transport import requests

# Bearer Tokens received by apps will always specify this issuer.
CHAT_ISSUER = 'chat@system.gserviceaccount.com'

# Intended audience of the token, which is the URL of the app.
AUDIENCE = 'https://example.com/app/'

# Get this value from the request's Authorization HTTPS header.
# For example, for 'Authorization: Bearer AbCdEf123456' use 'AbCdEf123456'.
BEARER_TOKEN = 'AbCdEf123456'

try:
  # Verify valid token, signed by CHAT_ISSUER, intended for a third party.
  request = requests.Request()
  token = id_token.verify_oauth2_token(BEARER_TOKEN, request, AUDIENCE)

  if token['email'] != CHAT_ISSUER:
    sys.exit('Invalid token')
except:
  sys.exit('Invalid token')

# Token originates from Google and is targeted to a specific client.
print('The token is valid')

Node.js

import {OAuth2Client} from 'google-auth-library';

// Bearer Tokens received by apps will always specify this issuer.
const CHAT_ISSUER = 'chat@system.gserviceaccount.com';

// Intended audience of the token, which is the URL of the app.
const AUDIENCE = 'https://example.com/app/';

// Get this value from the request's Authorization HTTPS header.
// For example, for "Authorization: Bearer AbCdEf123456" use "AbCdEf123456"
const BEARER_TOKEN = 'AbCdEf123456';

const client = new OAuth2Client();

async function verify() {
  // Verify valid token, signed by CHAT_ISSUER, intended for a third party.
  try {
    const ticket = await client.verifyIdToken({
      idToken: BEARER_TOKEN,
      audience: AUDIENCE
    });
    if (!ticket.getPayload().email_verified
        || ticket.getPayload().email !== CHAT_ISSUER) {
      throw new Error('Invalid issuer');
    }
  } catch (unused) {
    console.error('Invalid token');
    process.exit(1);
  }

  // Token originates from Google and is targeted to a specific client.
  console.log('The token is valid');
}

verify();

একটি প্রকল্প নম্বর JWT দিয়ে অনুরোধগুলি প্রমাণীকরণ করুন

যদি চ্যাট অ্যাপ সংযোগ সেটিংসের প্রমাণীকরণ দর্শক ক্ষেত্রটি Project Number সেট করা থাকে (বা সেট না করা হয়), অনুরোধে বহনকারী অনুমোদনের টোকেনটি একটি স্ব-স্বাক্ষরিত JSON ওয়েব টোকেন (JWT) , যা chat@system.gserviceaccount.com দ্বারা জারি এবং স্বাক্ষরিত chat@system.gserviceaccount.com audience ক্ষেত্রটি Google ক্লাউড প্রজেক্ট নম্বরে সেট করা আছে যেটি আপনি আপনার চ্যাট অ্যাপ তৈরি করতে ব্যবহার করেছেন। উদাহরণস্বরূপ, যদি আপনার চ্যাট অ্যাপের ক্লাউড প্রজেক্ট নম্বর হয় 1234567890 , তাহলে JWT-এর audience ক্ষেত্র হল 1234567890

নিম্নলিখিত নমুনাগুলি দেখায় যে কীভাবে যাচাই করা যায় যে বাহক টোকেনটি Google Chat দ্বারা জারি করা হয়েছে এবং Google OAuth ক্লায়েন্ট লাইব্রেরি ব্যবহার করে আপনার প্রকল্পে লক্ষ্য করা হয়েছে৷

জাভা

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;

import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager;
import com.google.api.client.http.apache.ApacheHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.json.JsonFactory;

/** Tool for verifying JWT Tokens for Apps in Google Chat. */
public class JWTVerify {
  // Bearer Tokens received by apps will always specify this issuer.
  static String CHAT_ISSUER = "chat@system.gserviceaccount.com";

  // Url to obtain the public certificate for the issuer.
  static String PUBLIC_CERT_URL_PREFIX =
      "https://www.googleapis.com/service_accounts/v1/metadata/x509/";

  // Intended audience of the token, which is the project number of the app.
  static String AUDIENCE = "1234567890";

  // Get this value from the request's Authorization HTTPS header.
  // For example, for "Authorization: Bearer AbCdEf123456" use "AbCdEf123456".
  static String BEARER_TOKEN = "AbCdEf123456";

  public static void main(String[] args) throws GeneralSecurityException, IOException {
    JsonFactory factory = new GsonFactory();

    GooglePublicKeysManager.Builder keyManagerBuilder =
        new GooglePublicKeysManager.Builder(new ApacheHttpTransport(), factory);

    String certUrl = PUBLIC_CERT_URL_PREFIX + CHAT_ISSUER;
    keyManagerBuilder.setPublicCertsEncodedUrl(certUrl);

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

    GoogleIdToken idToken = GoogleIdToken.parse(factory, BEARER_TOKEN);
    if (idToken == null) {
      System.out.println("Token cannot be parsed");
      System.exit(-1);
    }

    // Verify valid token, signed by CHAT_ISSUER, intended for a third party.
    if (!verifier.verify(idToken)
        || !idToken.verifyAudience(Collections.singletonList(AUDIENCE))
        || !idToken.verifyIssuer(CHAT_ISSUER)) {
      System.out.println("Invalid token");
      System.exit(-1);
    }

    // Token originates from Google and is targeted to a specific client.
    System.out.println("The token is valid");
  }
}

পাইথন

import sys

from google.oauth2 import id_token
from google.auth.transport import requests

# Bearer Tokens received by apps will always specify this issuer.
CHAT_ISSUER = 'chat@system.gserviceaccount.com'

# Url to obtain the public certificate for the issuer.
PUBLIC_CERT_URL_PREFIX = 'https://www.googleapis.com/service_accounts/v1/metadata/x509/'

# Intended audience of the token, which will be the project number of the app.
AUDIENCE = '1234567890'

# Get this value from the request's Authorization HTTPS header.
# For example, for 'Authorization: Bearer AbCdEf123456' use 'AbCdEf123456'.
BEARER_TOKEN = 'AbCdEf123456'

try:
  # Verify valid token, signed by CHAT_ISSUER, intended for a third party.
  request = requests.Request()
  certs_url = PUBLIC_CERT_URL_PREFIX + CHAT_ISSUER
  token = id_token.verify_token(BEARER_TOKEN, request, AUDIENCE, certs_url)

  if token['iss'] != CHAT_ISSUER:
    sys.exit('Invalid issuer')
except:
  sys.exit('Invalid token')

# Token originates from Google and is targeted to a specific client.
print('The token is valid')

Node.js

import fetch from 'node-fetch';
import {OAuth2Client} from 'google-auth-library';

// Bearer Tokens received by apps will always specify this issuer.
const CHAT_ISSUER = 'chat@system.gserviceaccount.com';

// Url to obtain the public certificate for the issuer.
const PUBLIC_CERT_URL_PREFIX =
    'https://www.googleapis.com/service_accounts/v1/metadata/x509/';

// Intended audience of the token, which is the project number of the app.
const AUDIENCE = '1234567890';

// Get this value from the request's Authorization HTTPS header.
// For example, for "Authorization: Bearer AbCdEf123456" use "AbCdEf123456"
const BEARER_TOKEN = 'AbCdEf123456';

const client = new OAuth2Client();

/** Verifies JWT Tokens for Apps in Google Chat. */
async function verify() {
  // Verify valid token, signed by CHAT_ISSUER, intended for a third party.
  try {
    const response = await fetch(PUBLIC_CERT_URL_PREFIX + CHAT_ISSUER);
    const certs = await response.json();
    const ticket = await client.verifySignedJwtWithCertsAsync(
        BEARER_TOKEN, certs, AUDIENCE, [CHAT_ISSUER]);
  } catch (unused) {
    console.error('Invalid token');
    process.exit(1);
  }

  // Token originates from Google and is targeted to a specific client.
  console.log('The token is valid');
}

verify();