私は、C#、Google API、およびGoogle Analyticsで動作する簡単なサービスアカウントログインを取得しようとして、血まみれになっています。私の会社はすでにアナリティクスにデータを取得しており、Query Explorerで情報をクエリできますが、.Netで始めるのはどこにも行きません。ドキュメントでは、そのようなサービスアカウントがGoogla APIとのコンピューター間通信に適した方法であると述べているため、PKIでGoogleが生成したjsonファイルを使用しています。コードスニペット:
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
エラーがスローされます。
[無効な資格情報]場所[承認-ヘッダー]理由[authError]ドメイン[グローバル]
不足しているものは何ですか?
GoogleAnalyticsはジェネリックGoogleCredential
を消費してServiceAccountCredential
として解釈することはできないようです(実際にはそのタイプの)。したがって、ServiceAccountCredential
を作成する必要があります。 GoogleCredential
がクレデンシャルのさまざまなプロパティを公開しないことも残念なため、独自に作成する必要がありました。
JSON C#Class Generatorを http://jsonclassgenerator.codeplex.com/ で使用して、Google APIの自動部分であるJSONライブラリを使用して「パーソナル」ServiceAccountCredentialオブジェクトを構築しました(Newtonsoft.Json)、サービスアカウントのダウンロードされたjsonファイルの重要な部分を取得し、その電子メールと秘密キーのプロパティを使用して、必要な資格情報を構築しました。正規のServiceAccountCredential
をGoogleAnalyticsサービスコンストラクターに渡すと、ログインが成功し、そのアカウントの許可されたリソースにアクセスできます。
以下の作業コードのサンプル:
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();
PKI(Private Key)を使用してGoogleが生成したサービスアカウント資格情報がどのようなものか疑問に思うかもしれません。 https://console.developers.google.com/iam-admin/projects のGoogle API Manager(IAMおよび管理者)から、適切なプロジェクトを選択します(これらの少なくとも1つがあります)。次に、サービスアカウント(左のナビゲーションリンクから)、およびCREATE SERVICE ACCOUNT画面の上部。名前を入力し、新しい秘密キーを入力するチェックボックスを設定して、作成。 Googleは、次のようなJSONファイルの自動ダウンロードを引き起こします。
{
"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"
}
指定したスコープが実際に資格情報で送信されていないため、無効な資格情報エラーが発生しています。私は同じ間違いを犯しましたが、デバッグ後に初めて気づきましたが、CreateScoped
呼び出し後も資格情報に0のスコープが表示されました。
GoogleCredential
は不変なので、CreateScoped
は指定されたスコープセットで新しいインスタンスを作成します。
そのようにスコープされた結果で資格情報変数を再割り当てし、それが機能するはずです:
if (_cred.IsCreateScopedRequired) {
_cred = _cred.CreateScoped(AnalyticsService.Scope.Analytics);
}
受け入れられた答えは、同じことをより困難な方法で達成しているために機能します。
別のオプションは、GoogleCredential.GetApplicationDefault()
を使用することです。これは現在(2018年10月)推奨されているアプローチだと思います。以下にいくつかのF#を示しますが、C#モジュロ構文でもほぼ同じです。
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()
ここで、GOOGLE_APPLICATION_CREDENTIALS
クレデンシャルJSONファイルを含むファイルを指す、たとえば。 GOOGLE_APPLICATION_CREDENTIALS=creds.json dotnet run
。