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);
    }
}

Google+ API:我如何使用RefreshTokens来避免每次应用程序启动时请求访问

下面是一个例子。确保您添加了一个名为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();
    }

总体思路如下:

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

  2. 您将获得一个短期授权码。

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

  4. 使用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