c# - 使用 OAuth 2 和服务帐户访问旧版 GData API(电子表格 API)

标签 c# .net oauth-2.0 gdata-api google-spreadsheet-api

简短的问题是这是否可能,如果可能,如何实现?

大纲

我有一个 .NET 应用程序,它目前使用服务帐户通过 Google Drive API 访问整个 Google Apps 域中的信息。使用 google-api-dotnet-client library 效果很好并沿同一行编写代码 as shown in the samples here - 这是目前我正在做的一个非常好的基本示例。

我现在想做的是扩展它以及 using those APIs provided通过"new"google-api-dotnet-client 库,它使用旧的“GData”库,如通过 旧google-gdata library ,特别是 Spreadsheets API(可能还会有更多)。

问题

困难就在这里。正如上面第一段中的第二个链接所证明的那样,以前的图书馆完全按照我的意愿行事 - 事实上我自己也这样做了。 然而...虽然第二个库已更新为支持 OAuth 2.0 除了 OAuth 1.0 和其他较旧的身份验证技术外,它没有 - 据我从广泛的谷歌搜索和跟踪中可以看出 - and-error - 允许我需要的“代表我所有用户的服务帐户”操作。

我的问题是我是否遗漏了某些东西(可能是难以找到或未记录的东西),这些东西可以让我做我想做的事。如果做不到这一点,有什么方法可以强制执行此行为并使这两个库并行运行?

理想的解决方案

理想情况下,我会喜欢以某种方式拥有 Google.GData.Spreadsheets.SpreadsheetsService实例能够利用 Google.Apis.Authentication.Auth2Authenticator<AssertionFlowClient>例如我已经在使用...不知何故。这样的巫术可能吗?我错过了显而易见的东西吗?

如果做不到这一点,我很乐意在必要时以旧库可以处理的某种方式再次让整个 OAuth2“断言流客户端”跳舞。

帮忙吗?

其他想法

我考虑过——但暂时拒绝了——从头开始并编写我自己的库来实现这一目标的选择。这有两个原因:

  1. gdata 库已经存在,并且由许多可能比我聪明的人开发。我没有自大到相信自己可以做得更好。
  2. 我不确定这些旧 API 是否支持/允许使用服务帐户方法的 OAuth2。

我一直希望避免但可能不得不根据此处的答案退回到的另一种方法是对其中的部分使用 2-legged OAuth 1.0。我不想这样做,因为应用程序的某些部分依赖于一种旧的身份验证方法,而其他部分却以一种不错的新方式来实现,这对我来说是不对的。还有更多的问题......


更新

我已经考虑了子类化 GDataRequestFactory 和 GDataRequest 的可能性,这样我就可以创建自己的请求工厂并使用 Google.Apis.Authentication.Auth2Authenticator<AssertionFlowClient> 的实例。 (好吧,无论如何都是 Google.Apis.Authentication.IAuthenticator 的一个实例)它可以在调用之前介入以验证请求。但是... GDataRequest 的构造函数是内部的,这让我停了下来。

这看起来真的不是故意的。

最佳答案

为了其他人遇到这个问题(现在已接受的答案中链接的解决方案使用已弃用的代码),我是这样解决的:

首先,按照 Google 的 Service Account example 设置 ServiceAccountCredential,从“新 API”开始(使用 Google.Apis.Auth nuget 包):

//In the old api, this accessed the main api accounts' sheets, not anymore
//** Important ** share spreadsheets with the Service Account by inviting the "serviceAccountEmail" address to the sheet
string serviceAccountEmail = "12345697-abcdefghijklmnop@developer.gserviceaccount.com";

var certificate = new X509Certificate2(@"key.p12", "notasecret", X509KeyStorageFlags.Exportable);

ServiceAccountCredential credential = new ServiceAccountCredential(
   new ServiceAccountCredential.Initializer(serviceAccountEmail)
   {
       Scopes = new[] { "https://spreadsheets.google.com/feeds", "https://docs.google.com/feeds" }
   }.FromCertificate(certificate));

告诉凭据请求访问 token :

credential.RequestAccessTokenAsync(System.Threading.CancellationToken.None).Wait();

现在是切换回“旧 API”领域的时候了(使用 Google.GData.Spreadsheets nuget 包)。从构造 SpreadsheetsService(类似于 Google 的 example )开始:

SpreadsheetsService service = new SpreadsheetsService("MySpreadsheetIntegration-v1");

要使用服务帐户身份验证,我们将创建 GDataRequestFactory 实例并设置自定义 Authorization header :

var requestFactory = new GDataRequestFactory("My App User Agent");
requestFactory.CustomHeaders.Add(string.Format("Authorization: Bearer {0}", credential.Token.AccessToken));

最后,将 SpreadsheetsServiceRequestFactory 属性设置为这个新工厂:

service.RequestFactory = requestFactory;

继续使用 SpreadsheetsService,就像您使用任何其他技术进行身份验证一样。 (提示:通过邀请 serviceAccountEmail 地址访问工作表,与服务帐户共享电子表格)

关于c# - 使用 OAuth 2 和服务帐户访问旧版 GData API(电子表格 API),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13664731/

相关文章:

c# - 这可以在 C# 中简化吗?

c# - 具有相同元素的两个列表不相等。为什么?

c# - 如何获得在 webAPI 项目中公开的方法?

c# - 使用 protobuf-net 序列化巨大的复合图列表导致内存不足异常

c# - 无法上传大小超过 5000 k 的 zip 文件

c# - 编译表达式树性能

.net - 如果工作线程返回未处理的内容,则继续主线程

python - 身份验证后无法访问共享邮箱 - 用户已通过身份验证但未连接

angularjs - 使用 OpenIdConnect 和 angularjs : Bearer was forbidden 基于 Asp.net 核心 token 的声明身份验证

oauth-2.0 - 使用Google Picker Oauth2上传时出现服务器拒绝错误