Authenticate as a Google Chat app

This guide explains how to set up and use a service account to access the Google Chat API on behalf of a Chat app. First, it walks you through how to create a service account. Then, it demonstrates how to write a script that uses the service account to authenticate with the Chat API and post a message in a Chat space.

Chat apps can use service accounts to authenticate when asynchronously calling the Google Chat API so they can:

  • Send messages to Google Chat with spaces.messages.create to:
    • Notify users when a long-running background job finishes running.
    • Alert users that a server has gone offline.
    • Ask a customer support person to tend to a newly opened customer case.
  • Update previously sent messages with spaces.messages.update to:
    • Change the status of on ongoing operation.
    • Update a task's assignee or due date.
  • List users in a space with spaces.members.list to:
    • See who is in a space.
    • Verify space membership includes everyone on a team.

When authenticated with a service account, to get data about or perform actions in a Chat space, Chat apps must have membership in the space. For example, to list members of a space, or to create a message in a space, the Chat app has to itself be a member of the space.

If your Chat app needs to access user data or perform actions on a user's behalf, authenticate as a user instead.

If you're a domain administrator, you can grant domain-wide delegation of authority to authorize an application's service account to access your users' data without requiring each user to give consent. After you configure domain-wide delegation, you can make API calls using your service account to impersonate a user account. Although a service account is used for authentication, domain-wide delegation impersonates a user and is therefore considered user authentication. Any functionality that requires user authentication, you can use domain-wide delegation.

To learn more about when Chat apps require authentication and what kind of authentication to use, see Types of required authentication in the Chat API authentication and authorization overview.

Prerequisites

To run the example in this guide, you need the following prerequisites:

Additionally, you need the following language-specific prerequisites:

Java

  • JDK 1.7 or greater
  • The Maven package management tool
  • An initialized Maven project. To initialize a new project, run the following command in your command-line interface:

    mvn archetype:generate -DgroupId=com.google.chat.app.authsample -DartifactId=auth-sample-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
    

Python

  • Python 3.6 or greater
  • The pip package management tool

Node.js

  • Node.js
  • The npm package management tool
  • An initialized Node.js project. To initialize a new project, create and switch into a new folder, then run the following command in your command-line interface:

    npm init
    

Apps Script

Step 1: Create a service account in Google Cloud console

Create a service account that your Chat app can use to access Google APIs.

Create a service account

To create a service account, follow these steps:

Google Cloud console

  1. In the Google Cloud console, go to Menu > IAM & Admin > Service Accounts.

    Go to Service Accounts

  2. Click Create service account.
  3. Fill in the service account details, then click Create and continue.
  4. Optional: Assign roles to your service account to grant access to your Google Cloud project's resources. For more details, refer to Granting, changing, and revoking access to resources.
  5. Click Continue.
  6. Optional: Enter users or groups that can manage and perform actions with this service account. For more details, refer to Managing service account impersonation.
  7. Click Done. Make a note of the email address for the service account.

gcloud CLI

  1. Create the service account:
    gcloud iam service-accounts create SERVICE_ACCOUNT_NAME \
      --display-name="SERVICE_ACCOUNT_NAME"
  2. Optional: Assign roles to your service account to grant access to your Google Cloud project's resources. For more details, refer to Granting, changing, and revoking access to resources.

The service account appears on the service account page. Next, create a private key for the service account.

Create a private key

To create and download a private key for the service account, follow these steps:

  1. In the Google Cloud console, go to Menu > IAM & Admin > Service Accounts.

    Go to Service Accounts

  2. Select your service account.
  3. Click Keys > Add key > Create new key.
  4. Select JSON, then click Create.

    Your new public/private key pair is generated and downloaded to your machine as a new file. Save the downloaded JSON file as credentials.json in your working directory. This file is the only copy of this key. For information about how to store your key securely, see Managing service account keys.

  5. Click Close.

For more information about service accounts, see service accounts in the Google Cloud IAM documentation.

Step 2: Install the Google client library and other dependencies

Install the Google client library and other dependencies required for the project.

Java

To add the Google client libraries and other required dependencies to your Maven project, edit the file pom.xml in your project's directory and add the following dependencies:

<dependencies>
  <!-- ... existing dependencies ... -->
  <dependency>
    <groupId>com.google.apis</groupId>
    <artifactId>google-api-services-chat</artifactId>
    <version>v1-rev20230905-2.0.0</version>
  </dependency>
  <dependency>
    <groupId>com.google.auth</groupId>
    <artifactId>google-auth-library-oauth2-http</artifactId>
    <version>1.19.0</version>
  </dependency>
  <dependency>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
      <version>2.10.1</version>
  </dependency>
</dependencies>

Python

If you haven't already installed the Google client libraries for Python, run the following command in your command-line interface:

pip3 install --upgrade google-api-python-client google-auth

Node.js

To add the Google client libraries to your Node.js project, switch into your project's directory and run the following command in your command-line interface:

npm install "@googleapis/chat"

Apps Script

This sample uses the OAuth2 for Apps Script library to generate a JWT token for service account authentication. To add the library to your Apps Script project:

  1. At the left, click Editor .
  2. At the left, next to Libraries, click Add a library .
  3. Enter the script ID 1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF.
  4. Click Look up, then click Add.

This sample uses the Advanced Chat service to call Google Chat API. To turn on the service for your Apps Script project:

  1. At the left, click Editor .
  2. At the left, next to Services, click Add a service .
  3. Select Google Chat API.
  4. In Version, select v1.
  5. Click Add.

You can use any language supported by our client libraries.

Step 3: Write a script that uses the service account to authenticate with Chat API

The following code authenticates with the Chat API using a service account, then posts a message to a Chat space:

Java

  1. In your project's directory, open the file src/main/java/com/google/chat/app/authsample/App.java.
  2. Replace the contents in App.java with the following code:

    package com.google.chat.app.authsample;
    
    import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
    import com.google.api.client.http.HttpRequestInitializer;
    import com.google.api.client.json.gson.GsonFactory;
    import com.google.api.services.chat.v1.HangoutsChat;
    import com.google.api.services.chat.v1.model.Message;
    import com.google.auth.http.HttpCredentialsAdapter;
    import com.google.auth.oauth2.GoogleCredentials;
    
    /**
     * Authenticates with Chat API via service account credentials,
     * then creates a Chat message.
     */
    public class App {
        // Specify required scopes.
        private static final String CHAT_SCOPE = "https://www.googleapis.com/auth/chat.bot";
    
        // Specify service account details.
        private static final String PRIVATE_KEY_RESOURCE_URI = "/credentials.json";
    
        public static void main( String[] args ) {
            try {
                // Run app.
                Message response = App.createChatMessage();
                // Print details about the created message.
                System.out.println(response);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        private static Message createChatMessage() throws Exception {
            // Build the Chat API client and authenticate with the service account.
            GoogleCredentials credentials = GoogleCredentials.fromStream(
                App.class.getResourceAsStream(PRIVATE_KEY_RESOURCE_URI))
                .createScoped(CHAT_SCOPE);
            HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credentials);
            HangoutsChat chatService = new HangoutsChat.Builder(
                GoogleNetHttpTransport.newTrustedTransport(),
                GsonFactory.getDefaultInstance(),
                requestInitializer)
                .setApplicationName("auth-sample-app")
                .build();
    
            // The space to create the message in.
            //
            // Replace SPACE_NAME with a space name.
            // Obtain the space name from the spaces resource of Chat API,
            // or from a space's URL.
            String spaceName = "spaces/SPACE_NAME";
    
            // Create a Chat message.
            Message message = new Message().setText("Hello, world!");
            return chatService.spaces().messages().create(spaceName, message).execute();
        }
    }
    
  3. In the code, replace SPACE_NAME with a space name, which you can obtain from the spaces.list method in Chat API, or from a space's URL.

  4. Create a new subdirectory named resources within your project's directory.

  5. Make sure that the private key file for your service account is named credentials.json and copy it to the resources subdirectory.

  6. To configure Maven to include the private key file in the project package, edit the file pom.xml in your project's directory and add the following configuration to the <build> section:

    <build>
      <!-- ... existing configurations ... -->
      <resources>
        <resource>
          <directory>resources</directory>
        </resource>
      </resources>
    </build>
    
  7. To configure Maven to include the dependencies in the project package and to execute your application's main class, edit the file pom.xml in your project's directory and add the following configuration to the <plugins> section:

    <plugins>
      <!-- ... existing configurations ... -->
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <mainClass>com.google.chat.app.authsample.App</mainClass>
            </manifest>
          </archive>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
    

Python

  1. In your working directory, create a file named chat_app_auth.py.
  2. Include the following code in chat_app_auth.py:

    from apiclient.discovery import build
    from google.oauth2 import service_account
    
    # Specify required scopes.
    SCOPES = ['https://www.googleapis.com/auth/chat.bot']
    
    # Specify service account details.
    CREDENTIALS = service_account.Credentials.from_service_account_file(
        'credentials.json', scopes=SCOPES)
    
    # Build the URI and authenticate with the service account.
    chat = build('chat', 'v1', credentials=CREDENTIALS)
    
    # Create a Chat message.
    result = chat.spaces().messages().create(
    
        # The space to create the message in.
        #
        # Replace SPACE_NAME with a space name.
        # Obtain the space name from the spaces resource of Chat API,
        # or from a space's URL.
        parent='spaces/SPACE_NAME',
    
        # The message to create.
        body={'text': 'Hello, world!'}
    
    ).execute()
    
    # Prints details about the created message.
    print(result)
    
  3. In the code, replace SPACE_NAME with a space name, which you can obtain from the spaces.list method in Chat API, or from a space's URL. Make sure that the private key file for your service account is named credentials.json.

Node.js

  1. In your project's directory, create a file named chat_app_auth.js.
  2. Include the following code in chat_app_auth.js:

    const chat = require('@googleapis/chat');
    
    async function createMessage() {
      const auth = new chat.auth.GoogleAuth({
    
        // Specify service account details.
        keyFilename: 'credentials.json',
    
        // Specify required scopes.
        scopes: ['https://www.googleapis.com/auth/chat.bot']
    
      });
      const authClient = await auth.getClient();
    
      // Create the Chat API client and authenticate with the service account.
      const chatClient = await chat.chat({
        version: 'v1',
        auth: authClient
      });
    
      // Create a Chat message.
      const result = await chatClient.spaces.messages.create({
    
        // The space to create the message in.
        //
        // Replace SPACE_NAME with a space name.
        // Obtain the space name from the spaces resource of Chat API,
        // or from a space's URL.
        parent: 'spaces/SPACE_NAME',
    
        // The message to create.
        requestBody: { 'text': 'Hello, world!' }
    
      });
      return result;
    }
    
    // Execute function then print details about the created message.
    createMessage().then(console.log);
    
  3. In the code, replace SPACE_NAME with a space name, which you can obtain from the spaces.list method in Chat API, or from a space's URL. Make sure that the private key file for your service account is named credentials.json.

Apps Script

  1. In the Apps Script editor, edit the file appsscript.json and add the OAuth scope necessary to make external requests to obtain the service account OAuth token:

      "oauthScopes": [
        "https://www.googleapis.com/auth/script.external_request"
      ]
    
  2. Save the following code in a file named ChatAppAuth.gs in your Apps Script project:

    // Specify the contents of the file credentials.json.
    const CREDENTIALS = CREDENTIALS;
    
    const SCOPE = 'https://www.googleapis.com/auth/chat.bot';
    
    // The space to create the message in.
    //
    // Replace SPACE_NAME with a space name.
    // Obtain the space name from the spaces resource of Chat API,
    // or from a space's URL.
    const PARENT = 'spaces/SPACE_NAME'
    
    /**
     * Authenticates with Chat API via app credentials, then posts a message.
     */
    function createMessageWithAppCredentials() {
      try {
        const service = getService_();
        if (!service.hasAccess()) {
          console.error(service.getLastError());
          return;
        }
    
        // Specify the message to create.
        const message = {'text': 'Hello world!'};
    
        // Call Chat API with a service account to create a message.
        const result = Chat.Spaces.Messages.create(
            message,
            PARENT,
            {},
            // Authenticate with the service account token.
            {'Authorization': 'Bearer ' + service.getAccessToken()});
    
        // Log details about the created message.
        console.log(result);
    
      } catch (err) {
        // TODO (developer) - Handle exception.
        console.log('Failed to create message with error %s', err.message);
      }
    }
    
    /**
     * Configures the OAuth library to authenticate with the service account.
     */
    function getService_() {
      return OAuth2.createService(CREDENTIALS.client_email)
          .setTokenUrl('https://oauth2.googleapis.com/token')
          .setPrivateKey(CREDENTIALS.private_key)
          .setIssuer(CREDENTIALS.client_email)
          .setSubject(CREDENTIALS.client_email)
          .setScope(SCOPE)
          .setPropertyStore(PropertiesService.getScriptProperties());
    }
    
  3. In the code, replace CREDENTIALS with the contents of the file credentials.json.

  4. In the code, replace SPACE_NAME with a space name, which you can obtain from the spaces.list method in Chat API, or from a space's URL.

Step 4: Run the complete example

In your working directory, build and run the sample:

Java

mvn compile assembly:single
java -jar target/auth-sample-app-1.0-SNAPSHOT-jar-with-dependencies.jar

Python

python3 chat_app_auth.py

Node.js

node chat_app_auth.js

Apps Script

Open the file ChatAppAuth.gs in the Apps Script Editor and click Run.

Your script makes an authenticated request to the Chat API, which responds by posting a message in a Chat space as a Chat app.

Troubleshoot the example

This section describes common issues that you might encounter while attempting to run this sample.

You are not permitted to use this app

When running the script, you might receive an error that says:

<HttpError 403 when requesting https://chat.googleapis.com/v1/spaces/{space}/messages?alt=json returned "You are not permitted to use this app". Details: "You are not permitted to use this app">

This error message means that the Chat app doesn't have permission to create Chat messages in the specified Chat space.

To resolve the error, add the Chat app to the Chat space specified in the script.

Learn what else Chat API can do by reviewing the Chat API reference documentation.