Weryfikowanie próśb z Google Chat

W tej sekcji dowiesz się, jak w przypadku aplikacji Google Chat utworzonych na podstawie punktów końcowych HTTP sprawdzić, czy żądania kierowane do Twojego punktu końcowego pochodzą z Google Chat.

Aby wysyłać zdarzenia interakcji do punktu końcowego aplikacji Google Chat, Google wysyła żądania do Twojej usługi. Aby sprawdzić, czy żądanie jest przychodzące z Google, Google Chat dołącza token okaziciela w nagłówku Authorization każdego żądania HTTPS do Twojego punktu końcowego. Przykład:

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

Ciąg znaków AbCdEf123456 w poprzednim przykładzie to token autoryzacji okaziciela. Jest to token kryptograficzny wygenerowany przez Google. Typ tokena okaziciela i wartość pola audience zależą od typu odbiorców uwierzytelniania wybranego podczas konfigurowania aplikacji Google Chat.

Jeśli aplikacja Google Chat została wdrożona przy użyciu funkcji Cloud Run, Cloud IAM automatycznie obsługuje weryfikację tokena. Musisz dodać konto usługi Google Chat jako autoryzowanego wywołującego. Jeśli Twoja aplikacja implementuje własny serwer HTTP, możesz zweryfikować token okaziciela za pomocą biblioteki klienta interfejsu API Google o otwartym kodzie źródłowym:

Jeśli token nie zostanie zweryfikowany w aplikacji Google Chat, Twoja usługa powinna odpowiedzieć na żądanie kodem odpowiedzi HTTPS 401 (Unauthorized).

Uwierzytelnianie żądań za pomocą funkcji Cloud Run

Jeśli logika funkcji jest zaimplementowana przy użyciu funkcji Cloud Run, musisz wybrać Adres URL punktu końcowego HTTP w polu Odbiorcy uwierzytelniania w ustawieniach połączenia aplikacji Google Chat i upewnić się, że adres URL punktu końcowego HTTP w konfiguracji odpowiada adresowi URL punktu końcowego funkcji Cloud Run.

Następnie musisz autoryzować konto usługi Google Chat chat@system.gserviceaccount.com jako wywołującego, wykonując te czynności:

Konsola

Po wdrożeniu funkcji lub usługi w Google Cloud:

  1. W konsoli Google Cloud otwórz stronę Cloud Run:

    Otwórz Cloud Run

  2. Na liście usług Cloud Run kliknij pole wyboru obok funkcji odbierającej. (Nie klikaj samej funkcji).

  3. U góry ekranu kliknij Uprawnienia. Otworzy się panel Uprawnienia.

  4. Kliknij Dodaj podmiot zabezpieczeń.

  5. W polu Nowe podmioty zabezpieczeń wpisz chat@system.gserviceaccount.com.

  6. W menu Wybierz rolę wybierz rolę Cloud Run

    Wywołujący Cloud Run.

  7. Kliknij Zapisz.

gcloud

Użyj polecenia gcloud functions add-invoker-policy-binding:

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

Zastąp RECEIVING_FUNCTION nazwą funkcji aplikacji Google Chat.

Uwierzytelnianie żądań HTTP za pomocą tokena identyfikatora

Jeśli pole Odbiorcy uwierzytelniania w ustawieniach połączenia aplikacji Google Chat jest ustawione na **Adres URL punktu końcowego HTTP** , token autoryzacji okaziciela w żądaniu jest tokenem identyfikatora OpenID Connect (OIDC) podpisanym przez Google. Pole email jest ustawione na chat@system.gserviceaccount.com. Pole Odbiorcy uwierzytelniania jest ustawione na adres URL, który został skonfigurowany w Google Chat do wysyłania żądań do aplikacji Google Chat. Jeśli na przykład skonfigurowany punkt końcowy aplikacji Google Chat to https://example.com/app/, pole Odbiorcy uwierzytelniania w tokenie identyfikatora to https://example.com/app/.

Jest to zalecana metoda uwierzytelniania, jeśli punkt końcowy HTTP nie jest hostowany w usłudze, która obsługuje uwierzytelnianie oparte na IAM (np. Cloud Run). W przypadku tej metody usługa HTTP potrzebuje informacji o adresie URL punktu końcowego, w którym jest uruchomiona, ale nie potrzebuje informacji o numerze projektu w chmurze.

Te przykłady pokazują, jak sprawdzić, czy token okaziciela został wydany przez Google Chat i jest przeznaczony dla Twojej aplikacji, za pomocą biblioteki klienta 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;
}

Uwierzytelnianie żądań za pomocą tokena JWT z numerem projektu

Jeśli pole Odbiorcy uwierzytelniania w ustawieniach połączenia aplikacji Google Chat jest ustawione na Project Number, token autoryzacji okaziciela w żądaniu jest tokenem internetowym JSON (JWT) z podpisem własnym , wydanym i podpisanym przez chat@system.gserviceaccount.com. Pole audience jest ustawione na numer projektu Google Cloud, którego używasz do tworzenia aplikacji Google Chat. Jeśli na przykład numer projektu w chmurze aplikacji Google Chat to 1234567890, pole audience w tokenie JWT to 1234567890.

Ta metoda uwierzytelniania jest zalecana tylko wtedy, gdy do weryfikowania żądań wolisz używać numeru projektu w chmurze zamiast adresu URL punktu końcowego HTTP. Na przykład jeśli chcesz z czasem zmieniać adres URL punktu końcowego, zachowując ten sam numer projektu w chmurze, lub jeśli chcesz używać tego samego punktu końcowego w przypadku wielu numerów projektów w chmurze i chcesz porównać pole audience z listą numerów projektów w chmurze.

Te przykłady pokazują, jak sprawdzić, czy token okaziciela został wydany przez Google Chat i jest przeznaczony dla Twojego projektu, za pomocą biblioteki klienta 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;
}