Xác minh yêu cầu từ Google Chat

Đối với các ứng dụng Google Chat được xây dựng trên điểm cuối HTTP, phần này giải thích cách xác minh rằng các yêu cầu đến điểm cuối của bạn đến từ Chat.

Để gửi các sự kiện tương tác đến ứng dụng Chat điểm cuối, Google sẽ gửi yêu cầu đến dịch vụ của bạn. Để xác minh rằng yêu cầu đó là của Google, Chat sẽ thêm một mã thông báo xác thực vào tiêu đề Authorization của mọi yêu cầu HTTPS đến điểm cuối của bạn. Ví dụ:

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

Chuỗi AbCdEf123456 trong ví dụ trước là sự uỷ quyền hàm mang mã thông báo. Đây là mã thông báo mã hoá do Google tạo. Loại phương thức mang mã thông báo và giá trị của mã audience phụ thuộc vào loại đối tượng xác thực mà bạn đã chọn khi định cấu hình ứng dụng Chat.

Nếu bạn đã triển khai ứng dụng Chat bằng Đám mây Các hàm hoặc Cloud Run, Cloud IAM sẽ tự động xử lý việc xác minh mã thông báo. Bạn chỉ cần thêm tài khoản dịch vụ Google Chat làm người gọi được uỷ quyền. Nếu ứng dụng của bạn triển khai máy chủ HTTP của riêng ứng dụng đó, thì bạn có thể xác minh mã thông báo của phương thức mang bằng thư viện ứng dụng Google API nguồn mở:

Nếu mã thông báo không xác minh cho ứng dụng Chat, dịch vụ phải phản hồi yêu cầu bằng mã phản hồi HTTPS 401 (Unauthorized).

Xác thực yêu cầu bằng Cloud Functions hoặc Cloud Run

Nếu logic hàm của bạn được triển khai bằng Cloud Functions hoặc Cloud Run, bạn phải chọn URL điểm cuối HTTP trong trường Đối tượng xác thực của ứng dụng Chat chế độ cài đặt kết nối và đảm bảo rằng URL điểm cuối HTTP trong cấu hình tương ứng với URL của Chức năng đám mây hoặc điểm cuối Cloud Run.

Sau đó, bạn cần uỷ quyền cho tài khoản dịch vụ Google Chat chat@system.gserviceaccount.com làm phương thức gọi.

Các bước sau đây cho biết cách sử dụng Cloud Functions (thế hệ thứ 1):

Giao diện dòng lệnh

Sau khi triển khai chức năng lên Google Cloud:

  1. Trong bảng điều khiển Google Cloud, hãy truy cập vào trang Cloud Functions:

    Chuyển đến Cloud Functions

  2. Trong danh sách Cloud Functions, hãy nhấp vào hộp đánh dấu bên cạnh tuỳ chọn nhận . (Đừng nhấp vào chính hàm đó.)

  3. Nhấp vào Quyền ở đầu màn hình. Ngăn Permissions (Quyền) sẽ mở ra.

  4. Nhấp vào Thêm người chính.

  5. Trong trường New principals (Chủ sở hữu mới), hãy nhập chat@system.gserviceaccount.com.

  6. Chọn vai trò Cloud Functions > Cloud Functions Invoker (Trình gọi hàm đám mây) từ Trình đơn thả xuống Chọn vai trò.

  7. Nhấp vào Lưu.

gcloud

Sử dụng lệnh gcloud functions add-iam-policy-binding:

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

Thay thế RECEIVING_FUNCTION bằng tên hàm của ứng dụng Chat.

Các bước sau đây cho biết cách sử dụng các dịch vụ Cloud Functions (thế hệ 2) hoặc Cloud Run:

Giao diện dòng lệnh

Sau khi triển khai chức năng hoặc dịch vụ của bạn trên Google Cloud:

  1. Trong bảng điều khiển Google Cloud, hãy truy cập vào trang Cloud Run:

    Chuyển đến Cloud Run

  2. Trong danh sách dịch vụ Cloud Run, hãy nhấp vào hộp đánh dấu bên cạnh hàm nhận. (Đừng nhấp vào chính hàm đó.)

  3. Nhấp vào Quyền ở đầu màn hình. Ngăn Permissions (Quyền) sẽ mở ra.

  4. Nhấp vào Thêm người chính.

  5. Trong trường New principals (Người dùng mới), hãy nhập chat@system.gserviceaccount.com.

  6. Chọn vai trò Cloud Run > Cloud Run Invoker từ Trình đơn thả xuống Chọn vai trò.

  7. Nhấp vào Lưu.

gcloud

Sử dụng lệnh gcloud functions add-invoker-policy-binding:

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

Thay thế RECEIVING_FUNCTION bằng tên hàm của ứng dụng Chat.

Xác thực yêu cầu HTTP bằng mã thông báo mã nhận dạng

Nếu trường Đối tượng xác thực của chế độ cài đặt kết nối trong ứng dụng Chat được đặt thành URL điểm cuối HTTP, thì mã thông báo uỷ quyền của người mang trong yêu cầu là mã nhận dạng OpenID Connect (OIDC) do Google ký. Trường email được đặt thành chat@system.gserviceaccount.com. Trường Authentication Audience (Đối tượng xác thực) được đặt thành URL mà bạn đã định cấu hình cho Google Chat để gửi yêu cầu đến ứng dụng Chat. Ví dụ: nếu điểm cuối được định cấu hình của ứng dụng Chat là https://example.com/app/, thì trường Authentication Audience (Đối tượng xác thực) trong mã nhận dạng sẽ là https://example.com/app/.

Các mẫu sau đây minh hoạ cách xác minh rằng mã thông báo mang được phát hành bởi Google Chat và nhắm đến ứng dụng của bạn bằng thư viện ứng dụng OAuth của Google.

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

nút/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;
}

Xác thực yêu cầu bằng JWT Số dự án

Nếu trường Đối tượng xác thực của ứng dụng Chat chế độ cài đặt kết nối được đặt thành Project Number, mã thông báo uỷ quyền truyền tải trong yêu cầu là mã tự ký Mã thông báo web JSON (JWT), do chat@system.gserviceaccount.com phát hành và ký. Trường audience được đặt thành số dự án trên Google Cloud mà bạn sử dụng để tạo ứng dụng Chat. Ví dụ: nếu Số dự án trên đám mây của ứng dụng Chat là 1234567890, thì trường audience trong JWT là 1234567890.

Các mẫu sau đây cho biết cách xác minh rằng mã thông báo của chủ sở hữu do Google Chat phát hành và nhắm đến dự án của bạn bằng cách sử dụng thư viện ứng dụng 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

nút/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;
}