it-swarm.com.de

So melden Sie sich mit dem Service-Konto in C # bei Google API an - Ungültige Anmeldeinformationen

Ich schlage mich verdammt noch mal, wenn ich versuche, ein einfaches Dienstkonto für die Anmeldung in C #, bei Google API und Google Analytics zu erhalten. Mein Unternehmen erhält bereits Daten in Analytics, und ich kann mit dem Abfrage-Explorer Informationen abfragen. Der Einstieg in .Net ist jedoch nicht von ungefähr. Ich verwende eine von Google generierte Json-Datei mit PKI, da die Dokumentation besagt, dass ein solches Dienstkonto der richtige Weg für die Kommunikation von Computer zu Computer mit der Googla-API ist. 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

Alles kompiliert gut, aber wenn es auf die Execute () - Anweisung trifft, wird ein GoogleApiException-Fehler ausgegeben:

[Ungültige Anmeldeinformationen] Speicherort [Berechtigungs-Header] Grund [authError] Domäne [global]

Was vermisse ich?

18
Vic Lindsey

Es scheint, dass GoogleAnalytics keine generische GoogleCredential verwenden und als ServiceAccountCredential interpretieren kann (auch wenn intern anerkannt wird, dass es sich tatsächlich um dieses Typs handelt). Daher müssen Sie eine ServiceAccountCredential auf die harte Tour erstellen. Es ist auch bedauerlich, dass GoogleCredential die verschiedenen Eigenschaften des Berechtigungsnachweises nicht preisgibt, also musste ich meine eigenen erstellen.

Ich habe mit dem JSON C # -Klassengenerator unter http://jsonclassgenerator.codeplex.com/ ein "persönliches" ServiceAccountCredential-Objekt mit der JSON-Bibliothek erstellt, die ein automatischer Bestandteil der Google-API (Newtonsoft.Json) ist. , riefen wesentliche Teile der heruntergeladenen json-Datei des Dienstkontos ab, um die erforderlichen Anmeldeinformationen mithilfe der E-Mail- und privaten Schlüsseleigenschaften zu erstellen. Wenn Sie eine echte ServiceAccountCredential an den GoogleAnalytics-Service-Konstruktor übergeben, erhalten Sie eine erfolgreiche Anmeldung und Zugriff auf die zulässigen Ressourcen dieses Kontos.

Beispiel für einen Arbeitscode:

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

Einige fragen sich vielleicht, wie ein von Google generierter Service-Account mit PKI (Private Key) aussieht. Wählen Sie im Google APIs Manager (IAM & Admin) unter https://console.developers.google.com/iam-admin/projects das entsprechende Projekt aus (Sie haben mindestens eines davon). Wählen Sie nun Dienstkonten (von den linken Navigationslinks) und CREATE SERVICE ACCOUNT am oberen Bildschirmrand. Geben Sie einen Namen ein, setzen Sie das Kontrollkästchen Neuen privaten Schlüssel einrichten, und klicken Sie auf Erstellen. Google veranlasst das automatische Herunterladen einer JSON-Datei, die ungefähr wie folgt aussieht:

{
  "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": "[email protected]",
  "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"
}
23
Vic Lindsey

Der Fehler wegen ungültiger Anmeldeinformationen tritt auf, weil die angegebenen Bereiche nicht tatsächlich mit Ihren Anmeldeinformationen gesendet werden. Ich habe den gleichen Fehler gemacht und erst nach dem Debuggen erkannt, dass nach dem Aufruf von CreateScoped noch 0 Bereiche für die Berechtigungsnachweise vorhanden waren.

Da GoogleCredential unveränderlich ist, erstellt CreateScoped eine neue Instanz mit den angegebenen Gültigkeitsbereichen.

Ordnen Sie Ihre Berechtigungsnachweisvariable mit dem Bereichsergebnis neu zu und es sollte funktionieren:

  if (_cred.IsCreateScopedRequired) {
    _cred = _cred.CreateScoped(AnalyticsService.Scope.Analytics);
  }

Die akzeptierte Antwort funktioniert, weil sie dasselbe auf eine schwierigere Weise erreicht. 

0
dlumpp

Eine weitere Option ist die Verwendung von GoogleCredential.GetApplicationDefault(). Ich glaube, dies ist der derzeit (Oktober 2018) empfohlene Ansatz. Hier einige F #, aber in der C # -Modulo-Syntax ist es mehr oder weniger gleich:

let projectId = "<your Google Cloud project ID...>"
let creds =
  GoogleCredential.GetApplicationDefault()
    .CreateScoped(["https://www.googleapis.com/auth/cloud-platform"])
use service =
  new CloudBuildService(
    BaseClientService.Initializer(HttpClientInitializer=creds))
let foo = service.Projects.Builds.List(projectId).Execute()

Stellen Sie nun sicher, dass Sie den GOOGLE_APPLICATION_CREDENTIALS so einstellen, dass er auf die Datei mit der JSON-Datei mit den Berechtigungsnachweisen verweist, z. GOOGLE_APPLICATION_CREDENTIALS=creds.json dotnet run.

0
skainswo