【问题标题】:Integrating with Google Admin SDK in C#在 C# 中与 Google Admin SDK 集成
【发布时间】:2019-09-20 03:37:26
【问题描述】:

我目前正在尝试通过 C# 与 Google Admin SDK 集成,以便我们可以通过自己的系统管理用户。但是,在运行项目时出现错误:未经授权的客户端。

我已经通过超级管理员帐户完成的事情:

这是我正在使用的代码。

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:“”

【问题讨论】:

    标签: c# google-api google-admin-sdk google-api-dotnet-client google-workspace


    【解决方案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 文件包含我从控制台获得的服务帐户凭据。不知道在哪里看,因为我已经根据我所看到的设置了所有内容
    猜你喜欢
    • 2016-04-02
    • 2011-12-13
    • 1970-01-01
    • 2022-10-18
    • 2014-02-17
    • 2016-09-28
    • 2021-06-12
    • 2012-03-12
    • 1970-01-01
    相关资源
    最近更新 更多