如何使用C#中的服务帐户登录Google API-无效的凭据

问题描述:

我为自己的流血而努力,试图获得一个简单的服务帐户登录名以使用C#,Google API和Google Analytics(分析).我的公司已经将数据导入到Analytics(分析)中,我可以使用他们的Query Explorer查询信息,但是从.Net入门并没有成功.我使用的是Google生成的带有PKI的json文件,因为该文档说,这样的服务帐户是使用Googla API进行计算机到计算机通信的正确方法.代码段:

I'm beating myself bloody trying to get a simple service acccount login to work in C#, to Google API and Google Analytics. My company is already getting data into Analytics, and I can query information with their Query Explorer, but getting started in .Net is not going anywhere. I am using a Google-generated json file with PKI, as the documentation says that such a service account is the proper way for computer-to-computer communication with Googla API. Code snipet:

public static GoogleCredential _cred;
public static string _exePath;

static void Main(string[] args) {
    _exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Replace(@"file:\", "");
    var t = Task.Run(() => Run());
    t.Wait();
}

private static async Task Run() {
    try {
        // Get active credential
        using (var stream = new FileStream(_exePath + "\\Default-GASvcAcct-508d097b0bff.json", FileMode.Open, FileAccess.Read)) {
            _cred = GoogleCredential.FromStream(stream);
        }
        if (_cred.IsCreateScopedRequired) {
        _cred.CreateScoped(new string[] { AnalyticsService.Scope.Analytics });
        }
        // Create the service
        AnalyticsService service = new AnalyticsService(
            new BaseClientService.Initializer() {
                HttpClientInitializer = _cred,
            });
        var act1 = service.Management.Accounts.List().Execute(); // blows-up here

所有编译都很好,但是当它碰到Execute()语句时,会抛出GoogleApiException错误:

It all compiles fine, but when it hit the Execute() statement, a GoogleApiException error is thrown:

[无效凭据]位置[授权-标头]原因[authError]域[全局]

[Invalid Credentials] Location[Authorization - header] Reason[authError] Domain[global]

我想念什么?

What am I missing?

似乎GoogleAnalytics无法使用通用GoogleCredential并将其解释为ServiceAccountCredential(即使在内部承认它实际上是该类型).因此,您必须采用困难的方式创建ServiceAccountCredential.同样不幸的是,GoogleCredential没有公开凭证的各种属性,因此我必须构建自己的凭证.

我在 http://jsonclassgenerator.codeplex.com/处使用JSON C#类生成器来构建个人"使用作为Google API(Newtonsoft.Json)的自动部分的JSON库的ServiceAccountCredential对象,检索了服务帐户的已下载json文件的基本部分,以使用其电子邮件和私钥属性构造所需的凭据.将真实的ServiceAccountCredential传递给GoogleAnalytics服务构造函数,将导致成功登录并访问该帐户的允许资源.

It appears that the GoogleAnalytics cannot consume a generic GoogleCredential and interpret it as a ServiceAccountCredential (even though it is acknowledged, interally, that it is actually of that type). Thus you have to create a ServiceAccountCredential the hard way. It’s also unfortunate that GoogleCredential does not expose the various properties of the credential, so I had to build my own.

I used the JSON C# Class Generator at http://jsonclassgenerator.codeplex.com/ to build a "personal" ServiceAccountCredential object using the JSON library that is an automatic part of Google API (Newtonsoft.Json), retrieved essential parts of the downloaded json file of the service account, to construct the required credential, using its email and private key properties. Passing a genuine ServiceAccountCredential to the GoogleAnalytics service constructor, results in a successful login, and access to that account’s allowed resources.

下面的工作代码示例:

Sample of working code below:

using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Analytics.v3;
using Newtonsoft.Json;
    .
    .
    .
try
{
    // Get active credential
    string credPath = _exePath + @"\Private-67917519b23f.json";

    var json = File.ReadAllText(credPath);
    var cr = JsonConvert.DeserializeObject<PersonalServiceAccountCred>(json); // "personal" service account credential

    // Create an explicit ServiceAccountCredential credential
    var xCred = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(cr.ClientEmail)
    {
        Scopes = new[] {
            AnalyticsService.Scope.AnalyticsManageUsersReadonly,
            AnalyticsService.Scope.AnalyticsReadonly
        }
    }.FromPrivateKey(cr.PrivateKey));

    // Create the service
    AnalyticsService service = new AnalyticsService(
        new BaseClientService.Initializer()
        {
            HttpClientInitializer = xCred,
        }
    );

    // some calls to Google API
    var act1 = service.Management.Accounts.List().Execute();

    var actSum = service.Management.AccountSummaries.List().Execute();

    var resp1 = service.Management.Profiles.List(actSum.Items[0].Id, actSum.Items[0].WebProperties[0].Id).Execute();

有些人可能想知道Google生成的带有PKI(私钥)的服务帐户凭据是什么样的.从Google APIs Manager(IAM和Admin)的 https://console.developers.google .com/iam-admin/projects ,选择适当的项目(您至少有一个).现在,从左侧导航链接中选择服务帐户,然后在屏幕顶部选择创建服务帐户.填写名称,设置提供新的私钥复选框,然后单击创建. Google会自动下载JSON文件,如下所示:

Some may wonder what a Google-generated service account credential with PKI (Private Key) looks like. From the Google APIs Manager (IAM & Admin) at https://console.developers.google.com/iam-admin/projects, select the appropriate project (you have at least one of these). Now select Service accounts (from the left nav links), and CREATE SERVICE ACCOUNT at top of screen. Fill in a name, set the Furnish a new private key checkbox, then click Create. Google will cause an automatic download of a JSON file, that looks something like this:

{
  "type": "service_account",
  "project_id": "atomic-acrobat-135",
  "private_key_id": "508d097b0bff9e90b8d545f984888b0ef31",
  "private_key": "-----BEGIN PRIVATE KEY-----\nMIIE...o/0=\n-----END PRIVATE KEY-----\n",
  "client_email": "google-analytics@atomic-acrobat-135.iam.gserviceaccount.com",
  "client_id": "1123573016559832",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://accounts.google.com/o/oauth2/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/google-analytics%40atomic-acrobat-135923.iam.gserviceaccount.com"
}