Приложения для Chat, использующие аутентификацию пользователей, должны поддерживать детализированные разрешения OAuth, чтобы пользователи могли предоставлять только часть запрошенных областей действия. Например, пользователь может разрешить доступ к своему имени, но запретить доступ к календарю.
Обработка детализированных разрешений OAuth зависит от того, как вы создаете приложение Chat:
Apps Script
Если вы создаете приложение для Chat с помощью Apps Script, то Apps Script автоматически обрабатывает детализированные разрешения OAuth. Однако убедитесь, что ваш код обрабатывает случаи, когда пользователь не предоставляет все запрошенные области действия. Следуйте инструкциям в статье Как работать с детализированными разрешениями OAuth в Apps Script.
Конечные точки HTTP
Если вы создаете приложение Chat с помощью конечных точек HTTP, настройте код так, чтобы он обрабатывал детализированные разрешения OAuth. Проверьте, какие области действия авторизации предоставил пользователь, и при необходимости запросите авторизацию для недостающих областей действия или всех областей действия.
В файле манифеста приложения Chat укажите необходимые области авторизации в поле
oauthScopes. Это поле является частью ресурсаprojects.deployments.В примере ниже требуются области авторизации
chat.messagesиcalendar.events:JSON
{ "oauthScopes": [ "https://www.googleapis.com/auth/chat.messages", "https://www.googleapis.com/auth/calendar.events" ], "addOns": { "common": { "name": "My Chat App", "logoUrl": "https://lh3.googleusercontent.com/..." }, "chat": {}, "calendar": {}, "httpOptions": {} } }Чтобы узнать, какие области действия разрешил пользователь, проверьте поле
authorizationEventObject.authorizedScopes. Если обязательная область отсутствует, верните действиеrequesting_google_scopes, чтобы запросить у пользователя недостающие области.Node.js
// Check for authorized scopes. const authorizedScopes = req.body.authorizationEventObject?.authorizedScopes || []; if (!authorizedScopes.includes('https://www.googleapis.com/auth/chat.messages')) { // Respond with a request for the missing scope. res.send({ 'requesting_google_scopes': { 'scopes': ['https://www.googleapis.com/auth/chat.messages'] } }); return; }Python
from flask import jsonify, request # Check for authorized scopes. event_data = request.get_json() authorized_scopes = event_data.get('authorizationEventObject', {}).get('authorizedScopes', []) if 'https://www.googleapis.com/auth/chat.messages' not in authorized_scopes: # Respond with a request for the missing scope. return jsonify({ 'requesting_google_scopes': { 'scopes': ['https://www.googleapis.com/auth/chat.messages'] } })Java
import com.google.gson.JsonArray; import com.google.gson.JsonObject; import java.util.List; // Check for authorized scopes. List<String> authorizedScopes = event.getAuthorizationEventObject() != null ? event.getAuthorizationEventObject().getAuthorizedScopes() : null; if (authorizedScopes == null || !authorizedScopes.contains("https://www.googleapis.com/auth/chat.messages")) { // Respond with a request for the missing scope. JsonObject requestingGoogleScopes = new JsonObject(); JsonArray scopes = new JsonArray(); scopes.add("https://www.googleapis.com/auth/chat.messages"); requestingGoogleScopes.add("scopes", scopes); JsonObject response = new JsonObject(); response.add("requesting_google_scopes", requestingGoogleScopes); return response.toString(); }Чтобы запросить все области действия, связанные с приложением Chat, задайте для параметра
all_scopesзначениеtrue:Node.js
res.send({ 'requesting_google_scopes': { 'all_scopes': true } });Python
from flask import jsonify return jsonify({ 'requesting_google_scopes': { 'all_scopes': True } })Java
import com.google.gson.JsonObject; JsonObject requestingGoogleScopes = new JsonObject(); requestingGoogleScopes.addProperty("all_scopes", true); JsonObject response = new JsonObject(); response.add("requesting_google_scopes", requestingGoogleScopes); return response.toString();
Подробнее о том, как управлять детализированными разрешениями для дополнений Google Workspace, использующих конечные точки HTTP…
Статьи по теме
- Общую информацию об аутентификации и авторизации в Google Chat можно найти в статье Аутентификация и авторизация.
- Чтобы настроить аутентификацию пользователей, ознакомьтесь со статьей Как выполнить аутентификацию и авторизацию для пользователей Google Chat.
- Информацию о том, как настроить детализированные разрешения OAuth в Apps Script или для приложений Chat на основе HTTP, можно найти в следующих статьях:
- Подробнее о детализированных разрешениях OAuth…
Приложения для Chat, не являющиеся дополнениями: управление детализированными разрешениями OAuth для приложений Google Chat
Если вы поддерживаете приложение Chat, которое не является дополнением Google Workspace, следуйте приведенным ниже инструкциям, чтобы управлять детализированными разрешениями OAuth.
приложения Chat, созданные с помощью Apps Script и не являющиеся дополнениями;
Если вы создали приложение Chat, которое не является дополнением, с помощью Apps Script, инструкции из статьи Как работать с детализированными разрешениями OAuth в Apps Script будут работать с одним условием:
ScriptApp.requireScopes
останавливает выполнение скрипта, если указанные области не предоставлены, но пользователь видит в Chat карточку конфигурации вместо экрана запроса доступа OAuth. На карточке конфигурации всегда предлагается предоставить все запрошенные области действия, а не только те, которые ещё не были предоставлены.
Чтобы выполнять проверки на уровне отдельных областей авторизации, используйте ScriptApp.getAuthorizationInfo. С помощью этого метода можно проверить наличие авторизации и при необходимости запросить ее, используя личное сообщение.
В следующем примере показано, как проверить наличие определенного разрешения (например, на доступ к календарю) и, если оно отсутствует, вернуть личное сообщение с URL для авторизации.
Apps Script
/**
* Responds to a MESSAGE event in Google Chat.
* Checks for required permissions and if missing asks for them.
*
* @param {Object} event the event object from Chat
* @return {Object} JSON response
*/
function onMessage(event) {
// Check if the script has the necessary permissions.
// In this example, the script checks for the "calendar.events" scope.
var requiredScopes = ['https://www.googleapis.com/auth/calendar.events'];
var authInfo = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL, requiredScopes);
// If permissions are missing, return a message with the authorization URL.
if (authInfo.getAuthorizationStatus() === ScriptApp.AuthorizationStatus.REQUIRED) {
var authUrl = authInfo.getAuthorizationUrl();
return {
"text": "This action requires authorization. Please <" + authUrl + "|click here to authorize>.",
"privateMessageViewer": {
"name": event.user.name
}
};
}
// Permission granted; proceed with the application logic.
// ...
}
Приложения Chat HTTP, которые не являются дополнениями
Если ваше приложение Chat, не являющееся дополнением, представляет собой сервис HTTP, вы сами управляете потоком OAuth 2.0.
При получении сохраненного токена или обмене кода авторизации проверьте, какие области были предоставлены. Если необходимые области отсутствуют, предложите пользователю авторизовать их.
Node.js
// 1. List authorized scopes.
const fs = require('fs');
const tokens = JSON.parse(fs.readFileSync('token.json'));
const grantedScopes = tokens.scope.split(' ');
// 2. Detect missing scopes.
const requiredScopes = ['https://www.googleapis.com/auth/chat.messages'];
const missingScopes = requiredScopes.filter(scope => !grantedScopes.includes(scope));
if (missingScopes.length > 0) {
// 3. Request missing scopes.
const authUrl = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: missingScopes,
include_granted_scopes: true
});
res.redirect(authUrl);
}
// To request all scopes instead of just the missing ones:
const allScopesAuthUrl = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: requiredScopes,
include_granted_scopes: true
});
Python
from flask import redirect
from google.oauth2.credentials import Credentials
# 1. List authorized scopes.
credentials = Credentials.from_authorized_user_file('token.json')
granted_scopes = set(credentials.scopes)
# 2. Detect missing scopes.
required_scopes = {'https://www.googleapis.com/auth/chat.messages'}
missing_scopes = required_scopes - granted_scopes
if missing_scopes:
# 3. Request missing scopes.
flow.scope = list(missing_scopes)
auth_url, _ = flow.authorization_url(
access_type='offline',
include_granted_scopes=True
)
return redirect(auth_url)
# To request all scopes instead of just the missing ones:
flow.scope = list(required_scopes)
all_scopes_auth_url, _ = flow.authorization_url(
access_type='offline',
include_granted_scopes='true'
)
Java
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeRequestUrl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
// 1. List authorized scopes.
// The "user" string is the user ID for which to load credentials.
Credential credential = flow.loadCredential("user");
Collection<String> grantedScopes = credential.getScopes();
// 2. Detect missing scopes.
// The `requiredScopes` variable contains a list of the OAuth scopes
// that your app requires to function. Define this variable with the
// scopes needed by your application.
List<String> requiredScopes = Arrays.asList("https://www.googleapis.com/auth/chat.messages");
List<String> missingScopes = new ArrayList<>();
for (String scope : requiredScopes) {
if (!grantedScopes.contains(scope)) {
missingScopes.add(scope);
}
}
if (!missingScopes.isEmpty()) {
// 3. Request missing scopes.
GoogleAuthorizationCodeRequestUrl urlBuilder = new GoogleAuthorizationCodeRequestUrl(
clientId, redirectUri, missingScopes)
.setAccessType("offline")
.set("include_granted_scopes", "true");
String authUrl = urlBuilder.build();
response.sendRedirect(authUrl);
}
// To request all scopes instead of just the missing ones:
GoogleAuthorizationCodeRequestUrl allScopesUrlBuilder = new GoogleAuthorizationCodeRequestUrl(
clientId, redirectUri, requiredScopes)
.setAccessType("offline")
.set("include_granted_scopes", "true");
String allScopesAuthUrl = allScopesUrlBuilder.build();