访问旧的GData API与使用OAuth 2(电子表格API)和服务帐户(Accessing ol

2019-07-04 08:55发布

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

大纲

我目前使用的服务帐户,就能使用谷歌云端硬盘API谷歌的Apps域访问信息的.NET应用程序。 这使用工作正常谷歌的API-dotnet的客户端库和代码沿着相同的路线作为这里的样本中显示这是目前我在做什么了很好的基础的例子- 。

我想现在要做的就是这样,以及延长它的使用提供这些API由“新”谷歌API-DOTNET客户端库,它使用了旧的“的GData”库,通过旧规定的谷歌gdata的图书馆 ,特别是电子表格API(也许还有更多的惊喜)。

问题

这是难度就出现了。 前者库不正是我想要的东西,在上面第一段第二个链接为证 - 而事实上我有它做它自己。 无论其 ......虽然第二个库已更新,以支持OAuth 2.0用户除了到OAuth 1.0,其他老AUTH技术,它不会-因为据我可以从谷歌搜索的广泛和步道和错误告诉我们-让“代表我的所有用户”的操作,我需要的服务帐户。

我的问题是我是否失去了一些东西(可能是很难找到或无证的东西),这将让我做我想做的。 如果做不到这一点,有没有什么办法,我可以迫使这种行为,使这两个库并排操作?

理想的解决方案

理想我会爱具有的某种方式Google.GData.Spreadsheets.SpreadsheetsService例如可以采取的优势Google.Apis.Authentication.Auth2Authenticator<AssertionFlowClient>我已经使用实例...不知何故。 就是这样巫术可能吗? 我我缺少明显?

如果做不到这一点,我很高兴再次做整体的OAuth2“断言流客户端”的舞蹈,如果我要以某种方式使旧的库可以处理。

救命?

其他想法

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

  1. 该GDATA库已经存在,并且已经被很多人可能比我聪明的开发。 我不这么嚣张,我相信我可以做得更好。
  2. 我不能确定的OAuth2和服务帐户的做法甚至支持/不允许对这些旧的API。

这是我一直希望避免的,但可能要回落到根据这里的答案,另一种方法将是使用两方模式OAuth 1.0的这个部分。 我不希望,因为应用程序具有部分依赖于一个旧的身份验证方法,而其他部分做了漂亮的新方式只是觉得我错了。 还有的是更多的去错了...


更新

我曾考虑子类GDataRequestFactory和GDataRequest,所以我可以做我自己的要求在工厂和有需要的实例的可能性Google.Apis.Authentication.Auth2Authenticator<AssertionFlowClient>当然,实例Google.Apis.Authentication.IAuthenticator反正)这可能介入,以验证它被称为之前的请求。 但是...对于GDataRequest构造函数是内部的,它已经停止了我。

这真的看起来像这并不意味着要。

Answer 1:

对于跨这个问题(现在在接受的答案链接到该解决方案采用过时的代码)来其他人的缘故,这里是我如何解决它:

首先,在开始“新的API”土地(使用Google.Apis.Auth通过建立NuGet包) ServiceAccountCredential以下谷歌的服务帐户例如 :

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

告诉凭证请求访问令牌:

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

现在是时候切换回“旧的API”土地(使用Google.GData.Spreadsheets NuGet包)。 通过构建启动SpreadsheetsService (类似于谷歌的例子 ):

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

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

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地址到片材)



Answer 2:

我设法通过继承GDataRequestFactory和创建我自己的实现由GDataRequest实现的接口来解决这个问题。 此实现包装经由反射实例GDataRequest的一个实例,并且在必要的代码添加使用IAuthenticator的一个实例(在我的情况下,Auth2Authenticator)进行认证。

我写了这一篇博客文章,并添加了一个例子作为要点:

  • 博客:使用谷歌的电子表格API使用.NET,OAuth 2.0用户和服务帐户
  • 吉斯特4244834

随意使用这一点,如果它可以帮助你(BSD许可证)。



Answer 3:

嘿只是偶然翻过了同样的问题,产生了不同的解决方案:

有没有人曾经concidered从凭证对象的参数直接写入到OAuth2Parameters-对象?

我这样做,它很好地工作:

public class OAuthTest
{  
    OAuth2Parameters param = new OAuth2Parameters();

    public OAuthTest()
    {
        Debug.WriteLine("Calling: AuthGoogleDataInterface()");
        bool init = AuthGoogleDataInterface();
        if (init)
        {
            GOAuth2RequestFactory requestFactory = new GOAuth2RequestFactory(null, "My App User Agent", this.param);
            //requestFactory.CustomHeaders.Add(string.Format("Authorization: Bearer {0}", credential.Token.AccessToken));
            var service = new SpreadsheetsService("MyService");
            service.RequestFactory = requestFactory;
            SpreadsheetQuery query = new SpreadsheetQuery();

            // Make a request to the API and get all spreadsheets.
            SpreadsheetFeed feed = service.Query(query);

            // Iterate through all of the spreadsheets returned
            foreach (SpreadsheetEntry entry in feed.Entries)
            {
                // Print the title of this spreadsheet to the screen
                Debug.WriteLine(entry.Title.Text);
            }
        }
        Debug.WriteLine(m_Init);
    }

    private bool AuthGoogleDataInterface()
    {
        bool b_success;
        try
        {
            Console.WriteLine("New User Credential");
            // New User Credential
            UserCredential credential;
            using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
            {
                GoogleClientSecrets GCSecrets = GoogleClientSecrets.Load(stream);
                string[] ArrScope = new[] { "https://spreadsheets.google.com/feeds", "https://docs.google.com/feeds" };
                credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GCSecrets.Secrets,
                    ArrScope,
                    "user", CancellationToken.None,
                new FileDataStore("My.cal")).Result;
                // put the Information generated for the credentials object into the OAuth2Parameters-Object to access the Spreadsheets
                this.param.ClientId = GCSecrets.Secrets.ClientId; //CLIENT_ID;
                this.param.ClientSecret = GCSecrets.Secrets.ClientSecret; //CLIENT_SECRET;
                this.param.RedirectUri = "urn:ietf:wg:oauth:2.0:oob"; //REDIRECT_URI;
                this.param.Scope = ArrScope.ToString();
                this.param.AccessToken = credential.Token.AccessToken;
                this.param.RefreshToken = credential.Token.RefreshToken;
            }

            Debug.WriteLine("AuthGoogleDataInterface: Success");
            b_success = true;
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.ToString());
            b_success = false;
        }
        return b_success;
    }
}


文章来源: Accessing older GData APIs (Spreadsheet API) using OAuth 2 and a service account