本指南介绍了如何将 OAuth 2.0 与用户的 Google 凭据搭配使用,以访问 Chat API。使用用户凭据进行身份验证和授权后,Chat 应用便可访问用户数据,并代表已通过身份验证的用户执行操作。通过代表用户进行身份验证,应用可获得与该用户相同的权限,并且可以执行的操作就如同由该用户执行一样。
使用用户凭据对 API 调用进行身份验证和授权后,Chat 应用可以执行以下操作:
- 创建 Chat 聊天室。
- 向 Chat 聊天室和群组对话添加用户。
- 在其他 Workspace API(例如以下 API)中处理用户数据:
当应用在用户身份验证的情况下执行操作(例如创建聊天室)时,Google Chat 会显示一条归因消息,告知用户为其授权执行操作的应用的名称。
如需详细了解 Chat 应用何时需要身份验证以及应使用哪种身份验证,请参阅 Chat API 身份验证和授权概览中的所需身份验证类型。
以 Google Workspace 管理员身份进行身份验证和授权
本部分介绍了 Google Workspace 工作区管理员如何通过用户身份验证来管理贵组织中的 Google Chat 应用和聊天室。
使用全网域授权进行身份验证和授权
如果您是网域管理员,则可以授予全网域授权,以便授权应用的服务账号访问您用户的数据,而无需经过每位用户的同意。配置全网域委托后,服务账号可以模拟用户账号。虽然服务账号用于身份验证,但全网域授权会模拟用户,因此被视为用户身份验证。对于需要用户身份验证的任何功能,您都可以使用域级委托。
使用管理员权限进行身份验证和授权
如果您是网域管理员或具有管理员权限的委托管理员,则可以通过在适用方法的请求中设置 useAdminAccess
字段,以管理员权限对 Google Chat API 进行身份验证和授权。如需了解详情,请参阅 API 参考文档。
请注意,当 Google Chat 应用使用管理员权限执行操作时,Chat 不会告知用户执行操作的 Chat 应用的名称或授权该操作的管理员的名称,只会告知用户该操作是由其组织的管理员执行的。
前提条件
Java
- 拥有对 Google Chat 访问权限的商务版或企业版 Google Workspace 账号。
- 创建 Google Cloud 项目。
- 启用和配置 Google Chat API,为 Chat 应用提供名称、图标和说明。
- JDK 1.7 或更高版本
- Maven 软件包管理工具
-
已初始化的 Maven 项目。如需初始化新项目,请在命令行界面中运行以下命令:
mvn archetype:generate -DgroupId=com.google.chat.app.authsample -DartifactId=auth-sample-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
Python
- 拥有对 Google Chat 访问权限的商务版或企业版 Google Workspace 账号。
- 创建 Google Cloud 项目。
- 启用和配置 Google Chat API,为 Chat 应用提供名称、图标和说明。
- Python 3.6 或更高版本
- pip 软件包管理工具
Node.js
- 拥有对 Google Chat 访问权限的商务版或企业版 Google Workspace 账号。
- 创建 Google Cloud 项目。
- 启用和配置 Google Chat API,为 Chat 应用提供名称、图标和说明。
- Node.js 14 或更高版本
- npm 软件包管理工具
-
初始化的 Node.js 项目。如需初始化新项目,请创建并切换到新文件夹,然后在命令行界面中运行以下命令:
npm init
Apps 脚本
- 拥有对 Google Chat 访问权限的商务版或企业版 Google Workspace 账号。
- 创建 Google Cloud 项目。
- 启用和配置 Google Chat API,为 Chat 应用提供名称、图标和说明。
- 创建一个独立的 Apps 脚本项目,然后开启高级聊天服务。
第 1 步:配置 OAuth 同意屏幕、指定范围并注册应用
当您使用 OAuth 2.0 进行授权时,Google 会向用户显示权限请求页面,其中包括项目摘要信息及其政策和请求的授权范围。配置应用的 OAuth 权限请求页面可定义 Google 向用户和应用审核者显示的内容,还可注册应用以便以后发布。
使用 OAuth 2.0 的所有应用都需要配置意见征求界面,但您只需为 Google Workspace 组织外部人员使用的应用列出相应范围。
在 Google Cloud 控制台中,依次选择“菜单”图标 > API 和服务 > OAuth 同意屏幕。
为您的应用选择用户类型,然后点击创建。
填写应用注册表单,然后点击保存并继续。
点击添加或移除范围。添加并验证应用所需的授权范围,点击更新,然后点击保存并继续。
查看应用注册摘要。点击修改进行更改,或点击返回信息中心。
第 2 步:在 Google Cloud 控制台中创建 OAuth 客户端 ID 凭据
如需以最终用户身份进行身份验证并访问应用中的用户数据,您需要创建一个或多个 OAuth 2.0 客户端 ID。客户端 ID 用于向 Google 的 OAuth 服务器标识单个应用。如果您的应用在多个平台(例如 Android、iOS 和 Web)上运行,则需要为每个平台创建单独的客户端 ID。
创建 OAuth 客户端 ID 凭据
选择您的应用类型,查看有关如何创建 OAuth 客户端 ID 的具体说明:
Web 应用
- 在 Google Cloud 控制台中,依次选择“菜单”图标 > API 和服务 > 凭据。
- 依次点击创建凭据 > OAuth 客户端 ID。
- 依次点击应用类型 > Web 应用。
- 在名称字段中,输入凭据的名称。此名称仅在 Google Cloud 控制台中显示。
- 添加与您的应用相关的已获授权 URI:
- 客户端应用 (JavaScript) - 在已获授权的 JavaScript 来源下,点击添加 URI。然后,输入要用于浏览器请求的 URI。这用于标识您的应用可以从哪些网域向 OAuth 2.0 服务器发送 API 请求。
- 服务器端应用(Java、Python 等) - 在已获授权的重定向 URI 下,点击添加 URI。然后,输入 OAuth 2.0 服务器可以向其发送响应的端点 URI。
- 点击创建。系统随即会显示“OAuth 客户端已创建”屏幕,其中显示您的新客户端 ID 和客户端密钥。
记下客户端 ID。客户端密钥不适用于 Web 应用。
- 点击确定。新创建的凭据会显示在 OAuth 2.0 客户端 ID 下。
Android
- 在 Google Cloud 控制台中,依次选择“菜单”图标 > API 和服务 > 凭据。
- 依次点击创建凭据 > OAuth 客户端 ID。
- 依次点击应用类型 > Android。
- 在“名称”字段中,输入凭据的名称。此名称仅在 Google Cloud 控制台中显示。
- 在“软件包名称”字段中,输入
AndroidManifest.xml
文件中的软件包名称。 - 在“SHA-1 证书指纹”字段中,输入您生成的 SHA-1 证书指纹。
- 点击创建。系统随即会显示“OAuth 客户端已创建”屏幕,其中显示您的新客户端 ID。
- 点击确定。新创建的凭据会显示在“OAuth 2.0 客户端 ID”下。
iOS
- 在 Google Cloud 控制台中,依次选择“菜单”图标 > API 和服务 > 凭据。
- 依次点击创建凭据 > OAuth 客户端 ID。
- 依次点击应用类型 > iOS。
- 在“名称”字段中,输入凭据的名称。此名称仅在 Google Cloud 控制台中显示。
- 在“Bundle ID”字段中,输入应用的
Info.plist
文件中列出的软件包标识符。 - 可选:如果您的应用在 Apple App Store 中展示,请输入 App Store ID。
- 可选:在“团队 ID”字段中,输入由 Apple 生成并分配给您的团队的唯一字符串(包含 10 个字符)。
- 点击创建。系统随即会显示“OAuth 客户端已创建”屏幕,其中显示您的新客户端 ID 和客户端密钥。
- 点击确定。新创建的凭据会显示在“OAuth 2.0 客户端 ID”下。
Chrome 应用
- 在 Google Cloud 控制台中,依次选择“菜单”图标 > API 和服务 > 凭据。
- 依次点击创建凭据 > OAuth 客户端 ID。
- 依次点击应用类型 > Chrome 应用。
- 在“名称”字段中,输入凭据的名称。此名称仅在 Google Cloud 控制台中显示。
- 在“应用 ID”字段中,输入应用的 32 个字符的唯一 ID 字符串。您可以在应用的 Chrome 应用商店网址和 Chrome 应用商店开发者信息中心中找到此 ID 值。
- 点击创建。系统随即会显示“OAuth 客户端已创建”屏幕,其中显示您的新客户端 ID 和客户端密钥。
- 点击确定。新创建的凭据会显示在“OAuth 2.0 客户端 ID”下。
桌面应用
- 在 Google Cloud 控制台中,依次选择“菜单”图标 > API 和服务 > 凭据。
- 依次点击创建凭据 > OAuth 客户端 ID。
- 依次点击应用类型 > 桌面应用。
- 在名称字段中,输入凭据的名称。此名称仅在 Google Cloud 控制台中显示。
- 点击创建。系统随即会显示“OAuth 客户端已创建”屏幕,其中显示您的新客户端 ID 和客户端密钥。
- 点击确定。新创建的凭据会显示在 OAuth 2.0 客户端 ID 下。
电视和受限输入设备
- 在 Google Cloud 控制台中,依次选择“菜单”图标 > API 和服务 > 凭据。
- 依次点击创建凭据 > OAuth 客户端 ID。
- 依次点击应用类型 > 电视和输入受限设备。
- 在“名称”字段中,输入凭据的名称。此名称仅在 Google Cloud 控制台中显示。
- 点击创建。系统随即会显示“OAuth 客户端已创建”屏幕,其中显示您的新客户端 ID 和客户端密钥。
- 点击确定。新创建的凭据会显示在“OAuth 2.0 客户端 ID”下。
通用 Windows 平台 (UWP)
- 在 Google Cloud 控制台中,依次选择“菜单”图标 > API 和服务 > 凭据。
- 依次点击创建凭据 > OAuth 客户端 ID。
- 依次点击应用类型 > 通用 Windows 平台 (UWP)。
- 在“名称”字段中,输入凭据的名称。此名称仅在 Google Cloud 控制台中显示。
- 在“商店 ID”字段中,输入应用的唯一 12 位字符 Microsoft 商店 ID 值。您可以在应用的 Microsoft Store 网址和 Partner Center 中找到此 ID。
- 点击创建。系统随即会显示“OAuth 客户端已创建”屏幕,其中显示您的新客户端 ID 和客户端密钥。
- 点击确定。新创建的凭据会显示在“OAuth 2.0 客户端 ID”下。
下载客户端密钥 JSON 文件
客户端密钥文件是 OAuth 客户端 ID 凭据的 JSON 表示法,聊天应用在提供凭据时可以引用该凭据。
在 Google Cloud 控制台中,依次选择“菜单”图标 > API 和服务 > 凭据。
在 OAuth 2.0 客户端 ID 下,点击您创建的客户端 ID。
点击下载 JSON。
将该文件另存为
client_secrets.json
。
第 3 步:安装 Google 客户端库和其他依赖项
安装 Google 客户端库以及项目所需的其他依赖项。
Java
如需将 Google 客户端库和其他所需依赖项添加到 Maven 项目,请修改项目目录中的 pom.xml
文件,然后添加以下依赖项:
<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.oauth-client</groupId>
<artifactId>google-oauth-client-jetty</artifactId>
<version>1.34.1</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
</dependencies>
Python
如果您尚未安装 Python 版 Google 客户端库,请在命令行界面中运行以下命令:
pip3 install --upgrade google-api-python-client google-auth-oauthlib
Node.js
如需将 Google 客户端库和其他所需依赖项添加到 Node.js 项目中,请切换到项目的目录,然后在命令行界面中运行以下命令:
npm install "@googleapis/chat" open server-destroy
Apps 脚本
此示例使用高级聊天服务调用 Google Chat API。如需为您的 Apps Script 项目开启该服务,请执行以下操作:
- 点击左侧的编辑器图标 。
- 在左侧的服务旁边,点击添加服务 。
- 选择 Google Chat API。
- 在版本中,选择 v1。
- 点击添加。
您可以使用我们的客户端库支持的任何语言。
第 4 步:编写用于调用 Chat API 的脚本
使用 OAuth 授权调用 API 是一个多步流程。在 Web 或桌面应用中,该过程通常如下所示:
- 应用会将用户定向到授权页面,请求访问授权范围指定的用户数据。应用使用客户端 ID 凭据标识自己。
- 用户查看应用请求的权限,并批准该请求。
- Google 的身份验证服务器会将浏览器重定向到应用的 HTTP 端点,并附上授权代码。
- 应用会向 Google 的授权服务器发送另一个请求,以便使用授权代码换取访问令牌。
- 应用使用访问令牌代表用户调用 API。
如需详细了解 OAuth 授权流程,请参阅“使用 OAuth 2.0 访问 Google API”指南。
Java、Python 和 Node.js 中的以下代码示例使用客户端库执行 OAuth 授权流程。它会打开一个本地 HTTP 服务器,以接收授权服务器发回的授权代码,然后将其交换为访问令牌。在 Apps 脚本代码示例中,此授权流程由 Apps 脚本处理。
完成身份验证流程后,脚本会使用用户的访问令牌通过 Chat API 进行身份验证,然后创建聊天室。
Java
- 在项目目录中,打开
src/main/java/com/google/chat/app/authsample/App.java
文件。 将
App.java
中的内容替换为以下代码:package com.google.chat.app.authsample; import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp; import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver; import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow; import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets; import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; import com.google.api.client.http.HttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.client.json.gson.GsonFactory; import com.google.api.client.util.store.FileDataStoreFactory; import com.google.api.services.chat.v1.HangoutsChat; import com.google.api.services.chat.v1.model.Space; import java.io.InputStreamReader; import java.util.Collection; import java.util.Collections; /** * Authenticates with Chat API via user credentials, then creates a Chat space. */ public class App { // Application OAuth credentials. private static final String KEYS_RESOURCE_URI = "/client_secrets.json"; // Define your app's authorization scopes. private static final Collection<String> SCOPES = Collections.singleton("https://www.googleapis.com/auth/chat.spaces.create"); // Directory to store user credentials. private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"), ".store/auth-sample-app"); // Global instance of the JSON factory. private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance(); // Global instance of the HTTP transport. private static HttpTransport httpTransport; // Global instance of the DataStoreFactory. The best practice is to make it a single // globally shared instance across your application. private static FileDataStoreFactory dataStoreFactory; public static void main( String[] args ) { try { // Run app. httpTransport = GoogleNetHttpTransport.newTrustedTransport(); dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR); Credential userCredential = authorize(); Space response = App.createChatSpace(userCredential); // Print details about the created space. System.out.println(response); } catch (Exception e) { e.printStackTrace(); } } /** * Authorizes the installed application to access user's protected data. */ private static Credential authorize() throws Exception { // Load client secrets. GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(App.class.getResourceAsStream("/client_secrets.json"))); // Set up authorization code flow. GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder( httpTransport, JSON_FACTORY, clientSecrets, SCOPES) .setDataStoreFactory(dataStoreFactory) .build(); // Authorize. return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user"); } /** * Creates a Chat space. */ private static Space createChatSpace(Credential userCredential) throws Exception { // Build the Chat API client and authenticate with the user account. HangoutsChat chatService = new HangoutsChat.Builder( httpTransport, JSON_FACTORY, userCredential) .setApplicationName("auth-sample-app") .build(); // Create a Chat space. Space space = new Space() // To create a named space, set spaceType to SPACE. .setSpaceType("SPACE") // The user-visible name of the space. .setDisplayName("API-made"); return chatService.spaces().create(space).execute(); } }
在项目目录中创建一个名为
resources
的新子目录。将
client_secrets.json
文件复制到resources
子目录。如需配置 Maven 以在项目软件包中添加客户端密钥文件,请修改项目目录中的
pom.xml
文件,并将以下配置添加到<build>
部分:<build> <!-- ... existing configurations ... --> <resources> <resource> <directory>resources</directory> </resource> </resources> </build>
如需配置 Maven 以将依赖项添加到项目软件包中并执行应用的主类,请修改项目目录中的
pom.xml
文件,并将以下配置添加到<plugins>
部分:<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
将以下代码保存在包含
client_secrets.json
的同一目录中名为chat_space_create_named.py
的文件中:from google_auth_oauthlib.flow import InstalledAppFlow from googleapiclient.discovery import build # Define your app's authorization scopes. # When modifying these scopes, delete the file token.json, if it exists. SCOPES = ["https://www.googleapis.com/auth/chat.spaces.create"] def main(): ''' Authenticates with Chat API via user credentials, then creates a Chat space. ''' flow = InstalledAppFlow.from_client_secrets_file( 'client_secrets.json', SCOPES) creds = flow.run_local_server() # Build a service endpoint for Chat API. service = build('chat', 'v1', credentials=creds) # Use the service endpoint to call Chat API. result = service.spaces().create( # Details about the space to create. body = { # To create a named space, set spaceType to SPACE. 'spaceType': 'SPACE', # The user-visible name of the space. 'displayName': 'API-made' } ).execute() # Prints details about the created space. print(result) if __name__ == '__main__': main()
Node.js
将以下代码保存在包含 Node.js 项目和
client_secrets.json
的目录中名为chat_space_create_named.js
的文件中:const fs = require('fs'); const path = require('path'); const http = require('http'); const url = require('url'); const destroyer = require('server-destroy'); const chat = require('@googleapis/chat'); // Application OAuth credentials. const keys = require('./client_secrets.json').installed; // Define your app's authorization scopes. // When modifying these scopes, delete the file token.json, if it exists. const scopes = ["https://www.googleapis.com/auth/chat.spaces.create"]; // Create a new OAuth2 client with the configured keys. const oauth2Client = new chat.auth.OAuth2( keys.client_id, keys.client_secret, 'http://localhost:3000' ); /** * Opens an HTTP server to accept the OAuth callback. * In this simple example, the only request to our webserver is to /?code=<code>. */ async function authenticate(scopes) { const opn = (await import('open')).default; return new Promise((resolve, reject) => { // Generate the URL for authorization. const authorizeUrl = oauth2Client.generateAuthUrl({ access_type: 'offline', scope: scopes.join(' '), }); // Start the HTTP server to listen for the callback. const server = http .createServer(async (req, res) => { try { const qs = new url.URL(req.url, 'http://localhost:3000').searchParams; res.end('Authentication successful! Please return to the console.'); server.destroy(); const { tokens } = await oauth2Client.getToken(qs.get('code')); oauth2Client.credentials = tokens; resolve(oauth2Client); } catch (e) { reject(e); } }) .listen(3000, () => { // Open the browser to the authorize URL to start the workflow. opn(authorizeUrl, { wait: false }).then(cp => cp.unref()); }); destroyer(server); }); } /** * Authenticates with Chat API via user credentials, then creates a Chat space. */ async function createSpace() { // Create the Chat API client and authenticate with the authorized user. const chatClient = await chat.chat({ version: 'v1', auth: oauth2Client }); // Call the Chat API to create a space. const result = await chatClient.spaces.create({ // Details about the space to create. requestBody: { // To create a named space, set spaceType to SPACE. 'spaceType': 'SPACE', // The user-visible name of the space. 'displayName': 'API-made' } }); return result; } // Authenticate the user, execute the function, // then print details about the created space. authenticate(scopes) .then(createSpace) .then(console.log);
Apps 脚本
在 Apps 脚本编辑器中,修改
appsscript.json
文件,并添加调用该 API 所需的 OAuth 范围:"oauthScopes": [ "https://www.googleapis.com/auth/chat.spaces.create" ]
将以下代码保存在 Apps Script 项目中名为
ChatSpaceCreateNamed.gs
的文件中:/** * Authenticates with Chat API via user credentials, then creates a * Chat space. */ function createSpace() { try { // Details about the space to create. // To create a named space, set spaceType to SPACE. // The user-visible name of the space is displayName. const space = {'displayName': 'API-made', 'spaceType': 'SPACE'}; // Call Chat API with user credentials to create the space. const result = Chat.Spaces.create(space); // Log details about the created space. console.log(result); } catch (err) { // TODO (developer) - Handle exception console.log('Failed to create space with error %s', err.message); } }
第 5 步:运行示例脚本
如需运行该示例,请在命令行中前往存储项目文件的目录,然后执行以下命令:
Java
mvn compile assembly:single
java -jar target/auth-sample-app-1.0-SNAPSHOT-jar-with-dependencies.jar
Python
python3 chat_space_create_named.py
Node.js
node chat_space_create_named.js
Apps 脚本
在 Apps 脚本编辑器中打开文件 ChatSpaceCreateNamed.gs
,然后点击运行。
系统会打开一个浏览器,并提示您登录 Google 账号:
登录后,系统会显示 OAuth 权限请求页面,要求您向应用授予权限。
您授予权限后,该脚本会调用 Chat API,后者会通过创建显示名称为 API-made
的 Chat 聊天室来响应。控制台会输出 API 调用的详细信息。如需查找聊天室,请前往 Google Chat 中的聊天室面板。
对示例进行问题排查
运行 chat_space_create_named.py
时,您可能会收到以下错误消息:
Expected a JSON object with a single property for a "web" or "installed" application
此错误消息表示您从 Google Cloud 控制台下载的 client_secrets.json
文件不以 "web"
或 "installed"
属性开头。使用下载的文件进行身份验证后,如果您的代码未将访问令牌保存在新文件(例如 token.json
)中,则系统会将访问令牌写入 client_secrets.json
,这可能会在后续尝试授权时导致此错误。
如需解决此错误,请再次从 Google Cloud 控制台中下载客户端密钥文件,并将新文件保存在当前文件的位置。
相关主题
如果您的应用需要在单个流程范围之外继续使用用户令牌,则可以存储这些令牌以供日后重复使用。在这种情况下,您的应用需要安全地处理用户令牌,并处理刷新令牌的撤消和过期。如需了解详情,请参阅 “使用 OAuth 2.0”最佳实践指南。
如需了解 Chat API 的其他用途,请参阅 Chat API 参考文档。