【问题标题】:Authentication Error using Google Directory API from C#使用来自 C# 的 Google Directory API 的身份验证错误
【发布时间】:2016-04-26 11:59:36
【问题描述】:

我正在尝试调用 Google Apps Directory API,以便将用户列出到我单位的 Google Apps 帐户中

我已经通过他们的文档搜索了几个小时,并且能够想出下面的代码。但是,我收到以下错误。 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"
}

【问题讨论】:

    标签: c# authentication google-api-dotnet-client


    【解决方案1】:

    管理

    第 1 步:登录管理控制台

    第 2 步:确保启用 API 访问 Security > Api Reference > Enable API Access

    第 3 步:启用 Google Apps 域范围委派

    • 前往Dev Console
    • 选择 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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-24
      • 2011-03-05
      • 1970-01-01
      • 2018-05-28
      • 1970-01-01
      • 2019-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多