באפליקציות של Google Chat שמבוססות על נקודות קצה (endpoint) של 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 בקוד פתוח:
- Java: https://github.com/google/google-api-java-client
- Python: https://github.com/google/google-api-python-client
- Node.js: https://github.com/google/google-api-nodejs-client
- .NET: https://github.com/google/google-api-dotnet-client
אם אתם לא מצליחים לאמת את האסימון באפליקציית Chat, השירות אמור להגיב לבקשה עם קוד תגובה של HTTPS, 401 (Unauthorized)
.
אימות בקשות באמצעות Cloud Functions או Cloud Run
אם הלוגיקה של הפונקציה מוטמעת באמצעות Cloud Functions או Cloud Run, צריך לבחור את App URL
בשדה Authentication Audience בהגדרת החיבור של אפליקציית Chat, ולוודא שכתובת ה-URL של האפליקציה שבהגדרות תואמת לכתובת ה-URL של הפונקציה של Cloud Functions או של נקודת הקצה של Cloud Run.
לאחר מכן תצטרכו לאשר את חשבון השירות ב-Google Chat chat@system.gserviceaccount.com
כ-invoker.
בשלבים הבאים מוסבר איך להשתמש ב-Cloud Functions (דור ראשון):
המסוף
אחרי פריסת הפונקציה ב-Google Cloud:
במסוף Google Cloud, נכנסים לדף Cloud Functions:
ברשימה של Cloud Functions, לוחצים על תיבת הסימון שליד הפונקציה המקבלת. (אין ללחוץ על הפונקציה עצמה).
לוחצים על הרשאות בחלק העליון של המסך. החלונית Permissions תיפתח.
לוחצים על Add principal.
בשדה New principals, מזינים
chat@system.gserviceaccount.com
.בתפריט הנפתח Select a role, בוחרים את התפקיד Cloud Functions > Cloud Functions Invoker.
לוחצים על שמירה.
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:
במסוף Google Cloud, נכנסים לדף Cloud Run:
ברשימת השירותים של Cloud Run, לוחצים על תיבת הסימון שליד הפונקציה המקבלת. (אין ללחוץ על הפונקציה עצמה).
לוחצים על הרשאות בחלק העליון של המסך. החלונית Permissions תיפתח.
לוחצים על Add principal.
בשדה New principals, מזינים
chat@system.gserviceaccount.com
.בתפריט הנפתח Select a role, בוחרים את התפקיד Cloud Run > Cloud Run Invoker.
לוחצים על שמירה.
gcloud
משתמשים בפקודה gcloud functions add-invoker-policy-binding
:
gcloud functions add-invoker-policy-binding RECEIVING_FUNCTION \
--member='serviceAccount:chat@system.gserviceaccount.com'
מחליפים את RECEIVING_FUNCTION
בשם הפונקציה של אפליקציית Chat.
אימות בקשות באמצעות אסימון מזהה של כתובת URL של אפליקציה
אם השדה Authentication Audience בהגדרת החיבור של אפליקציית Chat מוגדר ל-App URL
, אסימון ההרשאה למוכ"ז בבקשה הוא אסימון מזהה של OpenID Connect בחתימה של Google.
השדה email
מוגדר ל-chat@system.gserviceaccount.com
.
השדה audience
מוגדר לכתובת ה-URL שהגדרתם ב-Google Chat כדי לשלוח בקשות לאפליקציית Chat. לדוגמה, אם נקודת הקצה (endpoint) של אפליקציית Chat היא https://example.com/app/
, השדה audience
באסימון המזהה הוא https://example.com/app/
.
הדוגמאות הבאות ממחישות איך לוודא שהאסימון למוכ"ז הונפק על ידי Google Chat ושהוא מטורגט לאפליקציה שלכם באמצעות ספריית הלקוח של OAuth של Google.
Java
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");
}
}
Python
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 של מספר פרויקט
אם השדה Authentication Audience (קהל האימות) בהגדרת החיבור של אפליקציית Chat מוגדר ל-Project
Number
, אסימון ההרשאה למוכ"ז בבקשה הוא JSON Web Token (JWT) בחתימה עצמית,
שהונפק ונחתם על ידי chat@system.gserviceaccount.com
.
השדה audience
מוגדר למספר הפרויקט ב-Google Cloud שבו השתמשתם כדי ליצור את אפליקציית Chat. לדוגמה, אם מספר הפרויקט ב-Cloud באפליקציית Chat הוא 1234567890
, השדה audience
ב-JWT הוא 1234567890
.
הדוגמאות הבאות ממחישות איך לוודא שהאסימון למוכ"ז הונפק על ידי Google Chat ושהוא מטורגט לפרויקט שלכם באמצעות ספריית הלקוח של OAuth של Google.
Java
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");
}
}
Python
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();
נושאים קשורים
- במאמר מידע על אימות והרשאה תוכלו לקרוא סקירה כללית על אימות והרשאה ב-Google Workspace.
- במאמר סקירה כללית על אימות תוכלו לקרוא סקירה כללית על אימות והרשאה ב-Chat.
- אפשר להגדיר אימות והרשאה באמצעות פרטי הכניסה של משתמש או באמצעות חשבון שירות.