在 C# 中与 Google Admin SDK 集成
Posted
技术标签:
【中文标题】在 C# 中与 Google Admin SDK 集成【英文标题】:Integrating with Google Admin SDK in C# 【发布时间】:2019-09-20 03:37:26 【问题描述】:我目前正在尝试通过 C# 与 Google Admin SDK 集成,以便我们可以通过自己的系统管理用户。但是,在运行项目时出现错误:未经授权的客户端。
我已经通过超级管理员帐户完成的事情:
设置服务帐号 在服务帐户上启用 GSuite 域范围委派 启用 API 访问 将服务帐户客户端 ID 添加到具有范围 (https://www.googleapis.com/auth/admin.directory.user) 的 API 客户端访问中这是我正在使用的代码。
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(_googleServiceSettings.Client_Email)
ProjectId = _googleServiceSettings.Project_Id,
User = "superadmin@google.com",
Scopes = new[] DirectoryService.Scope.AdminDirectoryUser
.FromPrivateKey(_googleServiceSettings.Private_Key));
var service = new DirectoryService(new BaseClientService.Initializer
HttpClientInitializer = credential,
ApplicationName = "Test API"
);
var request = service.Users.Get("user@google.com");
var result = await request.ExecuteAsync();
我得到的完整错误是
执行请求时发生未处理的异常。 Google.Apis.Auth.OAuth2.Responses.TokenResponseException:错误:“unauthorized_client”,描述:“客户端未授权使用此方法检索访问令牌,或客户端未授权任何请求的范围。”,Uri:“”
【问题讨论】:
【参考方案1】:好的,我已经解决了这个问题。
通过 Google 门户中的安全设置添加以下范围已解决了该问题。这很奇怪,因为他们自己的示例不需要添加此范围,并且他们的文档没有说明此方法需要它。
https://www.googleapis.com/auth/admin.directory.group
【讨论】:
我的示例 + G Suite 不使用group
范围。你还有其他事情需要group
。这个用户有什么不同吗?
@JohnHanley - 据我所知,我试图获取的超级管理员或用户没有什么特别之处。我们有多个超级管理员,在他们之间切换没有效果。这同样适用于我正在获取的用户。
我问的是您在 G Suite 中调用“Get()”的用户。例如,此用户是否是某个组的成员?您可以创建一个新用户然后重试吗?除非我故意尝试创建错误,否则我的代码没有问题。但是,我通常会给出所有范围,因此我不必担心委派权限的细节,因为调用者无论如何都必须拥有超级管理员权限。
所以我试图获取的用户与组相关联并且是委派管理员
我在这个问题上花了很多时间。我无法使用需要https://www.googleapis.com/auth/admin.directory.group
的组、权限等在 G Suite 中创建配置。您遗漏了一些有助于确定为什么需要group
的细节。需要它的一个示例是 List() 用户。【参考方案2】:
如果您想使用服务帐户,您可以使用以下代码进行身份验证。
String serviceAccountEmail = "yourserviceaccountmail";
public GmailService GetService(string user_email_address)
var certificate = new X509Certificate2(@"yourkeyfile.p12",
"notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
User = user_email_address,
Scopes = new[] GmailService.Scope.MailGoogleCom
.FromCertificate(certificate));
GmailService service = new GmailService(new BaseClientService.Initializer()
HttpClientInitializer = credential,
ApplicationName = AppName,
);
return service;
您可以列出使用此服务的用户。它为我工作。
您可以使用以下代码列出用户列表。 (使用 DirectoryService)
public Users GetDirService()//UserList with DirectoryService
string Admin_Email = "yoursuperadminemail";
string domain = "yourdomain.com";
try
var certificate = new X509Certificate2(@"yourkeyfile.p12", "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credentialUsers = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
Scopes = new[] DirectoryService.Scope.AdminDirectoryUser ,
User = Admin_Email,
.FromCertificate(certificate));
var serviceUsers = new DirectoryService(new BaseClientService.Initializer()
HttpClientInitializer = credentialUsers,
ApplicationName = AppName,
);
var listReq = serviceUsers.Users.List();
listReq.Domain = domain;
Users users = listReq.Execute();
return users;
catch (Exception ex)
MessageBox.Show("your mail address must be super admin authorized.", "Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
return null;
【讨论】:
你能用一个完整的例子改进你的答案吗? 我已经测试了您的示例,但仍然遇到相同的错误。感觉好像我错过了一个设置,但一切看起来都正确设置 也许吧。我在我的项目中使用了这段代码,它显然是有效的。 @Muammer 您能解释一下您在 Google 门户中采取了哪些步骤吗?我已经在我的原始帖子中列出了我已经做过的事情。你做过我没做过的事吗? @niko619 您需要将域范围的权限委托给您的服务帐户。检查here 并转到将域范围的权限委托给您的服务帐户步骤。【参考方案3】:将打印有关用户的一些信息的示例代码。
重要的是类Google.Apis.Admin.Directory.directory_v1.Data.User
文档link。
您的错误是由于未正确创建凭据造成的。通常,创建凭据时范围存在问题。我假设您为服务帐户正确设置了域范围委派。
我还假设您冒充的用户是 G Suite 超级管理员。如果没有,您将看到 service.Users.Get()
的 403 错误。
文件service_account.json
是您从 Google 控制台下载(或使用 gcloud 创建)的普通 JSON 文件。
user1@example.com
用户是将显示其信息的 G Suite 用户的电子邮件地址。
用户 admin@example.com
是 G Suite 超级管理员。
using Google.Apis.Auth.OAuth2;
using Google.Apis.Admin.Directory.directory_v1;
using Google.Apis.Admin.Directory.directory_v1.Data;
using Google.Apis.Services;
using System;
using System.IO;
// dotnet add package Google.Apis.Admin.Directory.directory_v1
// Tested with version 1.39.0.1505
// Google.Apis.Admin.Directory.directory_v1.Data.User
// https://developers.google.com/resources/api-libraries/documentation/admin/directory_v1/csharp/latest/classGoogle_1_1Apis_1_1Admin_1_1Directory_1_1directory__v1_1_1Data_1_1User.html
namespace Example
class Program
static void Main(string[] args)
// Service Account with Domain-Wide delegation
var sa_file = "service_account.json";
// G Suite User to impersonate
var user_email = "admin@example.com";
// G Suite User to get information about
var gs_email = "user1@example.com";
// Scopes
var scopes = "https://www.googleapis.com/auth/admin.directory.user";
var credential = GoogleCredential.FromFile(sa_file)
.CreateScoped(scopes)
.CreateWithUser(user_email);
// Create Directory API service.
var service = new DirectoryService(new BaseClientService.Initializer()
HttpClientInitializer = credential
);
try
var request = service.Users.Get(gs_email);
var result = request.Execute();
Console.WriteLine("Full Name: 0", result.Name.FullName);
Console.WriteLine("Email: 0", result.PrimaryEmail);
Console.WriteLine("ID: 0", result.Id);
Console.WriteLine("Is Admin: 0", result.IsAdmin);
catch
Console.WriteLine("User not found.");
【讨论】:
我采用了您的示例,但仍然收到相同的消息。 user_email 设置为我们的超级管理员电子邮件。 JSON 文件包含我从控制台获得的服务帐户凭据。不知道在哪里看,因为我已经根据我所看到的设置了所有内容以上是关于在 C# 中与 Google Admin SDK 集成的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 JWT 通过 NodeJS 客户端库访问 Google Directory (Admin SDK)?
将 Firebase Admin SDK 添加到 Unity 项目