
Если ваше дополнение Google Workspace подключается к сторонней службе или API, требующему авторизации, дополнение может предложить пользователям войти в систему и разрешить доступ.
На этой странице объясняется, как аутентифицировать пользователей с помощью потока авторизации (например, OAuth), который включает следующие шаги:
- Определите, когда требуется авторизация.
- Верните интерфейс карты, который предлагает пользователям войти в сервис.
- Обновите надстройку, чтобы пользователи могли получить доступ к сервису или защищенному ресурсу.
Если для вашего дополнения требуется только идентификатор пользователя, вы можете напрямую аутентифицировать пользователей, используя их идентификатор Google Workspace или адрес электронной почты. Чтобы использовать адрес электронной почты для аутентификации, см. раздел проверка запросов JSON . Если вы создали свое дополнение с помощью Google Apps Script, вы можете упростить этот процесс, используя библиотеку OAuth2 для Google Apps Script (также есть версия OAuth1 ).
Определить, что требуется авторизация
При использовании вашего дополнения пользователи могут не получить доступ к защищенному ресурсу по разным причинам, например:
- Токен доступа для подключения к сторонней службе еще не создан или срок его действия истек.
- Токен доступа не охватывает запрошенный ресурс.
- Токен доступа не охватывает требуемые области запроса.
Ваше дополнение должно обнаруживать такие случаи, чтобы пользователи могли войти в систему и получить доступ к вашему сервису.
Если вы создаете в Apps Script, функция hasAccess()
библиотеки OAuth может сообщить вам, есть ли у вас доступ к службе. В качестве альтернативы, при использовании запросов UrlFetchApp fetch()
вы можете установить параметр muteHttpExceptions
в значение true
. Это предотвращает выдачу исключения запросом при сбое запроса и позволяет вам проверять код ответа запроса и содержимое в возвращаемом объекте HttpResponse
.
Предложите пользователям войти в ваш сервис
Когда ваш add-on обнаруживает, что требуется авторизация, add-on должен вернуть интерфейс карты , чтобы предложить пользователям войти в сервис. Карта входа должна перенаправлять пользователей для завершения процесса сторонней аутентификации и авторизации в вашей инфраструктуре.
При создании надстройки с использованием конечных точек HTTP мы рекомендуем вам защитить целевое приложение с помощью Google Sign-in и получить идентификатор пользователя с помощью токена идентификации, выданного во время входа. Подзаявка содержит уникальный идентификатор пользователя и может быть сопоставлена с идентификатором из вашей надстройки.
Создайте и верните карту входа
Для карты входа в вашу службу вы можете использовать базовую карту авторизации Google или настроить карту для отображения дополнительной информации, например логотипа вашей организации. Если вы публикуете свое дополнение публично, вы должны использовать пользовательскую карту.
Базовая карта авторизации
На следующем изображении показан пример базовой карты авторизации Google:

Чтобы предложить пользователям базовую карту авторизации, необходимо вернуть объект AuthorizationError
. Следующий код показывает пример объекта AuthorizationError
:
Скрипт приложений
CardService.newAuthorizationException() .setAuthorizationUrl('AUTHORIZATION_URL') .setResourceDisplayName('RESOURCE_DISPLAY_NAME') .throwException();
JSON
Верните следующий ответ JSON:
{
"basic_authorization_prompt": {
"authorization_url": "AUTHORIZATION_URL",
"resource": "RESOURCE_DISPLAY_NAME"
}
}
Заменить следующее:
-
AUTHORIZATION_URL
: URL-адрес веб-приложения, которое обрабатывает авторизацию. -
RESOURCE_DISPLAY_NAME
: Отображаемое имя защищенного ресурса или службы. Это имя отображается пользователю в запросе на авторизацию. Например, если вашRESOURCE_DISPLAY_NAME
—Example Account
, запрос будет гласить: «Это дополнение хотело бы показать дополнительную информацию, но для доступа к вашему Example Account ему необходимо одобрение».
После завершения авторизации пользователю предлагается обновить надстройку для доступа к защищенному ресурсу.
Возврат карт авторизации в Google Chat
Если ваше дополнение расширяет Google Chat и пользователь выполняет его в Google Chat, пользователь может завершить процесс авторизации без ручного обновления. Google Chat поддерживает автоматическое повторение предыдущего выполнения, если триггером является Message , Added to space или App command . Для этих триггеров ваше дополнение получает completeRedirectUri
в полезной нагрузке события . Вы должны закодировать completeRedirectUri
в URL-адресе конфигурации, чтобы запустить автоматическое повторение. Перенаправление на этот URL-адрес сигнализирует Google Chat о том, что запрос конфигурации был выполнен, и позволяет Google Chat повторить предыдущее выполнение.
Когда пользователь успешно перенаправляется на configCompleteRedirectUrl
указанный в исходном сообщении, Google Chat выполняет следующие действия:
- Удаляет подсказку, отображаемую инициирующему пользователю.
- Отправляет исходный объект события в то же дополнение второй раз.
Если вы не закодируете completeRedirectUri
в URL-адресе конфигурации, пользователь все равно сможет завершить поток авторизации. Однако Google Chat не повторяет предыдущее выполнение, и пользователь должен вручную снова вызвать ваше дополнение.
Пользовательская карта авторизации
Чтобы изменить запрос на авторизацию, вы можете создать специальную карту для входа в систему вашего сервиса.
Если вы публикуете свое дополнение публично, вы должны использовать специальную карту авторизации. Чтобы узнать больше о требованиях к публикации для Google Workspace Marketplace, см . раздел About app review .
Возвращаемая карта должна соответствовать следующим требованиям:
- Дайте пользователю понять, что дополнение запрашивает разрешение на доступ к сторонним службам от его имени.
- Дайте ясно понять, что может делать надстройка, если она авторизована.
- Содержит кнопку или аналогичный виджет, который перенаправляет пользователя на URL авторизации сервиса. Убедитесь, что функция этого виджета очевидна для пользователя.
- Приведенный выше виджет должен использовать настройку
OnClose.RELOAD
в своем объектеOpenLink
, чтобы гарантировать перезагрузку надстройки после получения авторизации. - Все ссылки, открываемые из запроса на авторизацию, должны использовать HTTPS .
На следующем изображении показан пример пользовательской карты авторизации для домашней страницы дополнения. Карта включает логотип, описание и кнопку входа:

Следующий код показывает, как использовать этот пример пользовательской карты:
Скрипт приложений
function customAuthorizationCard() {
let cardSection1Image1 = CardService.newImage()
.setImageUrl('LOGO_URL')
.setAltText('LOGO_ALT_TEXT');
let cardSection1Divider1 = CardService.newDivider();
let cardSection1TextParagraph1 = CardService.newTextParagraph()
.setText('DESCRIPTION');
let cardSection1ButtonList1Button1 = CardService.newTextButton()
.setText('Sign in')
.setBackgroundColor('#0055ff')
.setTextButtonStyle(CardService.TextButtonStyle.FILLED)
.setAuthorizationAction(CardService.newAuthorizationAction()
.setAuthorizationUrl('AUTHORIZATION_URL'));
let cardSection1ButtonList1 = CardService.newButtonSet()
.addButton(cardSection1ButtonList1Button1);
let cardSection1TextParagraph2 = CardService.newTextParagraph()
.setText('TEXT_SIGN_UP');
let cardSection1 = CardService.newCardSection()
.addWidget(cardSection1Image1)
.addWidget(cardSection1Divider1)
.addWidget(cardSection1TextParagraph1)
.addWidget(cardSection1ButtonList1)
.addWidget(cardSection1TextParagraph2);
let card = CardService.newCardBuilder()
.addSection(cardSection1)
.build();
return [card];
}
function startNonGoogleAuth() {
CardService.newAuthorizationException()
.setAuthorizationUrl('AUTHORIZATION_URL')
.setResourceDisplayName('RESOURCE_DISPLAY_NAME')
.setCustomUiCallback('customAuthorizationCard')
.throwException();
}
JSON
Верните следующий ответ JSON:
{
"custom_authorization_prompt": {
"action": {
"navigations": [
{
"pushCard": {
"sections": [
{
"widgets": [
{
"image": {
"imageUrl": "LOGO_URL",
"altText": "LOGO_ALT_TEXT"
}
},
{
"divider": {}
},
{
"textParagraph": {
"text": "DESCRIPTION"
}
},
{
"buttonList": {
"buttons": [
{
"text": "Sign in",
"onClick": {
"openLink": {
"url": "AUTHORIZATION_URL",
"onClose": "RELOAD",
"openAs": "OVERLAY"
}
},
"color": {
"red": 0,
"green": 0,
"blue": 1,
"alpha": 1,
}
}
]
}
},
{
"textParagraph": {
"text": "TEXT_SIGN_UP"
}
}
]
}
]
}
}
]
}
}
}
Заменить следующее:
-
LOGO_URL
: URL-адрес логотипа или изображения. Должен быть публичным URL-адресом. -
LOGO_ALT_TEXT
: Альтернативный текст для логотипа или изображения, например,Cymbal Labs Logo
. -
DESCRIPTION
: Призыв к действию для пользователей войти в систему, например:Sign in to get started
. - Чтобы обновить кнопку входа:
-
AUTHORIZATION_URL
: URL-адрес веб-приложения, которое обрабатывает авторизацию. - Необязательно: Чтобы изменить цвет кнопки, обновите значения RGBA float поля
color
. Для Apps Script обновите методsetBackgroundColor()
, используя шестнадцатеричные значения.
-
-
TEXT_SIGN_UP
: Текст, который предлагает пользователям создать учетную запись, если у них ее нет. Например,New to Cymbal Labs? <a href=\"https://www.example.com/signup\">Sign up</a> here
.
Управление сторонними входами в приложения Google Workspace
Одним из распространенных применений дополнений Google Workspace является предоставление интерфейса для взаимодействия со сторонней системой из хост-приложения Google Workspace.
Сторонние системы часто требуют, чтобы пользователь входил в систему с использованием идентификатора пользователя, пароля или других учетных данных. Когда пользователь входит в вашу стороннюю службу, используя один хост Google Workspace, вы должны убедиться, что ему не придется входить снова при переключении на другой хост Google Workspace.
Если вы создаете в Apps Script, вы можете предотвратить повторные запросы на вход с помощью свойств пользователя или токенов ID. Они объясняются в следующих разделах.
Свойства пользователя
Вы можете хранить данные входа пользователя в свойствах пользователя Apps Script. Например, вы можете создать свой собственный JSON Web Token (JWT) из их службы входа и записать его в свойство пользователя или записать имя пользователя и пароль для их службы.
Пользовательские свойства ограничены так, что они доступны только этому пользователю в скрипте вашего дополнения. Другие пользователи и другие скрипты не могут получить доступ к этим свойствам. Подробнее см. PropertiesService
.
Идентификационные токены
Вы можете использовать токен Google ID в качестве учетных данных для входа в ваш сервис. Это способ достижения единого входа. Пользователи уже вошли в Google, поскольку они находятся в хост-приложении Google.
Пример конфигурации OAuth не от Google
Следующий пример кода Apps Script показывает, как настроить надстройку для использования API, не принадлежащего Google, требующего OAuth. Этот пример использует библиотеку OAuth2 для Apps Script для создания службы для доступа к API.
Скрипт приложений
/**
* Attempts to access a non-Google API using a constructed service
* object.
*
* If your add-on needs access to non-Google APIs that require OAuth,
* you need to implement this method. You can use the OAuth1 and
* OAuth2 Apps Script libraries to help implement it.
*
* @param {String} url The URL to access.
* @param {String} method_opt The HTTP method. Defaults to GET.
* @param {Object} headers_opt The HTTP headers. Defaults to an empty
* object. The Authorization field is added
* to the headers in this method.
* @return {HttpResponse} the result from the UrlFetchApp.fetch() call.
*/
function accessProtectedResource(url, method_opt, headers_opt) {
var service = getOAuthService();
var maybeAuthorized = service.hasAccess();
if (maybeAuthorized) {
// A token is present, but it may be expired or invalid. Make a
// request and check the response code to be sure.
// Make the UrlFetch request and return the result.
var accessToken = service.getAccessToken();
var method = method_opt || 'get';
var headers = headers_opt || {};
headers['Authorization'] =
Utilities.formatString('Bearer %s', accessToken);
var resp = UrlFetchApp.fetch(url, {
'headers': headers,
'method' : method,
'muteHttpExceptions': true, // Prevents thrown HTTP exceptions.
});
var code = resp.getResponseCode();
if (code >= 200 && code < 300) {
return resp.getContentText("utf-8"); // Success
} else if (code == 401 || code == 403) {
// Not fully authorized for this action.
maybeAuthorized = false;
} else {
// Handle other response codes by logging them and throwing an
// exception.
console.error("Backend server error (%s): %s", code.toString(),
resp.getContentText("utf-8"));
throw ("Backend server error: " + code);
}
}
if (!maybeAuthorized) {
// Invoke the authorization flow using the default authorization
// prompt card.
CardService.newAuthorizationException()
.setAuthorizationUrl(service.getAuthorizationUrl())
.setResourceDisplayName("Display name to show to the user")
.throwException();
}
}
/**
* Create a new OAuth service to facilitate accessing an API.
* This example assumes there is a single service that the add-on needs to
* access. Its name is used when persisting the authorized token, so ensure
* it is unique within the scope of the property store. You must set the
* client secret and client ID, which are obtained when registering your
* add-on with the API.
*
* See the Apps Script OAuth2 Library documentation for more
* information:
* https://github.com/googlesamples/apps-script-oauth2#1-create-the-oauth2-service
*
* @return A configured OAuth2 service object.
*/
function getOAuthService() {
return OAuth2.createService('SERVICE_NAME')
.setAuthorizationBaseUrl('SERVICE_AUTH_URL')
.setTokenUrl('SERVICE_AUTH_TOKEN_URL')
.setClientId('CLIENT_ID')
.setClientSecret('CLIENT_SECRET')
.setScope('SERVICE_SCOPE_REQUESTS')
.setCallbackFunction('authCallback')
.setCache(CacheService.getUserCache())
.setPropertyStore(PropertiesService.getUserProperties());
}
/**
* Boilerplate code to determine if a request is authorized and returns
* a corresponding HTML message. When the user completes the OAuth2 flow
* on the service provider's website, this function is invoked from the
* service. In order for authorization to succeed you must make sure that
* the service knows how to call this function by setting the correct
* redirect URL.
*
* The redirect URL to enter is:
* https://script.google.com/macros/d/<Apps Script ID>/usercallback
*
* See the Apps Script OAuth2 Library documentation for more
* information:
* https://github.com/googlesamples/apps-script-oauth2#1-create-the-oauth2-service
*
* @param {Object} callbackRequest The request data received from the
* callback function. Pass it to the service's
* handleCallback() method to complete the
* authorization process.
* @return {HtmlOutput} a success or denied HTML message to display to
* the user.
*/
function authCallback(callbackRequest) {
var authorized = getOAuthService().handleCallback(callbackRequest);
if (authorized) {
return HtmlService.createHtmlOutput(
'Success!');
} else {
return HtmlService.createHtmlOutput('Denied');
}
}
/**
* Unauthorizes the non-Google service. This is useful for OAuth
* development/testing. Run this method (Run > resetOAuth in the script
* editor) to reset OAuth to re-prompt the user for OAuth.
*/
function resetOAuth() {
getOAuthService().reset();
}