Google+ API:我如何使用RefreshTokens来避免每次应用程序启动时请求访问
本文关键字:应用程序 启动 访问 请求 API 何使用 RefreshTokens Google+ | 更新日期: 2023-09-27 18:08:57
我试图使用Google+ API来访问经过身份验证的用户的信息。我已经从一个示例中复制了一些代码,它工作得很好(如下),但是我在使它能够在应用程序启动时重用令牌的方式上遇到了麻烦。
我尝试捕获"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<NativeApplicationClient>(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的字符串设置和引用系统。安全性或寻找另一种安全存储刷新令牌的方法。
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();
}
总体思路如下:
-
将用户重定向到Google的授权端点。
-
您将获得一个短期授权码。
-
您立即使用Google的令牌端点交换长期访问令牌的授权码。访问令牌带有到期日期和刷新令牌。
-
使用Access Token向Google的API发出请求。
您可以为任意多的请求重用访问令牌,直到它过期。然后你可以使用刷新令牌来请求一个新的访问令牌(它带有一个新的到期日期和一个新的刷新令牌)。
参见:
- OAuth 2.0授权协议
- Google OAuth 2.0文档
我也有问题获得"离线"身份验证工作(即获取身份验证与刷新令牌),并获得http -响应400 Bad request
与代码类似的OP的代码。但是,我让它与Authenticate
-方法中的client.ClientCredentialApplicator = ClientCredentialApplicator.PostParameter(this.clientSecret);
行一起工作。这是必需的以获得工作代码——我认为这一行强制将clientSecret作为post参数发送到服务器(而不是作为HTTP基本auth参数)。
此解决方案假设您已经获得了客户端ID、客户端秘密和刷新令牌。注意,您不需要在代码中输入访问令牌。(当发送带有client.RefreshAuthorization(state);
行的长寿命刷新令牌时,从Google服务器"在底层"获取短寿命访问代码。这个访问令牌作为auth
变量的一部分存储,从那里它被用于授权"底层"的api调用。
一个代码示例,为我工作与谷歌API v3访问我的谷歌日历:
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<NativeApplicationClient> auth = new OAuth2Authenticator<NativeApplicationClient>(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版本实现了与Google当前实现的OAuth 2.0不同的草案。这两部分都不是"正确的",因为规范还没有最终确定,但它使兼容性成为一场噩梦。
你可以检查你正在使用的DotNetOpenAuth版本是最新的(如果有帮助,它可能),但最终你可能需要坐等规范最终确定,每个人都正确地实现它们,或者你自己阅读谷歌文档(大概描述了他们的OAuth 2.0版本),并实现一个专门针对他们的草案版本。
我建议您查看Google .NET客户端API示例解决方案中的"SampleHelper"项目:
- 样品/SampleHelper AuthorizationMgr.cs
这个文件展示了如何使用Windows保护数据来存储刷新令牌,它还展示了如何使用本地环回服务器和不同的技术来捕获访问代码,而不是让用户手动输入。
库中使用这种授权方法的示例如下:
- 样品/Tasks.CreateTasks Program.cs