ユーザー認証を使用する Chat アプリは、ユーザーがリクエストされたスコープのサブセットを付与できるように、 きめ細かい OAuth 権限 をサポートする必要があります。たとえば、ユーザーは自分の名前へのアクセスを許可する一方で、カレンダーへのアクセスを拒否できます。
きめ細かい OAuth 権限の処理は、Chat アプリの構築方法によって異なります。
- Chat を拡張する Apps Script Google Workspace アドオン
- スタンドアロンの Apps Script Chat アプリ
- Chat を拡張する HTTP Google Workspace アドオン
- スタンドアロンの HTTP Chat アプリ
Apps Script
Apps Script を使用して Chat アプリを構築する場合、 Apps Script がきめ細かい OAuth 権限を自動的に処理します。 ただし、ユーザーがリクエストされたスコープをすべて付与しない場合を処理するようにコードを記述してください。この方法は、Apps Script が Apps Script を使用して Google Chat を拡張する Google Workspace アドオンであるか、Apps Script とインタラクション イベントで構築されたスタンドアロンの Chat アプリであるかによって異なります。
Chat を拡張する Google Workspace アドオン
Apps Script を使用して Google Chat を拡張する Google Workspace アドオンとして Chat アプリを構築する場合は、 Apps Script できめ細かい OAuth 権限を処理するの手順に沿って操作してください。
スタンドアロンの Apps Script Chat アプリ
Apps Script とインタラクション イベントを使用して Chat アプリを構築する場合は、 Apps Script できめ細かい OAuth 権限を処理する の手順に沿って操作してください。ただし、次の点に注意してください。
ScriptApp.requireScopes
は、指定されたスコープが付与されていない場合、スクリプトの実行を停止しますが、OAuth
同意画面ではなく、Chat に構成カードが表示されます。構成カードでは、付与されていないスコープだけでなく、リクエストされたすべてのスコープを付与するようにユーザーに求められます。
個々の承認スコープ レベルのチェックを行うには、
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.
// ...
}
HTTP エンドポイント
HTTP エンドポイントを使用して Chat アプリを構築する場合、 Chat アプリはきめ細かい OAuth 権限をサポートする必要があります。
Chat を拡張する Google Workspace アドオン
Google Workspace アドオンとして Chat アプリを構築する場合は、きめ細かい OAuth 権限を処理するようにコードを構成します。ユーザーが付与した承認スコープを確認し、必要に応じて、不足しているスコープまたはすべてのスコープの承認をリクエストします。
アドオンの マニフェスト ファイルで、必要な承認スコープを
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(); }アドオンに関連付けられているすべてのスコープをリクエストするには、
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();
詳細な手順については、 HTTP Google Workspace アドオンのきめ細かい権限を管理するをご覧ください。
スタンドアロンの HTTP Chat アプリ
Chat アプリがスタンドアロンの HTTP サービス(Google Workspace アドオンではない)の場合は、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();
詳細については、 きめ細かい OAuth 権限をご覧ください。
関連トピック
- Google Chat での認証と承認の概要については、 認証と承認について をご覧ください。
- ユーザー認証を設定するには、 Google Chat ユーザーとして認証して承認するをご覧ください。
- Apps Script または HTTP Google Workspace アドオンで、きめ細かい OAuth 権限を設定する方法については、以下をご覧ください。
- きめ細かい OAuth 権限について詳しくは、 きめ細かい OAuth 権限をご覧ください。