Per le app di Google Chat basate su endpoint HTTP, questa sezione spiega come verificare che le richieste al tuo endpoint provengano da Chat.
Per inviare eventi di interazione all'endpoint
della tua app Chat, Google effettua richieste al tuo servizio. Per verificare che la richiesta provenga
da Google, Chat include un
token di connessione
nell'intestazione Authorization
di ogni richiesta HTTPS al tuo endpoint. Ad
esempio:
POST
Host: yourappurl.com
Authorization: Bearer AbCdEf123456
Content-Type: application/json
User-Agent: Google-Dynamite
La stringa AbCdEf123456
nell'esempio precedente è il token
di autorizzazione di connessione. Si tratta di un token crittografico prodotto da Google. Il tipo di token di connessione e il valore del campo audience
dipendono dal tipo di segmento di pubblico per l'autenticazione selezionato durante la configurazione dell'app Chat.
Se hai implementato l'app di chat utilizzando Cloud Functions o Cloud Run, Cloud IAM gestisce la verifica dei token automaticamente. Devi solo aggiungere l'account di servizio Google Chat come callback autorizzato. Se la tua app implementa il proprio server HTTP, puoi verificare il token di connessione utilizzando una libreria client API di Google open source:
- 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
Se il token non viene verificato per l'app Chat, il servizio deve rispondere alla richiesta con un codice di risposta HTTPS 401 (Unauthorized)
.
Autentica le richieste utilizzando Cloud Functions o Cloud Run
Se la logica della funzione viene implementata utilizzando Cloud Functions o Cloud Run, devi selezionare App URL
nel campo Authentication Audience dell'impostazione di connessione dell'app Chat e assicurarti che l'URL dell'app nella configurazione corrisponda all'URL della funzione Cloud Functions o dell'endpoint Cloud Run.
Quindi, devi autorizzare l'account di servizio Google Chat
chat@system.gserviceaccount.com
come callback.
I passaggi seguenti mostrano come utilizzare Cloud Functions (1a gen.):
Console
Dopo aver eseguito il deployment della funzione in Google Cloud:
Nella console Google Cloud, vai alla pagina Cloud Functions:
Nell'elenco di Cloud Functions, fai clic sulla casella di controllo accanto alla funzione di ricezione. Non fare clic sulla funzione in sé.
Fai clic su Autorizzazioni nella parte superiore dello schermo. Si apre il riquadro Autorizzazioni.
Fai clic su Aggiungi entità.
Nel campo Nuove entità, inserisci
chat@system.gserviceaccount.com
.Seleziona il ruolo Cloud Functions > Invoker di Cloud Functions dal menu a discesa Seleziona un ruolo.
Fai clic su Salva.
gcloud
Usa il comando gcloud functions add-iam-policy-binding
:
gcloud functions add-iam-policy-binding RECEIVING_FUNCTION \
--member='serviceAccount:chat@system.gserviceaccount.com' \
--role='roles/cloudfunctions.invoker'
Sostituisci RECEIVING_FUNCTION
con il nome della funzione
della tua app di Chat.
I passaggi seguenti mostrano come utilizzare i servizi Cloud Functions (2a gen.) o Cloud Run:
Console
Dopo aver eseguito il deployment della funzione o del servizio in Google Cloud:
Nella console Google Cloud, vai alla pagina Cloud Run:
Nell'elenco dei servizi Cloud Run, fai clic sulla casella di controllo accanto alla funzione di ricezione. Non fare clic sulla funzione in sé.
Fai clic su Autorizzazioni nella parte superiore dello schermo. Si apre il riquadro Autorizzazioni.
Fai clic su Aggiungi entità.
Nel campo Nuove entità, inserisci
chat@system.gserviceaccount.com
.Seleziona il ruolo Cloud Run > Invoker di Cloud Run dal menu a discesa Seleziona un ruolo.
Fai clic su Salva.
gcloud
Usa il comando gcloud functions add-invoker-policy-binding
:
gcloud functions add-invoker-policy-binding RECEIVING_FUNCTION \
--member='serviceAccount:chat@system.gserviceaccount.com'
Sostituisci RECEIVING_FUNCTION
con il nome della funzione
della tua app di Chat.
Autentica le richieste con un token ID URL app
Se il campo Authentication Audience dell'impostazione di connessione dell'app di Chat è impostato su App URL
, il token di autorizzazione di connessione nella richiesta è un token ID OpenID Connect (OIDC) firmato da Google.
Il campo email
è impostato su chat@system.gserviceaccount.com
.
Il campo audience
è impostato sull'URL che hai configurato con Google Chat per inviare
richieste alla tua app Chat. Ad esempio, se
l'endpoint configurato dell'app di Chat è
https://example.com/app/
, il campo audience
nel token ID è
https://example.com/app/
.
Gli esempi riportati di seguito mostrano come verificare che il token di connessione sia stato emesso da Google Chat e scelto come target della tua app utilizzando la libreria client OAuth di 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();
Autentica le richieste con un JWT con numero di progetto
Se il campo Authentication Audience dell'impostazione di connessione dell'app di Chat è impostato su Project
Number
, il token di autorizzazione di connessione nella richiesta è un token web JSON (JWT) autofirmato, emesso e firmato da chat@system.gserviceaccount.com
.
Il campo audience
è impostato sul numero di progetto Google Cloud che hai utilizzato
per creare l'app di Chat. Ad esempio, se il
numero di progetto Cloud dell'app di Chat è
1234567890
, il campo audience
nel JWT è 1234567890
.
Gli esempi riportati di seguito mostrano come verificare che il token di connessione sia stato emesso da Google Chat e scelto come target del tuo progetto utilizzando la libreria client OAuth di 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();
Argomenti correlati
- Per una panoramica dell'autenticazione e dell'autorizzazione in Google Workspace, consulta Scopri di più su autenticazione e autorizzazione.
- Per una panoramica dell'autenticazione e dell'autorizzazione in Chat, consulta Panoramica dell'autenticazione.
- Configura l'autenticazione e l'autorizzazione con le credenziali utente o un account di servizio.