HTTP uç noktaları üzerine oluşturulan Google Chat uygulamaları için bu bölümde, uç noktanıza gelen isteklerin Chat'ten geldiğini nasıl doğrulayacağınız açıklanmaktadır.
Google, etkileşim etkinliklerini Chat uygulamanızın uç noktasına göndermek için hizmetinize istekler gönderir. İsteğin Google'dan geldiğini doğrulamak için Chat, uç noktanıza gönderilen her HTTPS isteğinin Authorization
başlığına bir hamiline ait jeton ekler. Örneğin:
POST
Host: yourappurl.com
Authorization: Bearer AbCdEf123456
Content-Type: application/json
User-Agent: Google-Dynamite
Yukarıdaki örnekte yer alan AbCdEf123456
dizesi, hamiline ait yetkilendirme jetonudur. Bu, Google tarafından oluşturulan bir şifreleme jetonudur. Hamiline ait jetonun türü ve audience
alanının değeri, Chat uygulamasını yapılandırırken seçtiğiniz kimlik doğrulama kitlesi türüne bağlıdır.
Chat uygulamanızı Cloud Functions veya Cloud Run'ı kullanarak uyguladıysanız Cloud IAM, jeton doğrulamasını otomatik olarak gerçekleştirir. Google Chat hizmet hesabını yetkili bir çağrıcı olarak eklemeniz yeterlidir. Uygulamanız kendi HTTP sunucusunu uyguluyorsa açık kaynak bir Google API istemci kitaplığı kullanarak hamiline ait jetonunuzu doğrulayabilirsiniz:
- 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
Jeton, Chat uygulamasını doğrulamazsa hizmetiniz isteğe HTTPS yanıt koduyla (401 (Unauthorized)
) yanıt vermelidir.
Cloud Functions veya Cloud Run kullanarak isteklerin kimliğini doğrulama
İşlev mantığınız Cloud Functions veya Cloud Run kullanılarak uygulandıysa Chat uygulaması bağlantı ayarının Kimlik Doğrulama Kitlesi alanında App URL
öğesini seçmeniz ve yapılandırmadaki uygulama URL'sinin Cloud Functions veya Cloud Run uç noktasının URL'sine karşılık geldiğinden emin olmanız gerekir.
Ardından, Google Chat hizmet hesabını (chat@system.gserviceaccount.com
) çağırıcı olarak yetkilendirmeniz gerekir.
Aşağıdaki adımlarda Cloud Functions'ın (1. nesil) nasıl kullanılacağı gösterilmektedir:
Konsol
İşlevinizi Google Cloud'a dağıttıktan sonra:
Google Cloud Console'da Cloud Functions sayfasına gidin:
Cloud Functions listesinde, alma işlevinin yanındaki onay kutusunu tıklayın. (İşlevi tıklamayın.)
Ekranın üst kısmındaki İzinler'i tıklayın. İzinler paneli açılır.
Ana hesap ekle'yi tıklayın.
Yeni ana hesaplar alanına
chat@system.gserviceaccount.com
yazın.Rol seçin açılır menüsünden Cloud Functions > Cloud Functions Çağırıcısı rolünü seçin.
Kaydet'i tıklayın.
gcloud
gcloud functions add-iam-policy-binding
komutunu kullanın:
gcloud functions add-iam-policy-binding RECEIVING_FUNCTION \
--member='serviceAccount:chat@system.gserviceaccount.com' \
--role='roles/cloudfunctions.invoker'
RECEIVING_FUNCTION
değerini Chat uygulamanızın işlevinin adıyla değiştirin.
Aşağıdaki adımlarda, Cloud Functions (2. nesil) veya Cloud Run hizmetlerinin nasıl kullanılacağı gösterilmektedir:
Konsol
İşlevinizi veya hizmetinizi Google Cloud'a dağıttıktan sonra:
Google Cloud Console'da Cloud Run sayfasına gidin:
Cloud Run hizmetleri listesinde, alma işlevinin yanındaki onay kutusunu tıklayın. (İşlevi tıklamayın.)
Ekranın üst kısmındaki İzinler'i tıklayın. İzinler paneli açılır.
Ana hesap ekle'yi tıklayın.
Yeni ana hesaplar alanına
chat@system.gserviceaccount.com
yazın.Rol seçin açılır menüsünden Cloud Run > Cloud Run Çağırıcısı rolünü seçin.
Kaydet'i tıklayın.
gcloud
gcloud functions add-invoker-policy-binding
komutunu kullanın:
gcloud functions add-invoker-policy-binding RECEIVING_FUNCTION \
--member='serviceAccount:chat@system.gserviceaccount.com'
RECEIVING_FUNCTION
değerini Chat uygulamanızın işlevinin adıyla değiştirin.
Uygulama URL'si Kimliği Jetonu ile isteklerin kimliğini doğrulama
Chat uygulaması bağlantı ayarının Authentication Audience (Kimlik Doğrulama Kitlesi) alanı App URL
olarak ayarlanırsa istekteki hamiline ait yetkilendirme jetonu, Google tarafından imzalanmış bir RFC Connect (OIDC) kimlik jetonudur.
email
alanı chat@system.gserviceaccount.com
olarak ayarlanmış.
audience
alanı, Google Chat'i Chat uygulamanıza istek göndermesi için yapılandırdığınız URL olarak ayarlanır. Örneğin, Chat uygulamanızın yapılandırılmış uç noktası https://example.com/app/
ise kimlik jetonunda audience
alanı https://example.com/app/
olur.
Aşağıdaki örneklerde, hamiline ait jetonun Google Chat tarafından yayınlandığını ve Google OAuth istemci kitaplığı kullanılarak uygulamanızı hedeflediğinin nasıl doğrulanacağı gösterilmektedir.
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();
Proje Numarası JWT ile isteklerin kimliğini doğrulama
Chat uygulaması bağlantı ayarının Authentication Audience alanı Project
Number
olarak ayarlanırsa istekteki hamiline ait yetkilendirme jetonu, chat@system.gserviceaccount.com
tarafından yayınlanan ve imzalanan kendinden imzalı bir JSON Web Jetonu (JWT) olur.
audience
alanı, Chat uygulamanızı oluşturmak için kullandığınız Google Cloud proje numarası olarak ayarlanır. Örneğin, Chat uygulamanızın Cloud proje numarası 1234567890
ise JWT'deki audience
alanı 1234567890
olur.
Aşağıdaki örneklerde, hamiline ait jetonun Google Chat tarafından yayınlandığını ve Google OAuth istemci kitaplığı kullanılarak projenizi hedeflediğinin nasıl doğrulanacağı gösterilmektedir.
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();
İlgili konular
- Google Workspace'te kimlik doğrulama ve yetkilendirmeye genel bakış için Kimlik doğrulama ve yetkilendirme hakkında bilgi edinme başlıklı makaleyi inceleyin.
- Chat'te kimlik doğrulama ve yetkilendirmeye genel bir bakış için Kimlik doğrulamaya genel bakış bölümüne göz atın.
- Kullanıcı kimlik bilgileri veya hizmet hesabı ile kimlik doğrulama ve yetkilendirme ayarlayın.