Verificare le richieste da Google Chat

Per le app di 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 di Chat, Google effettua richieste al tuo servizio. Per verificare che la richiesta provenga da Google, Chat include un token di autenticazione 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 autenticazione. Si tratta di un token crittografico prodotto da Google. Il tipo di token di autenticazione e il valore del campo audience dipendono dal tipo di pubblico di autenticazione selezionato quando configuri l'app di Chat.

Se hai implementato l'app di Chat utilizzando Cloud Run Functions, Cloud IAM gestisce automaticamente la verifica dei token. Devi aggiungere il service account di Google Chat come invoker autorizzato. Se la tua app implementa il proprio server HTTP, puoi verificare il token di connessione utilizzando una libreria client delle API di Google open source:

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

Autenticare le richieste utilizzando Cloud Run Functions

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

Dopodiché, devi autorizzare il service account di Google Chat chat@system.gserviceaccount.com come invoker seguendo questi passaggi:

Console

Dopo aver eseguito il deployment della funzione o del servizio su 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 ricevente. (Non fare clic sulla funzione stessa.)

  3. Fai clic su Autorizzazioni nella parte superiore della schermata. Si apre il riquadro Autorizzazioni.

  4. Fai clic su Aggiungi entità.

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

  6. Dal menu Seleziona un ruolo, seleziona il ruolo Cloud Run

    Invoker di Cloud Run.

  7. Fai clic su Salva.

gcloud

Utilizza 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 dell'app di Chat.

Autenticare le richieste HTTP con un token ID

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

Questo è il metodo di autenticazione consigliato se l'endpoint HTTP non è ospitato su un servizio che supporta l'autenticazione basata su IAM (ad esempio Cloud Run). Utilizzando questo metodo, il servizio HTTP ha bisogno di informazioni sull'URL dell'endpoint in cui è in esecuzione, ma non ha bisogno di informazioni sul numero di progetto Cloud.

I seguenti esempi mostrano come verificare che il token di connessione sia stato emesso da Google Chat e sia destinato alla tua app utilizzando la libreria client 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();

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

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

Autenticare le richieste con un JWT del numero di progetto

Se il campo Pubblico di autenticazione dell'app di Chat impostazione di connessione è impostato su Project Number, il token di autorizzazione di autenticazione nella richiesta è un token JSON Web Token (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 della tua app di Chat è 1234567890, il campo audience nel JWT è 1234567890.

Questo metodo di autenticazione è consigliato solo se preferisci utilizzare il numero di progetto Cloud per verificare le richieste anziché l'URL dell'endpoint HTTP. Ad esempio, se vuoi modificare l'URL dell'endpoint nel tempo mantenendo lo stesso numero di progetto Cloud o se vuoi utilizzare lo stesso endpoint per più numeri di progetto Cloud e vuoi confrontare il campo audience con un elenco di numeri di progetto Cloud.

I seguenti esempi mostrano come verificare che il token di connessione sia stato emesso da Google Chat e sia destinato al tuo progetto utilizzando la libreria client 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

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