使用来自 C# 的 Google 目录 API 的身份验证错误
Authentication Error using Google Directory API from C#
我正在尝试调用 Google 应用程序目录 API,以便我可以将用户列出到我组织的 Google 应用程序帐户
我在他们的文档中搜索了几个小时,并得出了下面的代码。但是,我收到以下错误。 Invalid Credentials [401] 我怀疑这与我构造 ServiceAccountCredential
的方式有关
[STAThread]
static void Main(string[] args)
{
Console.WriteLine("Google Directory Service API");
Console.WriteLine("================================");
try
{
new Program().Run().Wait();
}
catch (AggregateException ex)
{
foreach (var e in ex.InnerExceptions)
{
Console.WriteLine("ERROR: " + e.Message);
}
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
private async Task Run()
{
using (var stream = new FileStream("../../client-secrets.json", FileMode.Open, FileAccess.Read))
using (var reader = new StreamReader(stream))
{
JObject clientJObject = JObject.Parse(reader.ReadToEnd());
var secrets = new ClientSecrets
{
ClientId = clientJObject.GetValue("client_id").ToString(),
ClientSecret = clientJObject.GetValue("private_key").ToString()
};
var tokenUrl = clientJObject.GetValue("token_uri").ToString();
var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(secrets.ClientId, tokenUrl).FromPrivateKey(secrets.ClientSecret));
var initializer = new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "My Directory Listing App",
};
var service = new DirectoryService(initializer);
var users = await service.Users.List().ExecuteAsync();
users.UsersValue.ToList().ForEach(u =>
{
Console.WriteLine(u.PrimaryEmail);
});
}
}
我的Secrets.Json文件有点像下面这样。我删除了大部分私钥部分
{
"type": "service_account",
"project_id": "service.account",
"private_key_id": "fd6f98b603dd5a065c87a8d34a4e428cf6277a35",
"private_key": "-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----\n",
"client_email": "service.account@appspot.gserviceaccount.com",
"client_id": "102588765356663060837",
"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/service.account%40appspot.gserviceaccount.com"
}
管理
第 1 步:登录管理控制台
第 2 步:确保 API 访问已启用 Security > Api Reference > Enable API Access
第 3 步:启用 Google 应用全域委派
- 前往 Dev Console
- Select API 项目
- 然后前往
Credentials > Manage Service Accounts > "Edit Service Account" > Enable Google Apps Domain-wide Delegation
"Go Back" > "View ClientID"
- 复制客户端 ID,因为您将需要它
第 4 步:注册 API 客户端和范围 Security > Advanced Settings > Manage API client access
- 输入客户端 ID 和以逗号分隔的范围列表(即 https://www.googleapis.com/auth/admin.directory.user)
- 然后
Authorize
第 5 步:创建服务帐户私钥
Create Credentials > Service Account Key > "Select Service Account" > P12 "For backward compatibility with code using the P12 format" > Close
- 这会自动将密钥代码下载到您的系统。保存此密钥,因为它非常重要
代码
首先你需要安装以下软件包
install-package Google.Apis.Admin.Directory.directory_v1
install-package Newtonsoft.Json
最后是下面的代码
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using System;
using System.Linq;
using Google.Apis.Admin.Directory.directory_v1;
using System.Security.Cryptography.X509Certificates;
namespace GoogleApis
{
/// <summary>
/// This sample demonstrates the simplest use case for a Service Account service.
/// The certificate needs to be downloaded from the Google Developers Console
/// <see cref="https://console.developers.google.com/">
/// "Create another client ID..." -> "Service Account" -> Download the certificate,
/// rename it as "key.p12" and add it to the project. Don't forget to change the Build action
/// to "Content" and the Copy to Output Directory to "Copy if newer".
/// </summary>
public class Program
{
public static void Main(string[] args)
{
//Service account Email
//NOTE: This is the account for the Service Client
string serviceAccountEmail = "service.account@appspot.gserviceaccount.com";
//Path to Downloaded Key
var path = @"Path\To\key.p12";
//Generate a Certificate using the Key downloaded from the Api Console
var certificate = new X509Certificate2(path, "notasecret", X509KeyStorageFlags.Exportable);
//Create the Credential
ServiceAccountCredential serviceCredential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
//Define the Scopes You want the credential to Access
Scopes = new[]
{
DirectoryService.Scope.AdminDirectoryUser,
},
//Specify the User that this service Credential is Impersonating. Typically your Google Apps Admin Account
User = "admin@domain.com"
}.FromCertificate(certificate));
//Instantiate the Service (Could be any of the Google Api Services)
var service = new DirectoryService(new BaseClientService.Initializer()
{
HttpClientInitializer = serviceCredential,
});
// Define parameters of request.
UsersResource.ListRequest request = service.Users.List();
//Set the Domain of the Request
request.Domain = "domain.com";
// List users.
var users = request.Execute().UsersValue;
users.Select(u => u.PrimaryEmail).ToList().ForEach(Console.WriteLine);
Console.ReadKey();
}
}
}
我正在尝试调用 Google 应用程序目录 API,以便我可以将用户列出到我组织的 Google 应用程序帐户
我在他们的文档中搜索了几个小时,并得出了下面的代码。但是,我收到以下错误。 Invalid Credentials [401] 我怀疑这与我构造 ServiceAccountCredential
的方式有关 [STAThread]
static void Main(string[] args)
{
Console.WriteLine("Google Directory Service API");
Console.WriteLine("================================");
try
{
new Program().Run().Wait();
}
catch (AggregateException ex)
{
foreach (var e in ex.InnerExceptions)
{
Console.WriteLine("ERROR: " + e.Message);
}
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
private async Task Run()
{
using (var stream = new FileStream("../../client-secrets.json", FileMode.Open, FileAccess.Read))
using (var reader = new StreamReader(stream))
{
JObject clientJObject = JObject.Parse(reader.ReadToEnd());
var secrets = new ClientSecrets
{
ClientId = clientJObject.GetValue("client_id").ToString(),
ClientSecret = clientJObject.GetValue("private_key").ToString()
};
var tokenUrl = clientJObject.GetValue("token_uri").ToString();
var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(secrets.ClientId, tokenUrl).FromPrivateKey(secrets.ClientSecret));
var initializer = new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "My Directory Listing App",
};
var service = new DirectoryService(initializer);
var users = await service.Users.List().ExecuteAsync();
users.UsersValue.ToList().ForEach(u =>
{
Console.WriteLine(u.PrimaryEmail);
});
}
}
我的Secrets.Json文件有点像下面这样。我删除了大部分私钥部分
{
"type": "service_account",
"project_id": "service.account",
"private_key_id": "fd6f98b603dd5a065c87a8d34a4e428cf6277a35",
"private_key": "-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----\n",
"client_email": "service.account@appspot.gserviceaccount.com",
"client_id": "102588765356663060837",
"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/service.account%40appspot.gserviceaccount.com"
}
管理
第 1 步:登录管理控制台
第 2 步:确保 API 访问已启用 Security > Api Reference > Enable API Access
第 3 步:启用 Google 应用全域委派
- 前往 Dev Console
- Select API 项目
- 然后前往
Credentials > Manage Service Accounts > "Edit Service Account" > Enable Google Apps Domain-wide Delegation
"Go Back" > "View ClientID"
- 复制客户端 ID,因为您将需要它
第 4 步:注册 API 客户端和范围 Security > Advanced Settings > Manage API client access
- 输入客户端 ID 和以逗号分隔的范围列表(即 https://www.googleapis.com/auth/admin.directory.user)
- 然后
Authorize
第 5 步:创建服务帐户私钥
Create Credentials > Service Account Key > "Select Service Account" > P12 "For backward compatibility with code using the P12 format" > Close
- 这会自动将密钥代码下载到您的系统。保存此密钥,因为它非常重要
代码
首先你需要安装以下软件包
install-package Google.Apis.Admin.Directory.directory_v1
install-package Newtonsoft.Json
最后是下面的代码
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using System;
using System.Linq;
using Google.Apis.Admin.Directory.directory_v1;
using System.Security.Cryptography.X509Certificates;
namespace GoogleApis
{
/// <summary>
/// This sample demonstrates the simplest use case for a Service Account service.
/// The certificate needs to be downloaded from the Google Developers Console
/// <see cref="https://console.developers.google.com/">
/// "Create another client ID..." -> "Service Account" -> Download the certificate,
/// rename it as "key.p12" and add it to the project. Don't forget to change the Build action
/// to "Content" and the Copy to Output Directory to "Copy if newer".
/// </summary>
public class Program
{
public static void Main(string[] args)
{
//Service account Email
//NOTE: This is the account for the Service Client
string serviceAccountEmail = "service.account@appspot.gserviceaccount.com";
//Path to Downloaded Key
var path = @"Path\To\key.p12";
//Generate a Certificate using the Key downloaded from the Api Console
var certificate = new X509Certificate2(path, "notasecret", X509KeyStorageFlags.Exportable);
//Create the Credential
ServiceAccountCredential serviceCredential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
//Define the Scopes You want the credential to Access
Scopes = new[]
{
DirectoryService.Scope.AdminDirectoryUser,
},
//Specify the User that this service Credential is Impersonating. Typically your Google Apps Admin Account
User = "admin@domain.com"
}.FromCertificate(certificate));
//Instantiate the Service (Could be any of the Google Api Services)
var service = new DirectoryService(new BaseClientService.Initializer()
{
HttpClientInitializer = serviceCredential,
});
// Define parameters of request.
UsersResource.ListRequest request = service.Users.List();
//Set the Domain of the Request
request.Domain = "domain.com";
// List users.
var users = request.Execute().UsersValue;
users.Select(u => u.PrimaryEmail).ToList().ForEach(Console.WriteLine);
Console.ReadKey();
}
}
}