Что такое OAuth2 и зачем он нужен в Google Apps Script?
OAuth2 – это стандарт авторизации, который позволяет приложениям получать доступ к ресурсам пользователей на сторонних сервисах (например, Google Sheets, Google Drive) без необходимости передавать им логин и пароль. В Google Apps Script OAuth2 используется для безопасного доступа к различным Google API и другим сервисам, требующим авторизации.
Представьте, что вы разрабатываете скрипт для автоматической отправки отчетов из Google Sheets в Slack. OAuth2 позволяет вашему скрипту отправлять сообщения в Slack от имени пользователя, не запрашивая его пароль Slack. Это значительно повышает безопасность и удобство использования.
Основные принципы работы OAuth2: Grant Types, Access Token, Refresh Token
OAuth2 работает по следующей схеме:
- Приложение запрашивает авторизацию у пользователя. Для этого приложение перенаправляет пользователя на страницу авторизации сервиса (например, Google).
- Пользователь предоставляет приложению доступ к своим данным.
- Сервис выдает приложению Access Token. Это временный ключ, который приложение использует для доступа к ресурсам пользователя.
- Приложение использует Access Token для доступа к API сервиса.
- Access Token имеет ограниченный срок действия. Когда срок действия Access Token истекает, приложение использует Refresh Token для получения нового Access Token. Refresh Token выдается вместе с Access Token и позволяет приложению обновлять Access Token без повторного запроса авторизации у пользователя.
Grant Types определяют способ получения Access Token. Наиболее распространенный тип – Authorization Code Grant, который используется в большинстве веб-приложений.
Обзор библиотеки OAuth2 для Google Apps Script: преимущества и возможности
Библиотека OAuth2 для Google Apps Script упрощает процесс реализации OAuth2 авторизации. Она предоставляет удобные функции для:
- Генерации URL для авторизации.
- Обмена authorization code на access token.
- Автоматического обновления access token с использованием refresh token.
- Проверки срока действия access token.
- Кэширования токенов для повышения производительности.
Использование библиотеки OAuth2 позволяет разработчикам сосредоточиться на логике своего приложения, а не на сложностях протокола OAuth2.
Подготовка к использованию библиотеки OAuth2
Создание проекта в Google Cloud Platform (GCP) и настройка OAuth 2.0 Client ID
- Перейдите в Google Cloud Platform Console.
- Создайте новый проект или выберите существующий.
- В меню выберите «APIs & Services» -> «Credentials».
- Нажмите «Create credentials» и выберите «OAuth client ID».
- Выберите тип приложения (например, «Web application»).
- Укажите имя вашего приложения.
- В поле «Authorized JavaScript origins» укажите URL вашего скрипта Google Apps Script (например,
https://script.google.com/). - В поле «Authorized redirect URIs» укажите URL, на который будет перенаправлен пользователь после авторизации (обычно это URL вашего скрипта Google Apps Script с добавлением параметра
authcallback). Например:https://script.google.com/macros/s/<YOUR_SCRIPT_ID>/devилиhttps://script.google.com/macros/s/<YOUR_SCRIPT_ID>/exec. - Нажмите «Create». Сохраните Client ID и Client Secret – они понадобятся вам для настройки библиотеки OAuth2.
Включение необходимых API (например, Google Sheets API, Google Drive API)
- В Google Cloud Platform Console перейдите в «APIs & Services» -> «Library».
- Найдите и включите API, которые вы планируете использовать (например, Google Sheets API, Google Drive API). Без этого библиотека не сможет получить доступ к API.
Установка библиотеки OAuth2 в Google Apps Script проект
- В редакторе Google Apps Script выберите «Libraries» (значок книги).
- В поле «Enter a Script ID or URL» введите ID библиотеки OAuth2:
1B7FSorxgnh5z6HiDrF2LqkovV9xKlbMsBJtFWdKGZqnZofDtsBsrsFyz. - Выберите последнюю версию библиотеки.
- Укажите alias, например
OAuth2. - Нажмите «Add».
Использование библиотеки OAuth2 для авторизации
Создание экземпляра сервиса OAuth2
/**
* Создает экземпляр сервиса OAuth2.
*
* @param {string} serviceName - Имя сервиса.
* @return {OAuth2.Service} - Экземпляр сервиса OAuth2.
*/
function getOAuthService(serviceName: string): OAuth2.Service {
const scriptProperties = PropertiesService.getScriptProperties();
const clientId = scriptProperties.getProperty('CLIENT_ID');
const clientSecret = scriptProperties.getProperty('CLIENT_SECRET');
if (!clientId || !clientSecret) {
throw new Error('Необходимо указать Client ID и Client Secret в свойствах скрипта.');
}
return OAuth2.createService(serviceName)
.setClientId(clientId)
.setClientSecret(clientSecret)
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
.setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
.setCallbackFunction('authCallback') // Ваша функция обратного вызова
.setPropertyStore(scriptProperties);
}
Получение URL для авторизации пользователя (Authorization URL)
/**
* Возвращает URL для авторизации пользователя.
*
* @return {string} - URL для авторизации.
*/
function getAuthorizationUrl(): string {
const service = getOAuthService('googleSheets');
return service.getAuthorizationUrl();
}
Обработка callback URL и получение Access Token
/**
* Функция обратного вызова, обрабатывающая результат авторизации.
*
* @param {Object} request - Объект запроса.
* @return {HtmlOutput} - HTML-ответ.
*/
function authCallback(request: any): GoogleAppsScript.HTML.HtmlOutput {
const service = getOAuthService('googleSheets');
const authorized = service.handleCallback(request);
if (authorized) {
return HtmlService.createHtmlOutput('Авторизация прошла успешно! Можете закрыть это окно.');
} else {
return HtmlService.createHtmlOutput('Авторизация не удалась. Попробуйте еще раз.');
}
}
Сохранение и обновление Access Token (использование Refresh Token)
Библиотека OAuth2 автоматически обрабатывает сохранение и обновление Access Token с использованием Refresh Token. Вам не нужно делать это вручную. Она использует PropertiesService для хранения токенов.
Примеры использования OAuth2 библиотеки с различными Google API
Чтение данных из Google Sheets с использованием авторизации
/**
* Читает данные из Google Sheets.
*
* @param {string} spreadsheetId - ID таблицы Google Sheets.
* @param {string} range - Диапазон ячеек для чтения.
* @return {any[][]} - Массив данных.
*/
function readDataFromSheets(spreadsheetId: string, range: string): any[][] {
const service = getOAuthService('googleSheets');
if (service.hasAccess()) {
const accessToken = service.getAccessToken();
const url = `https://sheets.googleapis.com/v4/spreadsheets/${spreadsheetId}/values/${range}`;
const options: GoogleAppsScript.URL_Fetch.URLFetchRequestOptions = {
headers: {
Authorization: `Bearer ${accessToken}`,
},
};
const response = UrlFetchApp.fetch(url, options);
const data = JSON.parse(response.getContentText());
return data.values;
} else {
const authorizationUrl = service.getAuthorizationUrl();
Logger.log(`Необходимо авторизоваться: ${authorizationUrl}`);
throw new Error(`Необходимо авторизоваться. URL: ${authorizationUrl}`);
}
}
Запись данных в Google Drive с использованием авторизации
/**
* Creates a new file in Google Drive with the provided content.
*
* @param {string} fileName - The name of the file to create.
* @param {string} fileContent - The content of the file.
* @param {string} mimeType - The MIME type of the file (e.g., 'text/plain').
* @returns {string} The ID of the created file.
*/
function createFileInDrive(fileName: string, fileContent: string, mimeType: string): string {
const service = getOAuthService('googleDrive');
if (service.hasAccess()) {
const accessToken = service.getAccessToken();
const url = 'https://www.googleapis.com/drive/v3/files?fields=id';
const metadata = {
name: fileName,
mimeType: mimeType,
};
const multipartBody = `--foo_bar_baz\r\n` +
`Content-Type: application/json; charset=UTF-8\r\n\r\n` +
`${JSON.stringify(metadata)}\r\n` +
`--foo_bar_baz\r\n` +
`Content-Type: ${mimeType}\r\n\r\n` +
`${fileContent}\r\n` +
`--foo_bar_baz--`;
const options: GoogleAppsScript.URL_Fetch.URLFetchRequestOptions = {
method: 'post',
contentType: 'multipart/related; boundary=foo_bar_baz',
payload: multipartBody,
headers: {
Authorization: 'Bearer ' + accessToken,
},
muteHttpExceptions: true, // Prevent throwing errors for non-200 responses
};
const response = UrlFetchApp.fetch(url, options);
const responseCode = response.getResponseCode();
const responseBody = response.getContentText();
if (responseCode >= 200 && responseCode < 300) {
const fileId = JSON.parse(responseBody).id;
Logger.log(`File created with ID: ${fileId}`);
return fileId;
} else {
Logger.log(`Error creating file: ${responseCode} - ${responseBody}`);
throw new Error(`Error creating file: ${responseCode} - ${responseBody}`);
}
} else {
const authorizationUrl = service.getAuthorizationUrl();
Logger.log(`Пожалуйста, авторизуйтесь: ${authorizationUrl}`);
throw new Error(`Необходимо авторизоваться. URL: ${authorizationUrl}`);
}
}
Использование OAuth2 для доступа к другим сервисам Google (например, Calendar API, Gmail API)
Аналогичным образом можно использовать OAuth2 для доступа к другим Google API. Просто включите необходимые API в Google Cloud Platform Console и настройте области доступа (scopes) в библиотеке OAuth2 с помощью метода .setScope().
Например, для доступа к Calendar API вам потребуется включить Calendar API в GCP и установить scope https://www.googleapis.com/auth/calendar.
Решение проблем и лучшие практики
Распространенные ошибки при использовании OAuth2 и способы их устранения
- Неправильный Client ID или Client Secret. Убедитесь, что вы правильно указали Client ID и Client Secret в свойствах скрипта.
- Неправильный Redirect URI. Убедитесь, что Redirect URI, указанный в Google Cloud Platform Console, соответствует URL вашего скрипта Google Apps Script.
- Не включены необходимые API. Убедитесь, что вы включили необходимые API в Google Cloud Platform Console.
- Неправильные области доступа (scopes). Убедитесь, что вы запросили необходимые области доступа в библиотеке OAuth2 с помощью метода
.setScope(). - Проблемы с кэшированием токенов. Очистите кэш браузера или попробуйте использовать другой браузер.
Безопасность OAuth2: хранение credentials и защита от атак
- Не храните Client Secret в открытом виде. Используйте
PropertiesServiceдля хранения Client Secret. - Используйте HTTPS. Убедитесь, что ваш скрипт Google Apps Script работает через HTTPS.
- Проверяйте Access Token. Перед использованием Access Token убедитесь, что он действителен.
- Защищайте Refresh Token. Refresh Token позволяет злоумышленнику получить Access Token, поэтому его необходимо хранить в безопасном месте.
Отладка OAuth2 в Google Apps Script
- Используйте Logger.log() для вывода отладочной информации.
- Используйте Chrome Developer Tools для просмотра сетевых запросов.
- Проверяйте ошибки в Google Cloud Platform Console.
- Включите подробное логирование в библиотеке OAuth2 с помощью метода
.setVerbose(true). Это может помочь выявить проблемы с авторизацией.