Verificare le richieste da Google Chat

Per le app Google Chat create su endpoint HTTP, questa sezione spiega come verificare che le richieste al tuo endpoint provengano da Chat.

Per inviare gli eventi di interazione all'endpoint della tua app Chat, Google invia richieste al tuo servizio. Per verificare che la richiesta provenga da Google, Chat include un token bearer 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 del portatore. Si tratta di un token crittografico prodotto da Google. Il tipo di token di accesso e il valore del campo audience dipendono dal tipo di pubblico di 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 invocatore autorizzato. Se la tua app implementa il proprio server HTTP, puoi verificare il token di accesso utilizzando una libreria client dell'API di Google open source:

Se il token non viene verificato per l'app Chat, il servizio deve rispondere alla richiesta con un codice di risposta HTTPS401 (Unauthorized).

Autentica le richieste utilizzando Cloud Functions o Cloud Run

Se la logica della funzione è implementata utilizzando Cloud Functions o Cloud Run, devi selezionare URL endpoint HTTP nel campo Authentication Audience (Pubblico di autenticazione) dell'impostazione di connessione dell'app Chat e assicurarti che l'URL endpoint HTTP nella configurazione corrisponda all'URL dell'endpoint Cloud Functions o Cloud Run.

Poi, devi autorizzare l'account di servizio Google Chatchat@system.gserviceaccount.com come invocatore.

I passaggi che seguono mostrano come utilizzare Cloud Functions (1ª gen.):

Console

Dopo aver eseguito il deployment della funzione in Google Cloud:

  1. Nella console Google Cloud, vai alla pagina Cloud Functions:

    Vai a Cloud Functions

  2. Nell'elenco di Cloud Functions, fai clic sulla casella di controllo accanto alla funzione di ricezione. Non fare clic sulla funzione stessa.

  3. Fai clic su Autorizzazioni nella parte superiore dello schermo. Viene visualizzato il riquadro Autorizzazioni.

  4. Fai clic su Aggiungi entità.

  5. Nel campo Nuove entità, inserisci chat@system.gserviceaccount.com.

  6. Seleziona il ruolo Cloud Functions > Cloud Functions Invoker dal menu a discesa Seleziona un ruolo.

  7. Fai clic su Salva.

gcloud

Utilizza 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 Chat.

I passaggi che seguono mostrano come utilizzare i servizi Cloud Functions (2ª gen.) o Cloud Run:

Console

Dopo aver eseguito il deployment della funzione o del servizio in Google Cloud:

  1. Nella console Google Cloud, vai alla pagina Cloud Run:

    Vai a Cloud Run

  2. Nell'elenco dei servizi Cloud Run, fai clic sulla casella di controllo accanto alla funzione di ricezione. Non fare clic sulla funzione stessa.

  3. Fai clic su Autorizzazioni nella parte superiore dello schermo. Viene visualizzato il riquadro Autorizzazioni.

  4. Fai clic su Aggiungi entità.

  5. Nel campo Nuove entità, inserisci chat@system.gserviceaccount.com.

  6. Seleziona il ruolo Cloud Run > Cloud Run Invoker dal menu a discesa Seleziona un ruolo.

  7. 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 Chat.

Autentica le richieste HTTP con un token ID

Se il campo Authentication Audience dell'impostazione di connessione dell'app Chat è impostato su URL endpoint HTTP, il token di autorizzazione con il ruolo di portatore nella richiesta è un token ID OpenID Connect (OIDC) firmato da Google. Il campo email è impostato su chat@system.gserviceaccount.com. Il campo Authentication Audience (Pubblico di autenticazione) è impostato sull'URL che hai configurato per Google Chat per inviare richieste alla tua app di Chat. Ad esempio, se l'endpoint configurato della tua app di Chat è https://example.com/app/, il campo Authentication Audience (Pubblico di autenticazione) nel token ID è https://example.com/app/.

Gli esempi riportati di seguito mostrano come verificare che il token di accesso sia stato emesso da Google Chat e abbia come target la tua app utilizzando la libreria client OAuth di 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/app-di-base/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

node/app-di-base/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;
}

Autentica le richieste con un JWT del numero di progetto

Se il campo Authentication Audience dell'impostazione di connessione dell'app Chat è impostato su Project Number, il token di autorizzazione con portatore 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 utilizzato per creare l'app Chat. Ad esempio, se il numero di progetto Cloud dell'app Chat è 1234567890, il campo audience nel JWT è 1234567890.

Gli esempi riportati di seguito mostrano come verificare che il token di accesso sia stato emesso da Google Chat e abbia come target il tuo progetto utilizzando la libreria client OAuth di 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();

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/app-di-base/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

node/app-di-base/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;
}