Verify requests from Google Chat

For Google Chat apps built on HTTP endpoints, this section explains how to verify that the requests to your endpoint come from Chat.

To dispatch interaction events to your Chat app's endpoint, Google makes requests to your service. To verify that the request is coming from Google, Chat includes a bearer token in the Authorization header of every HTTPS request to your endpoint. For example:

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

The string AbCdEf123456 in the preceding example is the bearer authorization token. This is a cryptographic token produced by Google. The type of the bearer token and the value of the audience field depend on the type of authentication audience you selected when configuring the Chat app .

If you've implemented your Chat app using Cloud Functions or Cloud Run, Cloud IAM handles token verification automatically. You just need to add the Google Chat service account as an authorized invoker. If your app implements its own HTTP server, you can verify your bearer token using an open source Google API client library :

If the token doesn't verify for the Chat app, your service should respond to the request with an HTTPS response code 401 (Unauthorized) .

Authenticate requests using Cloud Functions or Cloud Run

If your function logic is implemented using Cloud Functions or Cloud Run, you must select HTTP endpoint URLin the Authentication Audiencefield of the Chat app connection setting and make sure that the HTTP endpoint URL in the configuration corresponds to the URL of the Cloud Function or Cloud Run endpoint.

Then, you need to authorize the Google Chat service account chat@system.gserviceaccount.com as an invoker.

The following steps shows how to use Cloud Functions (1st gen):

Console

After deploying your function to Google Cloud:

  1. In the Google Cloud console, go to the Cloud Functions page:

    Go to Cloud Functions

  2. In the Cloud Functions list, click the checkbox next to the receiving function. (Don't click the function itself.)

  3. Click Permissionsat the top of the screen. The Permissionspanel opens.

  4. Click Add principal.

  5. In the New principalsfield, enter chat@system.gserviceaccount.com .

  6. Select the role Cloud Functions> Cloud Functions Invokerfrom the Select a roledrop-down menu.

  7. Click Save.

gcloud

Use the gcloud functions add-iam-policy-binding command:

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

Replace RECEIVING_FUNCTION with the name of your Chat app's function.

The following steps shows how to use Cloud Functions (2nd gen) or Cloud Run services:

Console

After deploying your function or service to Google Cloud:

  1. In the Google Cloud console, go to the Cloud Run page:

    Go to Cloud Run

  2. In the Cloud Run services list, click the checkbox next to the receiving function. (Don't click the function itself.)

  3. Click Permissionsat the top of the screen. The Permissionspanel opens.

  4. Click Add principal.

  5. In the New principalsfield, enter chat@system.gserviceaccount.com .

  6. Select the role Cloud Run> Cloud Run Invokerfrom the Select a roledrop-down menu.

  7. Click Save.

gcloud

Use the gcloud functions add-invoker-policy-binding command:

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

Replace RECEIVING_FUNCTION with the name of your Chat app's function.

Authenticate HTTP requests with an ID Token

If the Authentication Audience field of the Chat app connection setting is set to HTTP endpoint URL, the bearer authorization token in the request is a Google-signed OpenID Connect (OIDC) ID token . The email field is set to chat@system.gserviceaccount.com . The Authentication Audiencefield is set to the URL you configured Google Chat to send requests to your Chat app. For example, if the configured endpoint of your Chat app is https://example.com/app/ , then the Authentication Audiencefield in the ID token is https://example.com/app/ .

This is the recommended authentication method if your HTTP endpoint isn't hosted on a service that supports IAM-based authentication (such as Cloud Functions or Cloud Run). Using this method, your HTTP service needs information about the URL of the endpoint where it's running, but doesn't need information about the Cloud project number.

The following samples show how to verify that the bearer token was issued by Google Chat and targeted at your app using the Google OAuth client library.

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

Authenticate requests with a Project Number JWT

If the Authentication Audience field of the Chat app connection setting is set to Project Number , the bearer authorization token in the request is a self-signed JSON Web Token (JWT) , issued and signed by chat@system.gserviceaccount.com . The audience field is set to the Google Cloud project number that you used to build your Chat app. For example, if your Chat app's Cloud project number is 1234567890 , then the audience field in the JWT is 1234567890 .

This authentication method is only recommended if you prefer to use the Cloud project number to verify requests instead of the HTTP endpoint URL. For example, if you want to change the endpoint URL over time while keeping the same Cloud project number, or if you want to use the same endpoint for multiple Cloud project numbers and want to compare the audience field with a list of Cloud project numbers.

The following samples show how to verify that the bearer token was issued by Google Chat and targeted at your project using the Google OAuth client library.

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 
 ; 
 } 
Create a Mobile Website
View Site in Mobile | Classic
Share by: