C# Google将OAuth2与服务帐户协调

C# Google将OAuth2与服务帐户协调,c#,.net,google-api,google-oauth,google-api-dotnet-client,C#,.net,Google Api,Google Oauth,Google Api Dotnet Client,我有一个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

我有一个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();
    ...
}
我读过一些文章,建议更改本地服务器时间,以便与谷歌誓言服务器时间相匹配。但在把时间移到一边和另一边之后,问题仍然是一样的。 你能告诉我为什么会这样吗?
谢谢大家的回复

服务帐户不能与坐标API一起使用。[这是因为坐标API要求经过身份验证的API用户拥有坐标许可证,但无法将坐标许可证附加到服务帐户]

您可以改为使用web服务器流,请查找下面的示例

确保更新下面的代码,其中有包含“要更新”的注释

使用系统;
使用系统诊断;
使用System.Collections.Generic;
使用DotNetOpenAuth.OAuth2;
使用Google.api.Authentication.OAuth2;
使用Google.api.Authentication.OAuth2.DotNetOpenAuth;
使用Google.api.Coordinate.v1;
使用Google.api.Coordinate.v1.Data;
名称空间Google.api.Samples.CoordinationAuth2
{ 
///  
///此示例演示了OAuth2服务的最简单用例。
///这里提供的模式可以应用于每个需要身份验证的请求。
///  
公共类程序Web服务器
{ 
公共静态void Main(字符串[]args)
{ 
//要更新,可在坐标应用程序URL中找到
String TEAM_ID=“jskdQ--xKjFiFqLO-IpIlg”;
//注册验证器。
var provider=新的WebServerClient(GoogleAuthenticationServer.Description);
//要更新,可以在API控制台中找到。
provider.ClientIdentifier=“335858260352.apps.googleusercontent.com”;
//要更新,可以在API控制台中找到。
provider.ClientSecret=“yAMx sR[trunched]fX9ghtPRI”;
var auth=新的OAuth2Authenticator(提供者,GetAuthorization);
//创建服务。
var service=new CoordinateService(new BaseClientService.Initializer()
{
验证器=auth
});
//为可选参数创建作业资源https://developers.google.com/coordinate/v1/jobs#resource 
Job jobBody=新作业();
jobBody.Kind=“坐标#作业”;
State=newjobstate();
jobBody.State.Kind=“坐标#作业状态”;
jobBody.State.Assignee=”user@example.com"; 
//创建作业
JobsResource.InsertRequest ins=service.Jobs.Insert(jobBody,团队ID,“我家”,“51”,“0”,“使用.Net客户端库创建此作业”);
作业结果=ins.Fetch();
//显示响应
Console.WriteLine(“作业ID:”);
Console.WriteLine(results.Id.ToString());
Console.WriteLine(“按任意键继续”);
Console.ReadKey();
}
私有静态IAAuthorizationState GetAuthorization(WebServerClient客户端)
{ 
IAAuthorizationState=新授权状态(新[]{”https://www.googleapis.com/auth/coordinate" }); 
//已脱机检索刷新令牌
//在实际应用程序中,必须安全地存储该令牌,因为该令牌
//允许接受OAuth2流的用户访问坐标范围内的所有用户数据
//更新(有关说明,请参见下面的示例)
state.RefreshToken=“1/0KuRg-fh9yO[截断]yNVQcXcVYlfXg”;
返回状态;
} 
} 
}
可以使用OAuth2检索刷新令牌:

  • 在API控制台中,添加OAuth操场URL作为授权URL 重定向URI(当我们在 OAuth游乐场(下图)
  • 转到OAuth游乐场,在已验证API用户身份的浏览器会话中(该用户需要有坐标许可证)确保提供 您拥有OAuth2客户端ID(设置>使用您自己的OAuth凭据)。 否则,您的刷新令牌将绑定到OAuth2游乐场的 内部OAuth2客户端ID,当您要使用时将被拒绝 使用您自己的客户端ID刷新令牌以获取访问令牌
  • 使用步骤1中的范围, 在步骤2中点击“授权API”,点击“交换授权代码” “代币”
  • 复制代码中的刷新令牌。保持安全
  • 此刷新令牌不会过期,因此您的应用程序将保持身份验证

服务帐户不能与坐标API一起使用。[这是因为坐标API要求经过身份验证的API用户拥有坐标许可证,但无法将坐标许可证附加到服务帐户]

您可以改为使用web服务器流,请查找下面的示例

确保更新下面的代码,其中有包含“要更新”的注释

使用系统;
使用系统诊断;
使用System.Collections.Generic;
使用DotNetOpenAuth.OAuth2;
使用Google.api.Authentication.OAuth2;
使用Google.api.Authentication.OAuth2.DotNetOpenAuth;
使用Google.api.Coordinate.v1;
使用Google.api.Coordinate.v1.Data;
名称空间Google.api.Samples.CoordinationAuth2
{ 
///  
///此示例演示了OAuth2服务的最简单用例。
///这里提供的模式可以应用于每个需要身份验证的请求。
///  
公共类程序Web服务器
{ 
公共静态void Main(字符串[]args)
{ 
//要更新,可在坐标应用程序URL中找到
String TEAM_ID=“jskdQ--xKjFiFqLO-IpIlg”;
//注册验证器。
{
  "error" : "invalid_grant"
}
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;
        } 

    } 
}