Google+ API:如何在每次启动应用时使用RefreshTokens来避免请求访问权限?

我正在尝试使用Google+ API访问经过身份validation的用户的信息。 我从其中一个示例中复制了一些代码,这样可以正常工作(下图),但是我无法使其在我可以跨应用程序启动重用令牌的方式工作。

我尝试捕获“RefreshToken”属性并使用provider.RefreshToken() (以及其他内容)并始终获得400 Bad Request响应。

有谁知道如何使这项工作,或知道我在哪里可以找到一些样品? 谷歌代码网站似乎没有涵盖这个:-(

 class Program { private const string Scope = "https://www.googleapis.com/auth/plus.me"; static void Main(string[] args) { var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description); provider.ClientIdentifier = "BLAH"; provider.ClientSecret = "BLAH"; var auth = new OAuth2Authenticator(provider, GetAuthentication); var plus = new PlusService(auth); plus.Key = "BLAH"; var me = plus.People.Get("me").Fetch(); Console.WriteLine(me.DisplayName); } private static IAuthorizationState GetAuthentication(NativeApplicationClient arg) { // Get the auth URL: IAuthorizationState state = new AuthorizationState(new[] { Scope }); state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl); Uri authUri = arg.RequestUserAuthorization(state); // Request authorization from the user (by opening a browser window): Process.Start(authUri.ToString()); Console.Write(" Authorization Code: "); string authCode = Console.ReadLine(); Console.WriteLine(); // Retrieve the access token by using the authorization code: return arg.ProcessUserAuthorization(authCode, state); } } 

这是一个例子。 确保添加名为RefreshToken的字符串设置并引用System.Security或找到另一种安全存储刷新令牌的方法。

  private static byte[] aditionalEntropy = { 1, 2, 3, 4, 5 }; private static IAuthorizationState GetAuthorization(NativeApplicationClient arg) { // Get the auth URL: IAuthorizationState state = new AuthorizationState(new[] { PlusService.Scopes.PlusMe.GetStringValue() }); state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl); string refreshToken = LoadRefreshToken(); if (!String.IsNullOrWhiteSpace(refreshToken)) { state.RefreshToken = refreshToken; if (arg.RefreshToken(state)) return state; } Uri authUri = arg.RequestUserAuthorization(state); // Request authorization from the user (by opening a browser window): Process.Start(authUri.ToString()); Console.Write(" Authorization Code: "); string authCode = Console.ReadLine(); Console.WriteLine(); // Retrieve the access token by using the authorization code: var result = arg.ProcessUserAuthorization(authCode, state); StoreRefreshToken(state); return result; } private static string LoadRefreshToken() { return Encoding.Unicode.GetString(ProtectedData.Unprotect(Convert.FromBase64String(Properties.Settings.Default.RefreshToken), aditionalEntropy, DataProtectionScope.CurrentUser)); } private static void StoreRefreshToken(IAuthorizationState state) { Properties.Settings.Default.RefreshToken = Convert.ToBase64String(ProtectedData.Protect(Encoding.Unicode.GetBytes(state.RefreshToken), aditionalEntropy, DataProtectionScope.CurrentUser)); Properties.Settings.Default.Save(); } 

总体思路如下:

  1. 您将用户重定向到Google的授权端点。

  2. 您获得了一个短命的授权码。

  3. 您可以使用Google的令牌端点立即与长期访问令牌交换授权码。 访问令牌附带有效日期和刷新令牌。

  4. 您使用访问令牌向Google的API发出请求。

您可以根据需要重复使用访问令牌,直到它过期为止。 然后,您可以使用刷新令牌来请求新的访问令牌(带有新的到期日期和新的刷新令牌)。

也可以看看:

  • OAuth 2.0授权协议
  • Google的OAuth 2.0文档

我也遇到了使“离线”身份validation工作的问题(即使用刷新令牌获取身份validation),并获得了HTTP响应400 Bad request ,其代码类似于OP的代码。 但是, 我让它使用行client.ClientCredentialApplicator = ClientCredentialApplicator.PostParameter(this.clientSecret);Authenticate -method中。 这对于获取正常工作的代码至关重要 – 我认为这一行迫使clientSecret作为POST参数发送到服务器(而不是作为HTTP Basic Auth参数)。

此解决方案假定您已经拥有客户端ID,客户端密钥和刷新令牌。 请注意,您无需在代码中输入访问令牌。 (当使用行client.RefreshAuthorization(state);发送长期刷新令牌时,从Google服务器“获取”短期访问代码。此访问令牌作为auth一部分存储-variable,用于在“引擎盖下”授权API调用。)

使用Google API v3访问我的Google日历的代码示例:

 class SomeClass { private string clientID = "XXXXXXXXX.apps.googleusercontent.com"; private string clientSecret = "MY_CLIENT_SECRET"; private string refreshToken = "MY_REFRESH_TOKEN"; private string primaryCal = "MY_GMAIL_ADDRESS"; private void button2_Click_1(object sender, EventArgs e) { try { NativeApplicationClient client = new NativeApplicationClient(GoogleAuthenticationServer.Description, this.clientID, this.clientSecret); OAuth2Authenticator auth = new OAuth2Authenticator(client, Authenticate); // Authenticated and ready for API calls... // EITHER Calendar API calls (tested): CalendarService cal = new CalendarService(auth); EventsResource.ListRequest listrequest = cal.Events.List(this.primaryCal); Google.Apis.Calendar.v3.Data.Events events = listrequest.Fetch(); // iterate the events and show them here. // OR Plus API calls (not tested) - copied from OP's code: var plus = new PlusService(auth); plus.Key = "BLAH"; // don't know what this line does. var me = plus.People.Get("me").Fetch(); Console.WriteLine(me.DisplayName); // OR some other API calls... } catch (Exception ex) { Console.WriteLine("Error while communicating with Google servers. Try again(?). The error was:\r\n" + ex.Message + "\r\n\r\nInner exception:\r\n" + ex.InnerException.Message); } } private IAuthorizationState Authenticate(NativeApplicationClient client) { IAuthorizationState state = new AuthorizationState(new string[] { }) { RefreshToken = this.refreshToken }; // IMPORTANT - does not work without: client.ClientCredentialApplicator = ClientCredentialApplicator.PostParameter(this.clientSecret); client.RefreshAuthorization(state); return state; } } 

OAuth 2.0规范尚未完成,并且各种客户端和服务之间存在一些规范实现,导致出现这些错误。 很可能你正在做的一切正确,但你使用的DotNetOpenAuth版本实现了与谷歌目前正在实施的不同的OAuth 2.0草案。 这两个部分都没有“正确”,因为规范尚未最终确定,但它使兼容性成为一场噩梦。

您可以检查您使用的DotNetOpenAuth版本是否为最新版本(如果有帮助, 可能会这样 ),但最终您可能需要坐下来直到规范最终确定并且每个人都正确实现它们,或者阅读Google文档你自己(可能描述了他们的OAuth 2.0版本)并实现了一个专门针对他们的草稿版本的版本。

我建议在Google .NET Client API的Samples解决方案中查看“SampleHelper”项目:

  • 样品/ SampleHelper / AuthorizationMgr.cs

此文件显示了如何使用Windows受保护数据存储刷新令牌,还显示了如何使用本地环回服务器和不同技术捕获Access代码,而不是让用户手动输入。

使用这种授权方法的库中的一个样本可以在下面找到:

  • 样品/ Tasks.CreateTasks / Program.cs中