Я занимаюсь созданием внутреннего приложения, через которое пользователи могут загружать файлы, которые будут храниться на Google Диске. Поскольку рекомендуется не использовать учетные записи служб в качестве владельцев файлов, я хотел, чтобы приложение загружалось от имени назначенной учетной записи пользователя, к которой имеет доступ sysadmin компании.Неспособность делегировать доступ Google Диска к учетной записи службы
Я создал приложение вместе с учетной записью службы. Есть два ключа, созданные для учетной записи службы, как я попытался как JSON и форматы PKCS12 пытаются достичь этого:
Я скачал OAuth 2.0 клиент детали ID, а также имею .json и файлы .p12 для ключей учетной записи службы (в том порядке, как показано выше):
Я был мой сисадмин пройти шаги подробно здесь, чтобы делегировать полномочия для доступа к API Диска к учетной записи службы: https://developers.google.com/drive/v2/web/delegation#delegate_domain-wide_authority_to_your_service_account
Мы обнаружили, что единственное, что работало для «имени клиента» на шаге 4, - это «Идентификатор клиента», указанный для веб-приложения (завершение .apps.googleusercontent.com). Длинные шестнадцатеричные идентификаторы, указанные для ключей учетной записи службы не были, что это необходимо (см ниже):
Ранее к вышесказанному, у меня был код, который будет создавать экземпляр DriveService, которые могли бы загрузить непосредственно на службу счет, ссылающийся на файл .json для ключей учетной записи службы:
private DriveService GetServiceA()
{
var settings = SettingsProvider.GetInstance();
string keyFilePath = HostingEnvironment.MapPath("~/App_Data/keyfile.json");
var scopes = new string[] { DriveService.Scope.Drive };
var stream = new IO.FileStream(keyFilePath, IO.FileMode.Open, IO.FileAccess.Read);
var credential = GoogleCredential.FromStream(stream);
credential = credential.CreateScoped(scopes);
var service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "MyAppName"
});
return service;
}
это работает для включения и загрузки, хотя, конечно, нет веб-интерфейс для доступа к файлам, и кажется, что она не работает такие вещи, как метаданные разрешений или генерация миниатюр, например PDF-файлы. Вот почему я пытаюсь использовать стандартную учетную запись для загрузок.
После того, как делегация была, по-видимому, отсортирована, я попытался адаптировать код, показанный в ссылке, приведенной выше, в сочетании с кодом из другого места для извлечения необходимых деталей из файла ключа .json. С помощью этого кода, как только я пытаюсь выполнить любую команду API, даже просто как:
FileList fileList = service.FileList().Execute();
Я получаю сообщение об ошибке:
Сведения об исключении: Google.Apis.Auth.OAuth2.Responses.TokenResponseException Ошибка: «unauthorized_client», Описание: «Несанкционированное клиент или сфера в запросе.» Ури: «»
код для этой работы является:
private DriveService GetServiceB()
{
var settings = SettingsProvider.GetInstance();
string keyFilePath = HostingEnvironment.MapPath("~/App_Data/keyfile.json");
string serviceAccountEmail = "<account-email>@<project-id>.iam.gserviceaccount.com";
var scopes = new string[] { DriveService.Scope.Drive };
var stream = new IO.FileStream(keyFilePath, IO.FileMode.Open, IO.FileAccess.Read);
var reader = new IO.StreamReader(stream);
string jsonCreds = reader.ReadToEnd();
var o = JObject.Parse(jsonCreds);
string privateKey = o["private_key"].ToString();
var credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = scopes,
User = "[email protected]"
}
.FromPrivateKey(privateKey)
);
var service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "MyAppName"
});
return service;
}
Наконец, я создал второй се rvice для сохранения.p12 файл для того, чтобы более точно соответствовать код в документации делегирования полномочий, но приводит к тем же исключением:
private DriveService GetServiceC()
{
var settings = SettingsProvider.GetInstance();
string p12KeyFilePath = HostingEnvironment.MapPath("~/App_Data/keyfile.p12");
string serviceAccountEmail = "<account-email>@<project-id>.iam.gserviceaccount.com";
var scopes = new string[] { DriveService.Scope.Drive }; // Full access
X509Certificate2 certificate = new X509Certificate2(
p12KeyFilePath,
"notasecret",
X509KeyStorageFlags.Exportable
);
var credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = scopes,
User = "[email protected]"
}
.FromCertificate(certificate)
);
var service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "MyAppName"
});
return service;
}
minimial соответствующий класс, где этот метод живет является:
public class GoogleDrive
{
public DriveService Service { get; private set; }
public GoogleDrive()
{
this.Service = this.GetService();
}
private DriveService GetService()
{
// Code from either A, B or C
}
public FilesResource.ListRequest FileList()
{
return this.Service.Files.List();
}
}
И это используется таким образом:
var service = new GoogleDrive();
FilesResource.ListRequest listRequest = service.FileList();
FileList fileList = listRequest.Execute();
Исключение происходит на этой последней строке.
Я не понимаю, почему моя учетная запись службы не может действовать от имени назначенного пользователя, который является частью домена, для которого учетная запись службы приложения должна иметь делегированные полномочия. Что я здесь неправильно понял?
Это может быть вопрос конфигурации ошибки. Вы указали идентификатор клиента учетной записи службы в имени клиента? Это шаг № 5 в домене [Делегировать полномочия домена для вашей учетной записи службы] (https://developers.google.com/drive/v2/web/delegation#delegate_domain-wide_authority_to_your_service_account) – noogui
@noogui Файл .json, созданный для ключ учетной записи службы содержит запись «client_id», которая является 21-значным десятичным числом. Использование этого для шага № 5 показывает сообщение об ошибке: «Это имя клиента еще не было зарегистрировано в Google». –