Подтвердить что ты не робот

API Google+: как я могу использовать RefreshTokens, чтобы избежать запроса доступа каждый раз, когда запускается мое приложение?

Я пытаюсь использовать API Google+ для доступа к информации для аутентифицированного пользователя. Я скопировал код из одного из образцов, который отлично работает (ниже), однако у меня возникают проблемы с его работой, чтобы я мог повторно использовать токен в приложениях.

Я попытался захватить свойство RefreshToken и использовать provider.RefreshToken() (между прочим) и всегда получать ответ 400 Bad Request.

Кто-нибудь знает, как сделать эту работу, или знать, где я могу найти образцы? сайт Google Code, похоже, не охватывает этого: - (

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

Ответ 1

Вот пример. Убедитесь, что вы добавили строковый параметр 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();
    }

Ответ 2

Общая идея такова:

  • Вы перенаправляете пользователя на конечную точку авторизации Google.

  • Вы получаете недолгий код авторизации.

  • Вы немедленно обмениваете код авторизации для долгоживущего токена доступа с помощью конечной точки Google Token. Токен доступа имеет дату истечения срока действия и токен обновления.

  • Вы делаете запросы в Google API с помощью токена доступа.

Вы можете повторно использовать токен доступа столько запросов, сколько хотите до истечения срока его действия. Затем вы можете использовать токен обновления, чтобы запросить новый токен доступа (который поставляется с новой датой истечения срока действия и новым токеном обновления).

См. также:

Ответ 3

У меня также были проблемы с получением "автономной" аутентификации для работы (т.е. для получения аутентификации с токеном обновления) и получил HTTP-ответ 400 Bad request с кодом, похожим на код OP. Однако я получил его для работы с линией client.ClientCredentialApplicator = ClientCredentialApplicator.PostParameter(this.clientSecret); в методе Authenticate. Это существенный, чтобы получить рабочий код. Я думаю, что эта строка заставляет clientSecret быть отправлен как POST-параметр на сервер (вместо базового параметра аутентификации HTTP).

Это решение предполагает, что у вас уже есть идентификатор клиента, секрет клиента и токен обновления. Обратите внимание, что вам не нужно вводить токен доступа в код. (Короткоживущий код доступа приобретается "под капотом" с сервера Google при отправке долгоживущего токена обновления с линией client.RefreshAuthorization(state);. Этот токен доступа хранится как часть 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<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 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;
    }
}

Ответ 4

Спецификация OAuth 2.0 еще не завершена, и там существует множество реализаций реализации различных клиентов и служб, которые вызывают появление этих ошибок. Скорее всего, вы все делаете правильно, но версия DotNetOpenAuth, которую вы используете, реализует другой проект OAuth 2.0, который в настоящее время реализуется Google. Ни одна из частей не является "правильной", поскольку спецификация еще не завершена, но она делает совместимость чем-то вроде кошмара.

Вы можете проверить, что используемая вами версия DotNetOpenAuth является последней (в случае, если она помогает), но в конечном итоге вам может понадобиться либо сидеть, пока спецификации не будут завершены, а все будут правильно их выполнять или прочитать сами документы Google (которые предположительно описывают их версию OAuth 2.0) и реализуют ту, которая специально предназначена для их черновиковой версии.

Ответ 5

Я бы порекомендовал посмотреть проект "SampleHelper" в решении Samples API клиента Google.NET:

В этом файле показано, как использовать защищенные данные Windows для хранения токена Refresh, а также показано, как использовать локальный сервер Loopback и различные методы для захвата кода доступа вместо того, чтобы пользователь вводил его вручную.

Один из образцов библиотеки, использующих этот метод авторизации, можно найти ниже: