我有一个带有Google Coordinate .Net library和服务帐户开放身份验证的C#控制台应用程序。
private const string SERVICE_ACCOUNT_EMAIL = "XXX@developer.gserviceaccount.com";
private const string SERVICE_ACCOUNT_PKCS12_FILE_PATH = @"<path-to-private-key-file>\YYY-privatekey.p12";
private const string GOOGLE_COORDINATE_TEAM_ID = "ZZZ";
private CoordinateService BuildService()
{
X509Certificate2 certificate = new X509Certificate2(SERVICE_ACCOUNT_PKCS12_FILE_PATH, "notasecret", X509KeyStorageFlags.Exportable);
var provider = new AssertionFlowClient(GoogleAuthenticationServer.Description, certificate){
ServiceAccountId = SERVICE_ACCOUNT_EMAIL,
Scope = CoordinateService.Scopes.Coordinate.GetStringValue()
};
var auth = new OAuth2Authenticator<AssertionFlowClient>(provider, AssertionFlowClient.GetState);
return new CoordinateService(new BaseClientService.Initializer(){
Authenticator = auth
});
}
//some code that retrieves data from coordinate service
public void DoSomething()
{
CoordinateService service = BuildService();
var response = service.Jobs.List(GOOGLE_COORDINATE_TEAM_ID).Fetch();
...
}
在从Coordinate Service检索作业列表时,发生了DotNetOpenAuth.Messaging.ProtocolException(内部异常“远程服务器返回错误:(400)错误请求”)。使用Fiddler我设法看到来自Google OAuth服务的回复。 JSON响应对象:
{
"error" : "invalid_grant"
}
我已阅读一些建议更改本地服务器时间以与Google OAth服务器时间匹配的文章。但是在将时间改为一方和另一方后,问题仍然存在。 你能告诉我为什么会这样吗? 感谢所有回复!
答案 0 :(得分:1)
服务帐户不能与Coordinate API一起使用。 [这是因为Coordinate API要求经过身份验证的API用户拥有Coordinate许可证,但无法将Coordinate许可证附加到服务帐户]
您可以使用网络服务器流程,请参阅下面的示例。
请务必更新以下代码,其中包含“TO UPDATE”的评论。
using System;
using System.Diagnostics;
using System.Collections.Generic;
using DotNetOpenAuth.OAuth2;
using Google.Apis.Authentication.OAuth2;
using Google.Apis.Authentication.OAuth2.DotNetOpenAuth;
using Google.Apis.Coordinate.v1;
using Google.Apis.Coordinate.v1.Data;
namespace Google.Apis.Samples.CoordinateOAuth2
{
/// <summary>
/// This sample demonstrates the simplest use case for an OAuth2 service.
/// The schema provided here can be applied to every request requiring authentication.
/// </summary>
public class ProgramWebServer
{
public static void Main (string[] args)
{
// TO UPDATE, can be found in the Coordinate application URL
String TEAM_ID = "jskdQ--xKjFiFqLO-IpIlg";
// Register the authenticator.
var provider = new WebServerClient (GoogleAuthenticationServer.Description);
// TO UPDATE, can be found in the APIs Console.
provider.ClientIdentifier = "335858260352.apps.googleusercontent.com";
// TO UPDATE, can be found in the APIs Console.
provider.ClientSecret = "yAMx-sR[truncated]fX9ghtPRI";
var auth = new OAuth2Authenticator<WebServerClient> (provider, GetAuthorization);
// Create the service.
var service = new CoordinateService(new BaseClientService.Initializer()
{
Authenticator = auth
});
//Create a Job Resource for optional parameters https://developers.google.com/coordinate/v1/jobs#resource
Job jobBody = new Job ();
jobBody.Kind = "Coordinate#job";
jobBody.State = new JobState ();
jobBody.State.Kind = "coordinate#jobState";
jobBody.State.Assignee = "user@example.com";
//Create the Job
JobsResource.InsertRequest ins = service.Jobs.Insert (jobBody, TEAM_ID, "My Home", "51", "0", "Created this Job with the .Net Client Library");
Job results = ins.Fetch ();
//Display the response
Console.WriteLine ("Job ID:");
Console.WriteLine (results.Id.ToString ());
Console.WriteLine ("Press any Key to Continue");
Console.ReadKey ();
}
private static IAuthorizationState GetAuthorization (WebServerClient client)
{
IAuthorizationState state = new AuthorizationState (new[] { "https://www.googleapis.com/auth/coordinate" });
// The refresh token has already been retrieved offline
// In a real-world application, this has to be stored securely, since this token
// gives access to all user data on the Coordinate scope, for the user who accepted the OAuth2 flow
// TO UPDATE (see below the sample for instructions)
state.RefreshToken = "1/0KuRg-fh9yO[truncated]yNVQcXcVYlfXg";
return state;
}
}
}
可以使用OAuth2 Playground检索刷新令牌: