Google стремится продвигать расовое равенство для чернокожих сообществ. Смотри как.

Использование OAuth 2.0 для серверных приложений

Система Google OAuth 2.0 поддерживает межсерверное взаимодействие, например, между веб-приложением и службой Google. Для этого сценария вам понадобится учетная запись службы , которая принадлежит вашему приложению, а не отдельному конечному пользователю. Ваше приложение вызывает API Google от имени учетной записи службы, поэтому пользователи не участвуют напрямую. Этот сценарий иногда называют «двусторонним OAuth» или «2LO». (Связанный термин «трехсторонний OAuth» относится к сценариям, в которых ваше приложение вызывает API Google от имени конечных пользователей, и в которых иногда требуется согласие пользователя.)

Обычно приложение использует учетную запись службы, когда приложение использует API Google для работы со своими собственными данными, а не с данными пользователя. Например, приложение, которое использует Google Cloud Datastore для сохранения данных, будет использовать учетную запись службы для аутентификации своих вызовов в Google Cloud Datastore API.

Администраторы домена Google Workspace могут также предоставить служебным учетным записям права доступа на уровне домена для доступа к пользовательским данным от имени пользователей в домене.

В этом документе описывается, как приложение может выполнить межсерверный поток OAuth 2.0 с помощью клиентской библиотеки API Google (рекомендуется) или HTTP.

Обзор

Для поддержки межсерверного взаимодействия сначала создайте сервисную учетную запись для своего проекта в файле API Console. Если вы хотите получить доступ к пользовательским данным для пользователей в своей учетной записи Google Workspace, делегируйте доступ на уровне домена учетной записи службы.

Затем ваше приложение подготавливается к выполнению авторизованных вызовов API, используя учетные данные учетной записи службы для запроса токена доступа с сервера аутентификации OAuth 2.0.

Наконец, ваше приложение может использовать токен доступа для вызова API Google.

Создание учетной записи службы

Учетные данные учетной записи службы включают сгенерированный адрес электронной почты, который является уникальным, и по крайней мере одну пару открытого / закрытого ключей. Если делегирование на уровне домена включено, то идентификатор клиента также является частью учетных данных учетной записи службы.

Если ваше приложение работает на Google App Engine, учетная запись службы настраивается автоматически при создании проекта.

Если ваше приложение работает в Google Compute Engine, учетная запись службы также настраивается автоматически при создании проекта, но вы должны указать области, к которым вашему приложению нужен доступ, когда вы создаете экземпляр Google Compute Engine. Дополнительные сведения см. В разделе « Подготовка экземпляра к использованию учетных записей служб» .

Если ваше приложение не работает в Google App Engine или Google Compute Engine, вы должны получить эти учетные данные в Google API Console. Чтобы сгенерировать учетные данные служебной учетной записи или просмотреть уже созданные общедоступные учетные данные, выполните следующие действия:

  1. Откройте Service accounts page .
  2. If prompted, select a project, or create a new one.
  3. Нажмите Создать учетную запись службы .
  4. В разделе Сведения об учетной записи службы введите имя, идентификатор и описание для учетной записи службы, затем нажмите « Создать» .
  5. Необязательно: В разделе Разрешения учетной записи службы выберите роли IAM для предоставления учетной записи службы, затем нажмите « Продолжить» .
  6. Необязательно: В разделе Предоставить пользователям доступ к этой учетной записи службы добавьте пользователей или группы, которым разрешено использовать и управлять учетной записью службы.
  7. Нажмите ключ создания , затем нажмите Создать .

Ваша новая пара открытых / закрытых ключей генерируется и загружается на ваш компьютер; он служит единственной копией закрытого ключа. Вы несете ответственность за его надежное хранение. Если вы потеряете эту пару ключей, вам нужно будет сгенерировать новую.

Если вам необходимо предоставить полномочия G Suite для всей учетной записи службы, щелкните адрес электронной почты созданной учетной записи службы, а затем скопируйте значение из поля Уникальный идентификатор .

Чтобы делегировать полномочия учетной записи службы, используйте скопированное значение в качестве идентификатора клиента.

Вы можете вернуться к API Console в любое время, чтобы просмотреть адрес электронной почты, отпечатки открытого ключа и другую информацию или создать дополнительные пары открытого / закрытого ключей. Дополнительные сведения об учетных данных службы в API Console см. В разделе Учетные записи служб в файле справки API Console.

Запишите адрес электронной почты учетной записи службы и сохраните файл закрытого ключа учетной записи в месте, доступном для вашего приложения. Они нужны вашему приложению для выполнения авторизованных вызовов API.

Делегирование полномочий на уровне домена учетной записи службы

Если у вас есть учетная запись Google Workspace, администратор организации может разрешить приложению доступ к пользовательским данным от имени пользователей в домене Google Workspace. Например, приложение, использующее API Календаря Google для добавления событий в календари всех пользователей в домене Google Workspace, будет использовать учетную запись службы для доступа к API Календаря Google от имени пользователей. Авторизация учетной записи службы для доступа к данным от имени пользователей в домене иногда называется «делегированием полномочий на уровне домена» учетной записи службы.

Чтобы делегировать полномочия на уровне домена учетной записи службы, сначала включите делегирование всего домена для существующей учетной записи службы в Service accounts page или создайте новую учетную запись службы с включенным делегированием всего домена.

Затем суперадминистратор домена Google Workspace должен выполнить следующие действия:

  1. В консоли администратора вашего домена Google Workspace выберите Главное > Безопасность> Управление API .
  2. На панели делегирования домена выберите Управление делегированием домена .
  3. Щелкните Добавить .
  4. В поле « Идентификатор клиента» введите идентификатор клиента учетной записи службы. Вы можете найти идентификатор клиента своей сервисной учетной записи в Service accounts page.
  5. В поле OAuth scopes (разделенные запятыми) введите список областей, к которым вашему приложению должен быть предоставлен доступ. Например, если вашему приложению требуется полный доступ к Google Drive API и Google Calendar API на уровне домена, введите: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth. / календарь .
  6. Щелкните Авторизовать .

Теперь ваше приложение имеет право выполнять вызовы API в качестве пользователей в вашем домене (чтобы «выдавать себя за пользователей»). Когда вы готовитесь к авторизованным вызовам API, вы указываете пользователя, которого хотите выдать.

Подготовка к авторизованному вызову API

Ява

Получив адрес электронной почты клиента и закрытый ключ от API Console, используйте клиентскую библиотеку API Google для Java, чтобы создать объект GoogleCredential из учетных данных учетной записи службы и областей, к которым вашему приложению необходим доступ. Например:

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.sqladmin.SQLAdminScopes;

// ...

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN));

Если вы разрабатываете приложение на Google Cloud Platform, вместо этого вы можете использовать учетные данные приложения по умолчанию , что может упростить процесс.

Делегировать полномочия на уровне домена

Если вы делегировали доступ на уровне домена учетной записи службы и хотите выдать себя за учетную запись пользователя, укажите адрес электронной почты учетной записи пользователя с createDelegated метода GoogleCredential объекта GoogleCredential . Например:

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN))
    .createDelegated("user@example.com");

Используйте объект GoogleCredential для вызова API Google в вашем приложении.

Python

Получив адрес электронной почты клиента и закрытый ключ от API Console, используйте клиентскую библиотеку API Google для Python, чтобы выполнить следующие шаги:

  1. Создайте объект Credentials из учетных данных учетной записи службы и областей, к которым вашему приложению необходим доступ. Например:
    from google.oauth2 import service_account
    
    SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
    SERVICE_ACCOUNT_FILE = '/path/to/service.json'
    
    credentials = service_account.Credentials.from_service_account_file(
            SERVICE_ACCOUNT_FILE, scopes=SCOPES)

    Если вы разрабатываете приложение на Google Cloud Platform, вместо этого вы можете использовать учетные данные приложения по умолчанию , что может упростить процесс.

  2. Делегировать полномочия на уровне домена

    Если вы делегировали общедоменный доступ к учетной записи службы , и вы хотите , чтобы олицетворять учетную запись пользователя, используйте with_subject метод существующего ServiceAccountCredentials объекта. Например:

    delegated_credentials = credentials.with_subject('user@example.org')

Используйте объект Credentials для вызова API Google в вашем приложении.

HTTP / ОТДЫХ

После получения идентификатора клиента и закрытого ключа от API Console ваше приложение должно выполнить следующие шаги:

  1. Создайте веб-токен JSON (JWT, произносится как «jot»), который включает заголовок, набор утверждений и подпись.
  2. Запросите токен доступа у сервера авторизации Google OAuth 2.0.
  3. Обработайте ответ JSON, возвращаемый сервером авторизации.

В следующих разделах описывается, как выполнить эти шаги.

Если ответ включает токен доступа, вы можете использовать токен доступа для вызова Google API . (Если ответ не включает токен доступа, ваш JWT и запрос токена могут быть неправильно сформированы или учетная запись службы может не иметь разрешения на доступ к запрошенным областям.)

Когда срок действия токена доступа истекает , ваше приложение генерирует другой JWT, подписывает его и запрашивает другой токен доступа.

Ваше серверное приложение использует JWT для запроса токена с сервера авторизации Google, а затем использует токен для вызова конечной точки Google API. Конечный пользователь не участвует.

Остальная часть этого раздела описывает особенности создания JWT, подписания JWT, формирования запроса токена доступа и обработки ответа.

Создание JWT

JWT состоит из трех частей: заголовка, набора утверждений и подписи. Заголовок и набор утверждений - это объекты JSON. Эти объекты JSON сериализуются в байты UTF-8, а затем кодируются с использованием кодировки Base64url. Это кодирование обеспечивает устойчивость к изменениям кодирования из-за повторяющихся операций кодирования. Заголовок, набор требований и подпись объединяются символом точки ( . ).

JWT состоит из следующего:

{Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature}

Базовая строка для подписи следующая:

{Base64url encoded header}.{Base64url encoded claim set}
Формирование заголовка JWT

Заголовок состоит из двух полей, которые указывают алгоритм подписи и формат утверждения. Оба поля являются обязательными, и каждое поле имеет только одно значение. По мере введения дополнительных алгоритмов и форматов этот заголовок будет соответственно меняться.

Учетные записи служб используют алгоритм RSA SHA-256 и формат токена JWT. В результате JSON-представление заголовка выглядит следующим образом:

{"alg":"RS256","typ":"JWT"}

Это представление в Base64url выглядит следующим образом:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
Формирование набора заявок JWT

Набор утверждений JWT содержит информацию о JWT, включая запрашиваемые разрешения (области), цель токена, эмитента, время выдачи токена и время жизни токена. Большинство полей обязательны для заполнения. Как и заголовок JWT, набор утверждений JWT является объектом JSON и используется при вычислении подписи.

Обязательные претензии

Необходимые заявки в наборе заявок JWT показаны ниже. Они могут появляться в наборе требований в любом порядке.

Имя Описание
iss Электронный адрес учетной записи службы.
scope Разделенный пробелами список разрешений, запрашиваемых приложением.
aud Дескриптор предполагаемой цели утверждения. При запросе токена доступа это значение всегда https://oauth2.googleapis.com/token .
exp Время истечения срока действия утверждения, заданное в секундах с 00:00:00 UTC, 1 января 1970 г. Это значение имеет максимум 1 час после выданного времени.
iat Время, когда было выдано утверждение, в секундах с 00:00:00 UTC 1 января 1970 г.

Представление JSON необходимых полей в наборе утверждений JWT показано ниже:

{
  "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
}
Дополнительные претензии

В некоторых корпоративных случаях приложение может использовать делегирование на уровне домена, чтобы действовать от имени конкретного пользователя в организации. Разрешение на выполнение этого типа олицетворения должно быть предоставлено до того, как приложение сможет олицетворять пользователя, и обычно обрабатывается суперадминистратором. Дополнительные сведения см. В разделе Управление доступом к API с делегированием домена .

Чтобы получить маркер доступа, который предоставляет приложению делегированный доступ к ресурсу, включите адрес электронной почты пользователя в утверждение JWT, установленное в качестве значения sub .

Имя Описание
sub Адрес электронной почты пользователя, для которого приложение запрашивает делегированный доступ.

Если у приложения нет разрешения олицетворять пользователя, ответ на запрос токена доступа, который включает sub будет ошибкой .

Пример набора утверждений JWT, который включает sub показан ниже:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "sub": "some.user@example.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
Кодирование набора утверждений JWT

Как и заголовок JWT, набор утверждений JWT должен быть сериализован в UTF-8 и закодирован с использованием Base64url. Ниже приведен пример JSON-представления набора утверждений JWT:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
Вычисление подписи

Веб-подпись JSON (JWS) - это спецификация, которая определяет механизм генерации подписи для JWT. Вход для подписи - это байтовый массив следующего содержания:

{Base64url encoded header}.{Base64url encoded claim set}

При вычислении подписи должен использоваться алгоритм подписи в заголовке JWT. Единственный алгоритм подписи, поддерживаемый сервером авторизации Google OAuth 2.0, - это RSA с использованием алгоритма хеширования SHA-256. Это выражается как RS256 в поле alg заголовка JWT.

Подпишите представление ввода UTF-8 с помощью SHA256withRSA (также известного как RSASSA-PKCS1-V1_5-SIGN с хэш-функцией SHA-256) закрытым ключом, полученным от Google API Console. На выходе будет массив байтов.

В этом случае подпись должна быть закодирована в Base64url. Заголовок, набор требований и подпись объединяются символом точки ( . ). Результат - JWT. Он должен быть следующим (для ясности добавлены разрывы строк):

{Base64url encoded header}.
{Base64url encoded claim set}.
{Base64url encoded signature}

Ниже приведен пример JWT до кодирования Base64url:

{"alg":"RS256","typ":"JWT"}.
{
"iss":"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
"scope":"https://www.googleapis.com/auth/prediction",
"aud":"https://oauth2.googleapis.com/token",
"exp":1328554385,
"iat":1328550785
}.
[signature bytes]

Ниже приведен пример подписанного и готового к передаче JWT:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92NC90b2tlbiIsImV4cCI6MTMyODU1NDM4NSwiaWF0IjoxMzI4NTUwNzg1fQ.UFUt59SUM2_AW4cRU8Y0BYVQsNTo4n7AFsNrqOpYiICDu37vVt-tw38UKzjmUKtcRsLLjrR3gFW3dNDMx_pL9DVjgVHDdYirtrCekUHOYoa1CMR66nxep5q5cBQ4y4u2kIgSvChCTc9pmLLNoIem-ruCecAJYgI9Ks7pTnW1gkOKs0x3YpiLpzplVHAkkHztaXiJdtpBcY1OXyo6jTQCa3Lk2Q3va1dPkh_d--GU2M5flgd8xNBPYw4vxyt0mP59XZlHMpztZt0soSgObf7G3GXArreF_6tpbFsS3z2t5zkEiHuWJXpzcYr5zWTRPDEHsejeBSG8EgpLDce2380ROQ

Выполнение запроса токена доступа

После создания подписанного JWT приложение может использовать его для запроса токена доступа. Этот запрос токена доступа является запросом HTTPS POST , а его тело закодировано в URL-адресе. URL-адрес показан ниже:

https://oauth2.googleapis.com/token

В запросе HTTPS POST требуются следующие параметры:

Имя Описание
grant_type Используйте следующую строку в кодировке URL по мере необходимости: urn:ietf:params:oauth:grant-type:jwt-bearer
assertion JWT, включая подпись.

Ниже приведен необработанный дамп запроса 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

Ниже тот же запрос с использованием curl :

curl -d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.RZVpzWygMLuL-n3GwjW1_yhQhrqDacyvaXkuf8HcJl8EtXYjGjMaW5oiM5cgAaIorrqgYlp4DPF_GuncFqg9uDZrx7pMmCZ_yHfxhSCXru3gbXrZvAIicNQZMFxrEEn4REVuq7DjkTMyCMGCY1dpMa8aWfTQFt3Eh7smLchaZsU
' https://oauth2.googleapis.com/token

Обработка ответа

Если запрос JWT и токена доступа сформирован правильно и учетная запись службы имеет разрешение на выполнение операции, то ответ JSON от сервера авторизации включает токен доступа. Ниже приводится пример ответа:

{
  "access_token": "1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M",
  "scope": "https://www.googleapis.com/auth/prediction"
  "token_type": "Bearer",
  "expires_in": 3600
}

expires_in доступа можно повторно использовать в течение периода времени, указанного значением expires_in .

Вызов API Google

Ява

Используйте объект GoogleCredential для вызова API Google, выполнив следующие действия:

  1. Создайте объект службы для API, который вы хотите вызвать, с GoogleCredential объекта GoogleCredential . Например:
    SQLAdmin sqladmin =
        new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
  2. Делайте запросы к службе API, используя интерфейс, предоставляемый объектом службы . Например, чтобы перечислить экземпляры баз данных Cloud SQL в проекте amazing-example-123:
    SQLAdmin.Instances.List instances =
        sqladmin.instances().list("exciting-example-123").execute();

Python

Используйте авторизованный объект Credentials для вызова API Google, выполнив следующие действия:

  1. Создайте объект службы для API, который вы хотите вызвать. Вы создаете служебный объект, вызывая функцию build с именем и версией API и авторизованным объектом Credentials . Например, чтобы вызвать версию 1beta3 API администрирования Cloud SQL:
    import googleapiclient.discovery
    
    sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
  2. Выполняйте запросы к службе API, используя интерфейс, предоставляемый объектом службы . Например, чтобы перечислить экземпляры баз данных Cloud SQL в проекте amazing-example-123:
    response = sqladmin.instances().list(project='exciting-example-123').execute()

HTTP / ОТДЫХ

После того, как ваше приложение получит токен доступа, вы можете использовать этот токен для выполнения вызовов API Google от имени данной учетной записи службы или учетной записи пользователя, если объем доступа, требуемый API, был предоставлен. Для этого, включите маркер доступа в запросе к API путем включения либо access_token параметр запроса или Authorization HTTP заголовка Bearer значение. По возможности предпочтительнее использовать заголовок HTTP, поскольку строки запроса обычно видны в журналах сервера. В большинстве случаев вы можете использовать клиентскую библиотеку для настройки вызовов API Google (например, при вызове API файлов Диска ).

Вы можете опробовать все API Google и просмотреть их возможности на площадке OAuth 2.0 .

Примеры HTTP GET

Вызов drive.files точки drive.files (API файлов drive.files ) с использованием HTTP-заголовка Authorization: Bearer может выглядеть следующим образом. Обратите внимание, что вам необходимо указать собственный токен доступа:

GET /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

Вот вызов того же API для аутентифицированного пользователя с использованием параметра access_token запроса access_token :

GET https://www.googleapis.com/drive/v2/files?access_token=access_token

примеры curl

Вы можете протестировать эти команды с помощью приложения командной строки curl . Вот пример, в котором используется параметр заголовка HTTP (предпочтительно):

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files

Или, в качестве альтернативы, параметр параметра строки запроса:

curl https://www.googleapis.com/drive/v2/files?access_token=access_token

Когда истекает срок действия токенов доступа

expires_in доступа, выданные сервером авторизации Google OAuth 2.0, истекают по истечении срока, expires_in значении expires_in . Когда срок действия токена доступа истекает, приложение должно сгенерировать еще один JWT, подписать его и запросить другой токен доступа.

Коды ошибок JWT

поле error error_description поле Имея в виду Как разрешить
unauthorized_client Unauthorized client or scope in request. Если вы пытаетесь использовать делегирование в масштабе всего домена, учетная запись службы не авторизована в консоли администратора домена пользователя.

Убедитесь, что сервисный аккаунт авторизован на странице делегирования домена в консоли администратора для пользователя в sub утверждении (поле).

Хотя обычно это занимает несколько минут, для распространения авторизации на всех пользователей в вашей учетной записи Google может потребоваться до 24 часов.

unauthorized_client Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested. Сервисный аккаунт был авторизован с использованием адреса электронной почты клиента, а не идентификатора клиента (числового) в консоли администратора. На странице делегирования домена в консоли администратора удалите клиент и повторно добавьте его с числовым идентификатором.
access_denied (любое значение) Если вы используете делегирование на уровне домена, одна или несколько запрошенных областей не авторизованы в консоли администратора.

Убедитесь , что учетная запись службы имеет право в общедоменного делегации странице консоли администратора для пользователя в sub требования (поле), и что он включает в себя все прицелы вы запрашиваете в scope требования вашего JWT.

Хотя обычно это занимает несколько минут, для распространения авторизации на всех пользователей в вашей учетной записи Google может потребоваться до 24 часов.

invalid_grant Not a valid email. Пользователь не существует. Убедитесь, что адрес электронной почты в sub требовании (поле) правильный.
invalid_grant

Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your 'iat' and 'exp' values and use a clock with skew to account for clock differences between systems.

Обычно это означает, что местное системное время неверно. Это также может произойти, если значение exp будет больше, чем на 65 минут в будущем от значения iat , или значение exp меньше, чем значение iat .

Убедитесь, что часы в системе, в которой создается JWT, правильные. При необходимости синхронизируйте свое время с Google NTP .

invalid_grant Invalid JWT Signature.

Утверждение JWT подписано закрытым ключом, не связанным с учетной записью службы, указанной в электронном письме клиента.

В качестве альтернативы утверждение JWT может быть закодировано неправильно - оно должно быть закодировано в кодировке Base64, без новой строки или дополнительных знаков равенства.

Расшифруйте набор утверждений JWT и убедитесь, что ключ, которым подписано утверждение, связан с учетной записью службы.

Попробуйте использовать библиотеку OAuth, предоставленную Google, чтобы убедиться, что JWT сгенерирован правильно.

invalid_scope Invalid OAuth scope or ID token audience provided. Области не были запрошены (пустой список областей) или одна из запрашиваемых областей не существует (т. Е. Недействительна).

Убедитесь в том, что scope претензий (поле) из JWT населен, и сравнить области , которые она содержит с документально прицелов для API , который вы хотите использовать, чтобы гарантировать , что нет никаких ошибок или опечаток.

Обратите внимание , что список областей в scope потребностей утверждают, что они разделены пробелами, а не запятые.

disabled_client The OAuth client was disabled. Ключ, используемый для подписи утверждения JWT, отключен.

Перейдите к Google API Console и в разделе IAM & Admin> Service Accounts включите учетную запись службы, которая содержит «Key ID», используемый для подписи утверждения.

Приложение: Авторизация сервисного аккаунта без OAuth

С некоторыми API Google вы можете выполнять авторизованные вызовы API, используя подписанный JWT непосредственно в качестве токена-носителя, а не токена доступа OAuth 2.0. Когда это возможно, вы можете избежать необходимости делать сетевой запрос к серверу авторизации Google перед вызовом API.

Если API, который вы хотите вызвать, имеет определение службы, опубликованное в репозитории Google API на GitHub , вы можете выполнять авторизованные вызовы API, используя JWT вместо токена доступа. Для этого:

  1. Создайте учетную запись службы, как описано выше. Обязательно сохраните файл JSON, который вы получите при создании учетной записи.
  2. Используя любую стандартную библиотеку JWT, например, найденную на jwt.io , создайте JWT с заголовком и полезной нагрузкой, как в следующем примере:
    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "abcdef1234567890"
    }
    .
    {
      "iss": "123456-compute@developer.gserviceaccount.com",
      "sub": "123456-compute@developer.gserviceaccount.com",
      "aud": "https://firestore.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600
    }
    • В поле kid в заголовке укажите идентификатор закрытого ключа учетной записи службы. Вы можете найти это значение в private_key_id поля вашего файла учетной записи службы JSON.
    • В полях iss и sub укажите адрес электронной почты вашей учетной записи службы. Это значение можно найти в поле client_email в JSON-файле учетной записи службы.
    • В поле aud укажите конечную точку API. Например: https:// SERVICE .googleapis.com/ .
    • Для поля iat укажите текущее время Unix, а для поля exp укажите время ровно через 3600 секунд, когда истечет срок действия JWT.

Подпишите JWT с помощью RSA-256, используя закрытый ключ, найденный в файле JSON вашей учетной записи службы.

Например:

Ява

Использование google-api-java-client и java-jwt :

GoogleCredential credential =
        GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"));
PrivateKey privateKey = credential.getServiceAccountPrivateKey();
String privateKeyId = credential.getServiceAccountPrivateKeyId();

long now = System.currentTimeMillis();

try {
    Algorithm algorithm = Algorithm.RSA256(null, privateKey);
    String signedJwt = JWT.create()
        .withKeyId(privateKeyId)
        .withIssuer("123456-compute@developer.gserviceaccount.com")
        .withSubject("123456-compute@developer.gserviceaccount.com")
        .withAudience("https://firestore.googleapis.com/")
        .withIssuedAt(new Date(now))
        .withExpiresAt(new Date(now + 3600 * 1000L))
        .sign(algorithm);
} catch ...

Python

Используя PyJWT :

iat = time.time()
exp = iat + 3600
payload = {'iss': '123456-compute@developer.gserviceaccount.com',
           'sub': '123456-compute@developer.gserviceaccount.com',
           'aud': 'https://firestore.googleapis.com/',
           'iat': iat,
           'exp': exp}
additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON}
signed_jwt = jwt.encode(payload, PRIVATE_KEY_FROM_JSON, headers=additional_headers,
                       algorithm='RS256')
  1. Вызов API, используя подписанный JWT в качестве токена-носителя:
    GET /v1/projects/abc/databases/123/indexes HTTP/1.1
    Authorization: Bearer SIGNED_JWT
    Host: firestore.googleapis.com