我是Google Apps域的管理员,正在尝试编写一个程序来访问域中用户的联系人(请注意,我不是要获取共享联系人,而是要获取每个用户的个人联系人,因此共享联系人API将无济于事)。
最初,我使用的是三足身份验证的"推荐"方法(显示网页,用户批准,使用该令牌)。 这很好用,除非我尝试除自己以外的任何用户,否则我会收到 403 禁止错误。 所以后来我读到在这种情况下我想要两条腿的身份验证,尽管它已被弃用。
好吧,我想出了这个代码,但现在我得到了一个 401/未经授权的凭据。 我不确定问题出在我的代码还是其他地方(我注册应用程序的方式或其他东西),但我很难找到有用的文档。
public static Feed<Contact> MakeRequest(string userId, int numberToRetrieve = 9999)
{
var settings = new RequestSettings(Properties.Settings.Default.ApplicationName,
Properties.Settings.Default.ApiKey, Properties.Settings.Default.ConsumerSecret,
Properties.Settings.Default.GoogleUserName, Properties.Settings.Default.Domain);
var cRequest = new ContactsRequest(settings);
var query = new ContactsQuery(ContactsQuery.CreateContactsUri(userId));
query.NumberToRetrieve = numberToRetrieve;
return cRequest.Get(query);
}
对于 3 条腿的 OAuth,它仅在用户通过 OAuth 握手专门进行身份验证时才有效。 如果要代表所有用户进行呼叫,则需要使用 OAuth 2.0 的服务帐户。
查看驱动器 API 代码示例,它将为您提供一些如何开始使用 OAuth 2.0 和服务帐户的想法。
https://developers.google.com/drive/service-accounts#use_service_accounts_as_application-owned_accounts
如果您使用的是 OAuth 1.0,则需要使用特殊参数 xoauth_requestor_id。 以下是有关它的更多信息:
https://developers.google.com/accounts/docs/OAuth#GoogleAppsOAuth
好吧,我终于想通了。 我觉得这可能不是它应该工作的方式,我不得不挖掘ServiceAccountCredential的源代码,但它有效。 我实际上已经分开了一点,但为了清楚起见,这里完全是。
我也从Google.Apis.Authentication切换到Google.Apis.Auth。
public static Feed<Contact> MakeRequest(string userId, int numberToRetrieve = 9999)
{
var serviceCredential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(ServiceEmail)
{
Scopes = new[] { @"https://www.google.com/m8/feeds/" },
User = userId,
}.FromCertificate(Certificate));
var reqAccessTokenInfo = serviceCredential.GetType()
.GetMethod("RequestAccessToken", BindingFlags.Instance | BindingFlags.NonPublic);
var task = (Task<bool>) reqAccessTokenInfo.Invoke(serviceCredential, parameters: new object[] {new CancellationToken()});
task.Wait();
var settings = new RequestSettings(Properties.Settings.Default.ApplicationName, serviceCredential.Token.AccessToken);
var cRequest = new ContactsRequest(settings);
var query = new ContactsQuery(ContactsQuery.CreateContactsUri(userId)) { NumberToRetrieve = numberToRetrieve };
return cRequest.Get<Contact>(query);
}