Учетные данные аутентификации сервисной учетной записи для Google Диска не работают

Я создаю учетные данные для учетной записи службы Google из файла JSON следующим образом:

using var stream = new FileStream(credentialFileName, FileMode.Open, FileAccess.Read);
var credentials = ServiceAccountCredential.FromServiceAccountData(stream);

Учетная запись службы имеет делегирование на уровне домена с областями:

Результат затем используется для создания объекта DriveService или SheetsService.

sheetService = new SheetsService(new BaseClientService.Initializer
{
    HttpClientInitializer = credentials
});
driveService = new DriveService(new BaseClientService.Initializer
{
    HttpClientInitializer = credentials
});

Я успешно взаимодействовал с API Google Таблиц. Запись и чтение без проблем, все работает отлично.

Как только я пытаюсь взаимодействовать с API Google Диска, все не работает из-за отсутствия аутентификации. Этот код является примером:

var fileListRequest = DriveService.Files.List();
fileListRequest.Q = $"'{gDriveFolderID}' in parents";
var fileList = await fileListRequest.ExecuteAsync();

Я получаю исключение: «Диск службы выдал исключение. HttpStatusCode не авторизован. В запросе были неверные учетные данные для аутентификации. Ожидается токен доступа OAuth 2, файл cookie для входа или другие действительные учетные данные для аутентификации. См. https://developers.google.com/identity/sign- в/web/devconsole-project"

Если вместо аутентификации с помощью учетной записи службы я аутентифицируюсь с помощью идентификатора клиента OAuth 2.0, который требует от меня подтверждения на странице браузера, это работает. Проблема в том, что срок действия этой аутентификации истекает.

Я знаю, что мог бы использовать токен обновления. Но в какой-то момент срок его действия также истечет, а учетные записи служб существуют именно для того, чтобы избежать обновления аутентификации при работе с внутренними данными.

Создавая DriveService, вы не указываете область действия OAuth для доступа к Google Диску. Указание областей при настройке делегирования определяет, какие области могут быть запрошены. Ваш код не олицетворяет пользователя, который необходим для использования делегирования. Улучшите свой пост, добавив более полный код. Фрагменты кода слишком короткие.

John Hanley 05.03.2024 17:16

Код, который я опубликовал, — это код, который я использую, а не его короткая версия. Класс BaseClientService.Initializer не имеет свойства Scope, которое я мог бы использовать для указания области OAuth для доступа к Google Диску. Я не знаю, как заставить мой код выдавать себя за пользователя. Можете ли вы рассказать, как вы достигнете того, что сказали, опираясь на мой код?

Manuel Venè 05.03.2024 17:26

Спасибо за ваш вклад. «При создании DriveService вы не указываете область OAuth для доступа к Google Диску» было правильной причиной сбоя. Обращение к нему решило проблему. Я ответил кодом, который правильно создает учетные данные.

Manuel Venè 05.03.2024 17:40
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
226
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Благодаря комментарию Джона Хэнли я ​​смог найти решение. Я предположил, что лучше всего установить области делегирования на уровне всего домена. Я был неправ.

Как писал Джон Хэнли, я «не указывал область действия OAuth для доступа к Google Диску».

Следующий код достигает необходимого результата:

using var stream = new FileStream(credentialFileName, FileMode.Open, FileAccess.Read);
var credentials = ServiceAccountCredential.FromServiceAccountData(stream);
credentials.Scopes = new[]
{
    DriveService.Scope.Drive
};

Свойство credentials.Scopes можно настроить для включения необходимых областей.

Теперь это работает. Еще раз спасибо Джону Хэнли.

Ваш код не выдает себя за пользователя. Вероятно, это означает, что учетная запись службы не использует делегирование всего домена, а вместо этого ей предоставлен прямой доступ к общему ресурсу диска. См. ответ Аманды о том, как указать пользователя, которого нужно выдавать себя за другое лицо.

John Hanley 05.03.2024 17:52

Мы пересеклись с ответами. Просто знайте, что ваш ответ по-прежнему не выдает себя за пользователя.

Amanda Tarafa Mas 05.03.2024 17:56

Правильно, сервисная учетная запись имеет общий доступ к ресурсам диска. Принял ответ Аманды Тарафы Мас, поскольку он более полный.

Manuel Venè 05.03.2024 18:02
Ответ принят как подходящий

Ваш код не завершен, вы не проверяете свои учетные данные и не используете олицетворение пользователя.

var credentials = GoogleCredential.FromFile(credentialFileName)
    .CreateScoped(
        "https://www.googleapis.com/auth/drive", 
        "https://www.googleapis.com/auth/spreadsheets")
     // This is the email of the user in the domain where
     // the service account has domain wide delegation,
     // that you want to manipulate Drive files/Sheets for.
    .CreateWithUser("[email protected]");

var sheetService = new SheetsService(new BaseClientService.Initializer
{
    HttpClientInitializer = credentials
});
var driveService = new DriveService(new BaseClientService.Initializer
{
    HttpClientInitializer = credentials
});

Я не уверен, почему раньше это работало для Sheets.

Другие вопросы по теме