I want to create a Google Chat bot to retrieve historical messages within a space

I’ve deployed my program on Cloud Run, and after execution, I encounter the following error message:

403 Request had insufficient authentication scopes. Ensure the scopes you are using support app authentication with a service account. [links { description: “See article Authenticate as a Chat app.” url: " Authenticate as a Google Chat app | Google for Developers " } ]

Here’s my code:

import functions_framework
import logging
from google.apps import chat_v1 as google_chat
from google.apps.chat_v1 import ListMessagesRequest
from google.auth import default
from google.api_core import exceptions as gcp_exceptions
from google.protobuf.json_format import MessageToJson
import json

SCOPES = ['https://www.googleapis.com/auth/chat.messages']

def create_chat_client():
    try:
        credentials, project = default(scopes=SCOPES)
        client = google_chat.ChatServiceClient(credentials=credentials)
        return client
    except Exception as e:
        logging.error(f"Error creating chat client: {e}")
        return None

@functions_framework.http
def list_space_messages(request):
    client = create_chat_client()
    if not client:
        return {"error": "Failed to initialize Chat API client."}, 500

    event_data = request.get_json(silent=True)
    if not event_data:
        return {"error": "Request body must be a JSON."}, 400

    space_name = event_data.get("space_name")
    if not space_name or not space_name.startswith("spaces/"):
        return {"error": "Missing or invalid 'space_name'."}, 400

    logging.info(f"Listing messages for Space: {space_name}")

    try:
        list_messages_request = ListMessagesRequest(
            parent=space_name,
            page_size=10
        )

        messages_response = client.list_messages(request=list_messages_request)

        messages_list = []

        # ...

        return {
            "space_name": space_name,
            "message_count": len(messages_list),
            "messages": messages_list
        }, 200
    except gcp_exceptions.PermissionDenied as e:
        logging.error(f"Permission denied: {e}")
        return {"error": "Permission Denied."}, 403
    except gcp_exceptions.NotFound as e:
        logging.error(f"Space not found: {e}")
        return {"error": "Space not found."}, 404
    except Exception as e:
        logging.error(f"Unexpected error: {e}")
        return {"error": str(e)}, 500

I’ve researched and found that Domain-Wide Delegation seems to be required. Even after configuring it in Workspace, I still can’t get it to work successfully.

I also found that many solutions use the Service Account JSON approach, but due to permission restrictions, I can only use the Application Default Credentials method.

How can I resolve this issue? Thank you all.

Hey,

Hope you’re keeping well.

The 403 here means the credentials Cloud Run is using don’t have the correct Chat API scopes or aren’t authorized for the specific space. For historical message retrieval with a service account, you need to enable Domain-Wide Delegation in Workspace Admin, grant the service account the chat.messages scope, and impersonate a user who is a member of that space. With Application Default Credentials in Cloud Run, you can still do this by using google.auth.default() with subject=<user_email> on a delegated google.oauth2.service_account.Credentials object. Also make sure the Chat API is enabled in the project and the service account has the necessary Workspace API access configured in Admin Console > Security > API Controls > Manage Domain Wide Delegation. Without impersonation of a space member, the Chat API will not return historical messages even if the scope is correct.

Thanks and regards,
Taz