Автентифікація в Google Workspace API: теоретична частина
Облікові записи та дані Google
Обліковий запис, в Google Cloud також називають ідентичністю (Identity) або principal (принципал), який означує суб’єкта, що може отримувати доступ до ресурсів. Цим суб’єктом може бути людина, застосунок, сервер, пристрій або будь-яка інша сутність, якій система може надати права. Обліковий запис не містить доказу того, що суб’єкт справді є тим, за кого себе видає; він лише описує, хто саме взаємодіє із системою.
Засобом підтвердження автентичності облікового запису є облікові дані, тобто ці дані є доказом того, що суб’єкт контролює відповідну ідентичність. Облікові дані можуть мати різну форму залежно від технології: пароль, криптографічний ключ, сертифікат, токен доступу, біометричний параметр або будь-який інший механізм, який дозволяє системі переконатися, що доступ запитує саме той, хто має на це право.
Розподіл на обліковий запис та облікові дані застосовується в більшості систем безпеки, незалежно від конкретної технології чи стандарту. Він лежить в основі різноманітних протоколів автентифікації та модельованих систем доступу, включно з класичними локальними системами, хмарними платформами, мережевими протоколами та сучасними моделями Zero Trust.
Типи облікових записів
У Google Cloud вживають термін Principal — це ідентичність, якій можна надати доступ до ресурсу. Для автентифікації Google API підтримують два типи principal: облікові записи користувачів (user accounts) і сервісні акаунти (service accounts).
User accounts (облікові записи користувачів, користувацькі аккаунти) представляють розробника, адміністратора або будь-яку іншу особу, яка взаємодіє з Google API та сервісами.
Application Default Credentials (ADC) — це механізм, який автоматично знаходить облікові дані для автентифікації, залежно від середовища, в якому запускається програма.
Service accounts (службові аккаунти, сервісні аккаунти) — це акаунти, які представляють не людину а програму. Вони забезпечують спосіб керувати автентифікацією та авторизацією там, де людина безпосередньо не бере участі, наприклад коли застосунку потрібно отримати доступ до ресурсів Google Cloud. Service accounts керуються через IAM. Детальніше про сервісні аккаунти нижче.
Облікові дані (credentials)
Для автентифікації потрібні облікові дані (credentials) — це цифровий об’єкт, що підтверджує особу або сервіс. У якості облікових даних можуть використовуватися паролі, PIN-коди та біометричні дані, залежно від вимог застосунку. Наприклад, коли ви входите у свій обліковий запис користувача, ви вводите пароль і виконуєте вимогу двофакторної автентифікації, доводячи, що цей обліковий запис дійсно належить вам, а не використовується кимось зі зловмисних намірів. Варто зауважити що токени (маркери) не є обліковими даними, це цифровий об’єкт, який підтверджує, що викликач надав належні облікові дані. Тип облікових даних, які потрібно надати, залежить від того, до чого саме ви автентифікуєтеся.
У даному розділі зосередимся тільки на тих облікових даних, які адміністратор може створити через Google Cloud console, до них належать:
-
API keys - API-ключі можна використовувати з тими API, які їх приймають, щоб отримати доступ до API. API-ключі, не прив’язані до сервісного акаунта, передають проєкт, який використовується для білінгу та квот. Якщо API-ключ прив’язаний до сервісного акаунта, він також передає ідентичність і авторизацію сервісного акаунта (Preview).
-
OAuth Client IDs - OAuth Client ID використовується для ідентифікації застосунку в Google Cloud. Це необхідно, коли потрібно отримати доступ до ресурсів, що належать вашим кінцевим користувачам, так званий three-legged OAuth (3LO).
-
Service account keys (Ключі сервісного акаунта) Ключі сервісного акаунта ідентифікують суб’єкта (сервісний акаунт) і проєкт, пов’язаний із сервісним акаунтом. Ключі сервісних акаунтів становлять ризик безпеці, якщо ними неправильно керувати. За можливості слід обирати більш безпечні альтернативи.
Методи авторизації
Авторизація в Google Cloud переважно здійснюється через Identity and Access Management (IAM). IAM забезпечує детальне керування доступом як за принципалом, так і за ресурсом. Тобто для принципала можна вказати які саме ресурси і як можна використовувати. Так сам можна в ресурсі означити, які принципали мають до нього доступ (наприклад надати доступ до Google Sheet користувацькому або сервісному акаунту).
Також додатковий рівень авторизації можна застосувати при автентифікації OAuth 2.0 scopes.
- При автентифікації у сервісі Google Cloud, можна використовувати глобальний scope, який дозволяє доступ до всіх сервісів Google Cloud, вказавши
scope = https://www.googleapis.com/auth/cloud-platform. - Якщо застосунку необхідно обмежити доступ більш вузьким scope, можна вказати необхідний з наперед означених. Наприклад
scope=https://www.googleapis.com/auth/spreadsheetsзабезпечує усі можливості читання та редагування таблиць Google Sheet. Обмежені scopes можуть зменшити ризики, якщо код працює в середовищах, де існує ймовірність компрометації токенів, наприклад у мобільних застосунках.
Методи автентифікації в Google Cloud
Google Cloud підтримує кілька основних методів автентифікації, які використовуються залежно від типу застосунку (користувацький, серверний, автоматизований процес, локальний інструмент тощо). Узагальнено, підтримуються такі механізми:
1) Автентифікація за допомогою OAuth 2.0
- Автентифікація кінцевого користувача (End-user authentication). Застосунки, які працюють від імені користувачів (веб, мобільні, desktop), використовують OAuth 2.0 Client ID. Користувач виконує вхід, бачить екран згоди, надає доступ.
- OAuth 2.0 Authorization Code Flow. Основний потік для вебзастосунків. Видається authorization code → обмін на access token → доступ до API.
- OAuth 2.0 Implicit Flow (застарілий, але ще підтримується). Використовується лише у front-end сценаріях без бекенда, але Google рекомендує відмовлятися.
- OAuth 2.0 Device Authorization Flow. Для пристроїв з обмеженим введенням (TV, IoT). Користувач вводить код на іншому пристрої.
- OAuth 2.0 Installed App Flow. Для desktop-застосунків (наприклад, інструменти командного рядка).
2) Службові облікові записи (Service Accounts)
- Автентифікація сервіс-сервіс (server-to-server). Використання приватного ключа службового облікового запису. Найпоширеніший варіант для бекенд-процесів, мікросервісів, Cloud Functions, Cloud Run тощо.
- Domain-wide delegation (для Google Workspace). Сервісний акаунт може діяти від імені всіх користувачів домену (лише для супер-адмінів).
3) API keys (для публічних даних). Найпростіший механізм автентифікації для доступу до публічних ресурсів (напр. Maps, або файлів з відкритим доступом у Workspace). Не використовується для захищених персональних даних.
4) Identity Platform (як окремий сервіс автентифікації). Це використовується у Firebase/Identity Platform, але належить до Google Cloud.
- Парольна автентифікація (email + пароль)
- Телефонна автентифікація (SMS)
- Соціальні провайдери: Google, Facebook, Apple, Microsoft
- Anonymous auth
- Custom token auth (власний токен, підписаний ключем)
5) Workload Identity (для середовищ Kubernetes і хмарних служб)
- Workload Identity Federation. Дозволяє автентифікуватися без зберігання приватних ключів, через: – AWS IAM – Azure AD – OpenID Connect сумісні IdP – SAML 2.0 провайдери
- Workload Identity (GKE). Прив’язка Kubernetes service account → Google service account.
6) Google Cloud CLI та локальна розробка
- gcloud auth login. Через OAuth 2.0 у браузері.
- gcloud auth application-default login. Створює локальні облікові дані для Application Default Credentials.
Керування службовими (сервісними) акаунтами
Службові (сервісні) акаунти — це акаунти, які повинні представляти програму, яка повинна доступатися до ресурсів Google. Нижче наведено кілька методів використання сервісного акаунта для автентифікації в Google API та сервісах — у порядку від найбільш безпечного до найменш безпечного.
- Прикріпити керований користувачем сервісний акаунт до ресурсу та використовувати ADC(Application Default Credentials) для автентифікації. Це рекомендований спосіб автентифікації продуктивного коду, що виконується в Google Cloud. ADC(Application Default Credentials) - це механізм, який автоматично визначає, які облікові дані використовувати для автентифікації в Google API, залежно від того, де запускається ваш код.
- Використати сервісний акаунт для імітації (impersonation) іншого сервісного акаунта. Імітація сервісного акаунта дає змогу тимчасово надати йому більше привілеїв. Тимчасове розширення привілеїв дозволяє виконати необхідний доступ без постійного підвищення прав.
- Використати Workload Identity Federation для автентифікації робочих навантажень, що працюють локально або в іншого хмарного провайдера.
- Використати типовий сервісний акаунт (Default service accounts). Використання типового сервісного акаунта не рекомендується, оскільки за замовчуванням він має занадто високі привілеї, що порушує принцип мінімальних привілеїв.
- Використати ключ сервісного акаунта. Ключі сервісних акаунтів становлять ризик безпеці, якщо ними неправильно керувати.
У Google Cloud існує кілька різних типів сервісних акаунтів:
-
User-managed service accounts (Сервісні акаунти, якими керує користувач) — це акаунти, які ви створюєте й керуєте самостійно. Їх найчастіше використовують як ідентичності для робочих навантажень.
-
Default service accounts (Типові сервісні акаунти) — це також керовані користувачем акаунти, які створюються автоматично при активації певних сервісів Google Cloud. Ви відповідаєте за керування цими акаунтами так само, як і тими, що створили вручну.
-
Service agents (Сервісні агенти) — це сервісні акаунти, які створює та керує ними Google Cloud. Вони дозволяють самим сервісам Google отримувати доступ до ресурсів від вашого імені.
Застосунки та принципали можуть автентифікуватися як сервісний акаунт одним із таких способів:
-
Отримання короткоживучих облікових даних. У багатьох випадках, наприклад коли використовується прикріплений сервісний акаунт або коли в командах gcloud CLI застосовується прапорець
--impersonate-service-account, ці облікові дані отримуються автоматично — вам не потрібно створювати чи керувати ними вручну. -
Використання ключа сервісного акаунта для підписання
JSON Web Token (JWT)та обміну його наaccess token. Оскільки ключі сервісних акаунтів становлять ризик для безпеки, якщо ними неправильно управляти, слід за можливості обирати більш безпечні альтернативи цьому механізму.
Використання OAuth 2.0 для взаємодії типу сервер–сервер
https://developers.google.com/identity/protocols/oauth2/service-account
Система Google OAuth 2.0 підтримує взаємодію сервер–сервер, наприклад між вебзастосунком і сервісами Google. Для цього сценарію потрібен сервісний акаунт. Застосунок викликає Google API від імені сервісного акаунта, тому користувачі безпосередньо не задіяні. Такий сценарій інколи називають «двоногий OAuth» або «2LO». (Пов’язаний термін «трьохногий OAuth» описує сценарії, коли застосунок викликає Google API від імені кінцевого користувача, і де інколи потрібен запит згоди користувача.) Адміністратори домену Google Workspace також можуть надати сервісним акаунтам повноваження на рівні домену для доступу до даних користувачів від їхнього імені.
Послідовність використання сервісного аккаунту наступний:
1) У Google Cloude Console Створюється проєкт. 2) У Google Cloude Console створюється сервісний акаунт. 3) Якщо потрібно отримувати доступ до даних користувачів у домені Google Workspace, треба делегувати сервісному акаунту повноваження на рівні домену. 4) На рівні проєкту активується доступ Google API до потрібних сервісів Google. 5) Після цього застосунок використовуючи облікові дані сервісного акаунта запрошує токен доступу на сервері автентифікації OAuth 2.0.
6) Потім застосунок може використовувати отриманий токен доступу для викликів Google API.
Застосунок може виконати ці дії за допомогою клієнтської бібліотеки Google APIs для потрібної мови програмування або взаємодіючи з системою OAuth 2.0 безпосередньо через HTTP. Однак механізм автентифікації типу сервер–сервер вимагає від застосунку створення та криптографічного підписування JSON Web Tokens (JWT). Помилки в цих кроках можуть спричинити серйозні наслідки та негативно вплинути на безпеку вашого застосунку. З цієї причини наполегливо рекомендується використовувати бібліотеки, такі як Google APIs client libraries, які приховують криптографічні деталі та спрощують код застосунку. Нижче показано, як виконати авторизований виклик API шляхом безпосередньої взаємодії із системою OAuth 2.0 через HTTP.
Розглянемо ці кроки для способу роботи через API keys.
1) Спочатку в Google Cloud Console для сервісного аккаунту створюється API keys, в якому в форматі JSON зазначена необхідна інформація - client ID, приватний ключ та інші дані.
2) Застосунок на основі даних з API key створює JSON Web Token (JWT), який містить заголовок, корисне навантаження (claim set) і підпис. Детально про JWT можна почитати в JSON Web Tokens : теоретична частина
3) Використовуючи створений JWT, застосунок запрошує access token у сервера авторизації Google OAuth 2.0 (рис.1).
4) Сервер авторизації направляє токен доступу ( access token), який надалі використовується в кожному HTTP-запиті до Google API. Якщо access token у відповіді відсутній, це означає, що JWT або запит на отримання токена сформовано неправильно, або сервісний акаунт не має дозволу на використання потрібних scopes. 5) Токен доступу є тимчасовим, і коли його термін спливає, застосунок створює новий JWT, підписує його і надсилає новий запит на отримання токена.

рис.1. Послідовність автентифікації та використання Google API.
Кінцевий користувач у цьому процесі не бере участі.
Нижче описуються подробиці створення JWT, його підписування, формування запиту на отримання access token та обробки відповіді.
Створення сервісного аккаунту
Усі дії з сервісним аккаунтом проводяться через Google Cloud Console https://console.cloud.google.com.
Спочатку створюється проєкт, в межах якого створюється сервісний аккаунт. Потім в розділі сервісних аккаунтів створюється новий сервісний аккаунт

рис.2. Меню проєкту у Google Cloud Console.
Отримання API keys для сервісного аккаунту
Для сервісного аккаунту можна створювати кілька секретних ключів API. Як варіант при створенні можна завантажити його в форматі JSON. Після створення ключа, інформація про нього буде доступна виключно у створеному файлі, який завантажується на комп’ютер після створення.


рис.3. Меню API Key сервісного аккаунту.
Призначення властивостей Api key JSON наступне:
Таб.1. Api key JSON
| Властивість | Призначення |
|---|---|
type |
Вказує тип облікових даних. Для сервісних акаунтів завжди service_account. Це сигнал бібліотекам Google, що автентифікація має виконуватися через JWT + OAuth 2.0. |
project_id |
Ідентифікатор проєкту Google Cloud, до якого належить сервісний акаунт. Використовується для білінгу та прив’язки ресурсів. |
private_key_id |
Ідентифікатор приватного ключа. Google використовує його для ротації ключів та керування ключами сервісного акаунта. Сам по собі він не є секретним, але дозволяє Google знати, який ключ на руках. |
private_key |
Приватний ключ для підпису JWT у форматі PKCS#8 (PEM). Це найважливіше та найсекретніше поле — саме цим ключем підписується JWT для отримання OAuth-токенів (RS256). Якщо цей ключ витікає, зловмисник може отримувати токен доступу від сервісного акаунта. |
client_email |
Ідентичність сервісного акаунта у формі електронного листа. |
client_id |
Числовий ідентифікатор клієнта (OAuth 2.0). Використовується рідше, ніж client_email, але є у метаданих та в Cloud Console. |
auth_uri |
URL для авторизації в класичному OAuth 2.0 user-consent flow. Для сервісних акаунтів це фактично не використовується, але залишається в JSON для сумісності. |
token_uri |
URL, на який код має надсилати JWT для обміну на токен доступу |
auth_provider_x509_cert_url |
Посилання на публічні сертифікати Google, які використовуються для перевірки підпису Google ID tokens. |
client_x509_cert_url |
URL, за яким можна отримати публічний сертифікат сервісного акаунта (X.509). Цим сертифікатом інші сервіси можуть перевіряти підписи, зроблені приватним ключем. |
universe_domain |
Доменна зона для API (майже завжди googleapis.com). Google ввів це для мультидоменних інсталяцій Google Cloud, але для звичайних користувачів це просто метадані. |
Створення JWT
Загальний опис JWT описано в розділі посібника JSON Web Tokens : теоретична частина. Тут зупинимося на особливостях формування JWT для отримання токена доступу саме у сервера авторизації Google OAuth 2.0.
Заголовок JWT містить два обов’язкові поля: алгоритм підпису alg та формат твердження typ, а також необов’язковий key ID:
- алгоритм завжди
"alg": "RS256"(RSA SHA-256) - формат завжди
"typ": "JWT". Key IDє необов’язковим і містить ідентифікатор ключа сервісного акаунта; якщо не вказаноkey ID, то перевіряються всі ключі цього сервісного акаунта, і якщо жоден не підходить, тоді JWT відхиляється.
Приклад JSON-подання заголовка:
{"alg":"RS256","typ":"JWT","kid":"370ab79b4513eb9bad7c9bd16a95cb76b5b2a56a"}
Корисне навантаження JWT містить інформацію про токен, включно з дозволами (scopes), адресатом токена, видавцем, часом створення і строком дії. Більшість полів є обов’язковими. Обов’язкові поля:
iss — email сервісного акаунта
scope — список дозволів, розділених пробілом. Повний перелік доступний за посиланням
aud — адресат токена: завжди https://oauth2.googleapis.com/token
exp — час закінчення дії токена (Unix time), максимум +1 година
iat — час створення токена (Unix time)
Приклад:
{
"iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
"scope": "https://www.googleapis.com/auth/devstorage.read_only",
"aud": "https://oauth2.googleapis.com/token",
"exp": 1328554385,
"iat": 1328550785
}
Може містити і додаткові поля у випадку використання у корпоративних застосунках, про це детально в документації.
При підписуванні JWT використовується секретний ключ private_key отриманий з Api key JSON
Запит токена доступу
Після створення підписаного JWT застосунок може використати його для запиту токена доступу. Такий запит виконується як HTTPS POST на адресу https://oauth2.googleapis.com/token, а тіло запиту має бути наступного формату:
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=<jwt>
де <jwt> - отриманий закодований в Base64 JWT
Необхідні заголовки HTTP:
Content-Type: application/x-www-form-urlencoded
Ось приклад необробленого HTTPS POST запиту, який використовується для отримання токена доступу:
POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.ixOUGehweEVX_UKXv5BbbwVEdcz6AYS-6uQV6fGorGKrHf3LIJnyREw9evE-gs2bmMaQI5_UbabvI4k-mQE4kBqtmSpTzxYBL1TCd7Kv5nTZoUC1CmwmWCFqT9RE6D7XSgPUh_jF1qskLa2w0rxMSjwruNKbysgRNctZPln7cqQ
Обробка відповіді
Якщо JWT та запит на отримання токена доступу сформовано коректно й сервісний акаунт має дозвіл виконувати відповідну операцію, у JSON-відповіді від сервера авторизації міститиметься токен доступу. Нижче наведено приклад такої відповіді:
{
"access_token": "1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M",
"scope": "https://www.googleapis.com/auth/prediction"
"token_type": "Bearer",
"expires_in": 3600
}
access_token — короткоживучий токен для якого час життя expires_in зазначено в секундах. Коли пройде 3600 секунд, токен перестане бути чинним і сервер авторизації почне відповідати помилкою 401 Unauthorized або invalid_token. У нормальному OAuth-процесі після закінчення строку дії потрібно отримати новий access_token через refresh_token (якщо він є). Це стандартне поле в OAuth 2.0.
Використання токена доступу
Після того як застосунок отримує токен доступу, його можна використовувати для викликів Google API від імені певного сервісного акаунта або користувацького акаунта, якщо потрібний API має дозволені scope. Для цього необхідно додати токен доступу до запиту — або як параметр access_token у рядку запиту, або у вигляді значення Bearer в HTTP-заголовку Authorization. Бажано використовувати саме заголовок, оскільки рядки запиту можуть зберігатися в серверних логах.
Розглянемо це на прикладах.
Виклик до точки drive.files (Drive Files API) з використанням заголовка Authorization: Bearer може виглядати наступним чином. Зверніть увагу, що ви маєте підставити свій власний токен доступу:
GET /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token
Ось виклик до того самого API для автентифікованого користувача, але з використанням параметра access_token у рядку запиту:
GET https://www.googleapis.com/drive/v2/files?access_token=access_token
Це не остаточний варіант теоретичної частини.
Практична частина
Для кращого розуміння пройдіть Автентифікація в Google Workspace : практична частина
Посилання
https://docs.cloud.google.com/docs/authentication
Автор
Теоретичне заняття розробив Олександр Пупена.
Feedback
Якщо Ви хочете залишити коментар у Вас є наступні варіанти:
Про проект і можливість допомогти проекту написано тут