Anfragen von Google Chat prüfen

In diesem Abschnitt wird beschrieben, wie Sie bei Google Chat-Apps, die auf HTTP-Endpunkten basieren, prüfen, ob die Anfragen an Ihren Endpunkt von Google Chat stammen.

Um Interaktionsereignisse an den Endpunkt Ihrer Chat-App zu senden, sendet Google Anfragen an Ihren Dienst. Um zu prüfen, ob die Anfrage von Google stammt, fügt Google Chat in den Authorization-Header jeder HTTPS-Anfrage an Ihren Endpunkt ein Bearer-Token ein. Beispiel:

POST
Host: yourappurl.com
Authorization: Bearer AbCdEf123456
Content-Type: application/json
User-Agent: Google-Dynamite

Der String AbCdEf123456 im vorherigen Beispiel ist das Bearer-Autorisierungstoken. Dies ist ein kryptografisches Token, das von Google erstellt wird. Der Typ des Bearer-Tokens und der Wert des Felds audience hängen davon ab, welche Art von Authentifizierungsgruppe Sie bei der Konfiguration der Chat-App ausgewählt haben.

Wenn Sie Ihre Chat-App mit Cloud Functions oder Cloud Run implementiert haben, wird die Tokenbestätigung automatisch von Cloud IAM durchgeführt. Sie müssen lediglich das Google Chat-Dienstkonto als autorisierten Aufrufer hinzufügen. Wenn Ihre App einen eigenen HTTP-Server implementiert, können Sie Ihr Bearer-Token mit einer Open-Source-Google API-Clientbibliothek überprüfen:

Wenn das Token nicht für die Chat-App bestätigt wird, sollte Ihr Dienst mit dem HTTPS-Antwortcode 401 (Unauthorized) auf die Anfrage antworten.

Anfragen mit Cloud Functions oder Cloud Run authentifizieren

Wenn Ihre Funktionslogik mit Cloud Functions oder Cloud Run implementiert ist, müssen Sie in der Verbindungseinstellung der Chat-App im Feld Authentication Audience (Authentifizierungszielgruppe) die Option HTTP endpoint URL (HTTP-Endpunkt-URL) auswählen und darauf achten, dass die HTTP-Endpunkt-URL in der Konfiguration der URL des Cloud Functions- oder Cloud Run-Endpunkts entspricht.

Anschließend müssen Sie das Google Chat-Dienstkonto chat@system.gserviceaccount.com als Auslöser autorisieren.

In den folgenden Schritten wird gezeigt, wie Sie Cloud Functions (1. Generation) verwenden:

Console

Nachdem Sie die Funktion in Google Cloud bereitgestellt haben:

  1. Wechseln Sie in der Google Cloud Console zur Seite Cloud Functions:

    Zu Cloud Functions

  2. Klicken Sie in der Liste „Cloud Functions“ auf das Kästchen neben der empfangenden Funktion. (Klicken Sie nicht auf die Funktion selbst.)

  3. Klicken Sie oben auf dem Bildschirm auf Berechtigungen. Der Bereich Berechtigungen wird geöffnet.

  4. Klicken Sie auf Hauptkonto hinzufügen.

  5. Geben Sie im Feld Neue Hauptkonten chat@system.gserviceaccount.com ein.

  6. Wählen Sie im Drop-down-Menü Rolle auswählen die Rolle Cloud Functions > Cloud Functions-Invoker aus.

  7. Klicken Sie auf Speichern.

gcloud

Führen Sie den Befehl gcloud functions add-iam-policy-binding aus:

gcloud functions add-iam-policy-binding RECEIVING_FUNCTION \
  --member='serviceAccount:chat@system.gserviceaccount.com' \
  --role='roles/cloudfunctions.invoker'

Ersetzen Sie RECEIVING_FUNCTION durch den Namen der Funktion Ihrer Chat-App.

In den folgenden Schritten wird gezeigt, wie Sie Cloud Functions (2. Generation) oder Cloud Run-Dienste verwenden:

Console

Nach dem Bereitstellen Ihrer Funktion oder Ihres Dienstes in Google Cloud:

  1. Wechseln Sie in der Google Cloud Console zur Seite Cloud Run.

    Zu Cloud Run

  2. Klicken Sie in der Liste der Cloud Run-Dienste auf das Kästchen neben der empfangenden Funktion. (Klicken Sie nicht auf die Funktion selbst.)

  3. Klicken Sie oben auf dem Bildschirm auf Berechtigungen. Der Bereich Berechtigungen wird geöffnet.

  4. Klicken Sie auf Hauptkonto hinzufügen.

  5. Geben Sie im Feld Neue Hauptkonten chat@system.gserviceaccount.com ein.

  6. Wählen Sie im Drop-down-Menü Rolle auswählen die Rolle Cloud Run > Cloud Run Invoker aus.

  7. Klicken Sie auf Speichern.

gcloud

Führen Sie den Befehl gcloud functions add-invoker-policy-binding aus:

gcloud functions add-invoker-policy-binding RECEIVING_FUNCTION \
  --member='serviceAccount:chat@system.gserviceaccount.com'

Ersetzen Sie RECEIVING_FUNCTION durch den Namen der Funktion Ihrer Chat-App.

HTTP-Anfragen mit einem ID-Token authentifizieren

Wenn das Feld „Authentication Audience“ (Authentifizierungszielgruppe) der Verbindungseinstellung der Chat-App auf HTTP-Endpunkt-URL festgelegt ist, ist das Bearer-Autorisierungstoken in der Anfrage ein von Google signiertes OpenID Connect-ID-Token (OIDC). Das Feld email ist auf chat@system.gserviceaccount.com gesetzt. Das Feld Authentication Audience (Authentifizierungszielgruppe) ist auf die URL festgelegt, die Sie für Google Chat konfiguriert haben, um Anfragen an Ihre Chat-App zu senden. Ist der konfigurierte Endpunkt Ihrer Chat-App beispielsweise https://example.com/app/, lautet das Feld Authentication Audience (Authentifizierungszielgruppe) im ID-Token https://example.com/app/.

Diese Authentifizierungsmethode wird empfohlen, wenn Ihr HTTP-Endpunkt nicht auf einem Dienst gehostet wird, der die IAM-basierte Authentifizierung unterstützt (z. B. Cloud Functions oder Cloud Run). Bei dieser Methode benötigt Ihr HTTP-Dienst Informationen zur URL des Endpunkts, an dem er ausgeführt wird, aber keine Informationen zur Cloud-Projektnummer.

In den folgenden Beispielen wird gezeigt, wie Sie mithilfe der Google OAuth-Clientbibliothek prüfen, ob das Bearer-Token von Google Chat ausgestellt wurde und auf Ihre App ausgerichtet ist.

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

Anfragen mit einem JWT für die Projektnummer authentifizieren

Wenn das Feld „Authentication Audience“ (Authentifizierungszielgruppe) der Verbindungseinstellung der Chat-App auf Project Number festgelegt ist, ist das Bearer-Autorisierungstoken in der Anfrage ein selbstsigniertes JSON Web Token (JWT), das von chat@system.gserviceaccount.com ausgestellt und signiert wurde. Das Feld audience ist auf die Google Cloud-Projektnummer festgelegt, mit der Sie Ihre Chat-App erstellt haben. Wenn die Cloud-Projektnummer Ihrer Chat-App beispielsweise 1234567890 ist, enthält das Feld audience im JWT die Zahl 1234567890.

Diese Authentifizierungsmethode wird nur empfohlen, wenn Sie zum Bestätigen von Anfragen die Cloud-Projektnummer anstelle der HTTP-Endpunkt-URL verwenden möchten. Das ist beispielsweise der Fall, wenn Sie die Endpunkt-URL im Laufe der Zeit ändern möchten, dabei aber dieselbe Cloud-Projektnummer beibehalten möchten, oder wenn Sie denselben Endpunkt für mehrere Cloud-Projektnummern verwenden und das Feld audience mit einer Liste von Cloud-Projektnummern vergleichen möchten.

In den folgenden Beispielen wird gezeigt, wie Sie mithilfe der Google OAuth-Clientbibliothek prüfen, ob das Bearer-Token von Google Chat ausgestellt wurde und auf Ihr Projekt ausgerichtet ist.

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