使用 OAuth 2 和服务帐户访问较旧的 GData API(电子表格 API) [英] Accessing older GData APIs (Spreadsheet API) using OAuth 2 and a service account

查看:20
本文介绍了使用 OAuth 2 和服务帐户访问较旧的 GData API(电子表格 API)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The short question is whether is this possible and if so, how?

我有一个 .NET 应用程序,该应用程序当前使用服务帐户通过 Google Drive API 访问 Google Apps 域中的信息.这可以很好地使用 google-api-dotnet-client 库 和相同的代码如此处的示例所示 - 目前这是我正在做的工作的一个非常好的基本示例.

I have a .NET application which currently uses a service account to access information across a Google Apps domain using the Google Drive API. This works fine using the google-api-dotnet-client library and code along the same lines as shown in the samples here - which are currently a very good basic example of what I'm doing.

我现在想做的是扩展它以及使用提供的那些 API 通过新的"google-api-dotnet-client 库,它使用旧的GData"库,如通过较旧的 google-gdata 库,特别是电子表格 API(可能还有更多).

What I want to do now is extend it so as well as using those APIs provided by the "new" google-api-dotnet-client library, it uses the older "GData" libraries, as provided for via the older google-gdata library, specifically the Spreadsheets API (and perhaps more to come).

这就是困难的地方.前一个库完全符合我的要求,正如上面第一段中的第二个链接所证明的那样 - 事实上我自己也这样做了.然而...虽然第二个库已经更新为除了 OAuth 1.0 和其他较旧的身份验证技术之外还支持 OAuth 2.0,但它并没有 - 据我从广泛的谷歌搜索和跟踪中得知 -and-error - 允许我需要的代表我所有用户的服务帐户"操作.

This is where the difficulty arises. The former library does exactly what I want, as evidenced by the second link in the first paragraph above - and the fact I have it doing it myself. HOWEVER... although the second library has been updated to support OAuth 2.0 in addition to OAuth 1.0 and the other older auth techniques, it does not - as far as I can tell from extensive Googling and trail-and-error - allow the "service account on behalf of all my users" operation which I need.

我的问题是我是否遗漏了一些可以让我做我想做的事情(可能很难找到或没有记录的东西).如果做不到这一点,有什么办法可以强制这种行为并使这两个库并排运行?

My question is whether I'm missing something (possibly a hard to find or undocumented something) which would allow me to do what I want. Failing that, is there any way I could force this behaviour and make these two libraries operate side by side?

理想情况下,我希望以某种方式让 Google.GData.Spreadsheets.SpreadsheetsService 实例能够利用 Google.Apis.Authentication.Auth2Authenticator> 实例我已经在使用......不知何故.这种巫术可能吗?我错过了显而易见的事情吗?

Ideally I would love some way of having the Google.GData.Spreadsheets.SpreadsheetsService instance be able to take advantage of the Google.Apis.Authentication.Auth2Authenticator<AssertionFlowClient> instance I'm already using... somehow. Is such witchcraft possible? I'm I missing the obvious?

如果不能,我很乐意以旧库可以处理的某种方式再次执行整个 OAuth2断言流客户端"舞蹈.

Failing that, I'm happy to do the whole OAuth2 "assertion flow client" dance again if I have to, in some way that the older library can handle.

帮助?

我已经考虑过 - 暂时拒绝 - 从头开始​​并编写自己的库来实现这一目标的选项.这有两个原因:

I have considered - and rejected for the time being - the option of starting from scratch and writing my own library to make this happen. This is for two reasons:

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

我一直希望避免但可能不得不退回的另一种方法是使用 2-legged OAuth 1.0 来处理其中的一部分.我不想这样做,因为让应用程序的某些部分依赖于一种旧的身份验证方法,而其他部分则使用这种不错的新方法对我来说是错误的.还有很多地方会出错......

An alternate approach which I've been hoping to avoid but may have to fall back to depending on the answers here will be to use 2-legged OAuth 1.0 for portions of this. I'd prefer not to, as having parts of the app rely on one old auth method whilst other parts do it the nice new way just feels wrong to me. And there's that much more to go wrong...

我已经考虑了将 GDataRequestFactory 和 GDataRequest 子类化的可能性,这样我就可以创建自己的请求工厂,并使用 Google.Apis.Authentication.Auth2Authenticator<AssertionFlowClient> 的实例(嗯,一个实例Google.Apis.Authentication.IAuthenticator 无论如何),它可以在请求被调用之前介入以对其进行身份验证.但是…… GDataRequest 的构造函数是内部的,这让我无法理解.

I have considered the possibility of subclassing GDataRequestFactory and GDataRequest so I can make my own request factory and have that take the instance of Google.Apis.Authentication.Auth2Authenticator<AssertionFlowClient> (well, an instance of Google.Apis.Authentication.IAuthenticator anyway) which could step in to authenticate the request just before it's called. However... the constructor for GDataRequest is internal, which has stopped me.

看起来真的不是这样.

推荐答案

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

For the sake of other folks coming across this question (now that the solution linked to in the accepted answer uses deprecated code), here's how I solved it:

首先,按照 Google 的 服务帐户示例:

First, start in "new API" land (use the Google.Apis.Auth nuget package) by setting up a ServiceAccountCredential following Google's Service Account example:

//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));

告诉凭据请求访问令牌:

Tell the credential to request an Access Token:

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

现在是切换回旧 API"领域的时候了(使用 Google.GData.Spreadsheets nuget 包).首先构建 SpreadsheetsService(类似于 Google 的示例):>

Now it's time to switch back to "old API" land (use the Google.GData.Spreadsheets nuget package). Start by constructing the SpreadsheetsService (similar to Google's example):

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

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

To use Service Account authentication, we'll create an instance of the GDataRequestFactory and set a custom Authorization header:

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

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

Finally, set the SpreadsheetsService's RequestFactory property to this new factory:

service.RequestFactory = requestFactory;

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

And go ahead and use the SpreadsheetsService as you would had you authenticated using any other technique. (Tip: share spreadsheets with the Service Account by inviting the serviceAccountEmail address to the sheet)

这篇关于使用 OAuth 2 和服务帐户访问较旧的 GData API(电子表格 API)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆