OAuth с проверкой в ​​.NET.

Я пытаюсь создать клиентское приложение на основе .NET(в WPF - хотя пока я просто делаю это как консольное приложение) для интеграции с приложением с поддержкой OAuth, в частности с Mendeley (http://dev.mendeley.com), который, по-видимому, использует OAuth с тремя ногами.

Это мой первый раз, когда я использую OAuth, и мне сложно начать с этого. Я нашел несколько библиотек или помощников .NET OAuth, но они кажутся более сложными, чем мне кажется. Все, что я хочу сделать, это предоставить REST-запросы API-интерфейсу Mendeley и вернуть ответы!

До сих пор я пробовал:

Первый (DotNetOpenAuth) кажется, что он может сделать то, что мне нужно, если я потратил часы и часы, пытаясь понять, как это сделать. Второй и третий, насколько я могу судить, не поддерживают коды проверки, которые Менделей посылает обратно, хотя я мог ошибаться в этом:)

У меня есть ключ от пользователя и секрет от Mendeley, и с DotNetOpenAuth мне удалось получить браузер, запущенный на странице Mendeley, с кодом подтверждения для пользователя, чтобы войти в приложение. Однако в этот момент я потерялся и не мог понять, как разумно предоставить это обратно в приложение.

Я очень хочу признать, что я понятия не имею, с чего начать (хотя кажется, что здесь довольно крутая кривая обучения) - если кто-то может указать мне в правильном направлении, я бы это оценил!

Ответ 1

Я согласен с тобой. Открытые классы поддержки OAuth с открытым исходным кодом, доступные для приложений .NET, трудно понять, слишком сложно (сколько методов открыто DotNetOpenAuth?), Плохо спроектированы (посмотрите на методы с 10 строковыми параметрами в модуле OAuthBase.cs из этого google ссылку, которую вы предоставили - там вообще нет государственного управления) или иным образом неудовлетворительным.

Это не должно быть так сложно.

Я не эксперт по OAuth, но я создал класс менеджера на стороне клиента OAuth, который я успешно использую с Twitter и TwitPic. Он относительно прост в использовании. Он открыт с открытым исходным кодом и доступен здесь: Oauth.cs

Для обзора, в OAuth 1.0a... kinda funny, есть специальное имя, и оно выглядит как "стандарт", но насколько я знаю, единственным сервисом, который реализует "OAuth 1.0a", является Twitter. Наверное, этого стандарта достаточно. ok, так или иначе, в OAuth 1.0a, то, как он работает для настольных приложений, это:

  • Вы, разработчик приложения, зарегистрируете приложение и получите "потребительский ключ" и "секрет потребителя". На Arstechnica, хорошо написанный анализ того, почему эта модель не самая лучшая, но, как говорится, она такая, какая она есть.

  • Ваше приложение запускается. В первый раз, когда он запускается, он должен заставить пользователя явно предоставить одобрение для приложения, чтобы сделать OEST-аутентифицированные запросы REST для Twitter и его сестринских сервисов (например, TwitPic). Для этого вы должны пройти процесс утверждения с явным одобрением пользователем. Это происходит только при первом запуске приложения. Вот так:

    • запросить "токен запроса". Aka временный токен.
    • введите веб-страницу, передав этот токен запроса в качестве параметра запроса. Эта веб-страница представляет пользовательский интерфейс пользователю, спрашивая: "Вы хотите предоставить доступ к этому приложению?"
    • пользователь регистрируется на веб-странице twitter и предоставляет или запрещает доступ.
    • появится страница ответа html. Если пользователь предоставил доступ, там появится PIN-код, отображаемый шрифтом 48-pt
    • пользователю теперь нужно вырезать/вставить этот вывод в окно формы окна и нажать "Далее" или что-то подобное.
    • настольное приложение затем выполняет аутентифицированный запрос oauth для "токена доступа". Другой запрос REST.
    • настольное приложение получает "токен доступа" и "секрет доступа".

После танца одобрения настольное приложение может просто использовать пользовательский "токен доступа" и "секрет доступа" (вместе с конкретным приложением "потребительский ключ" и "секрет потребителя" ) для выполнения аутентифицированных запросов от имени пользователя для Twitter. Они не истекают, хотя, если пользователь отменяет авторизацию приложения или если Twitter по какой-то причине отменяет полномочия вашего приложения, или если вы потеряете токен доступа и/или секрет, вам нужно будет снова сделать танец одобрения,


Если вы не умны, поток пользовательского интерфейса может сортировать зеркало многоступенчатого потока сообщений OAuth. Существует лучший способ.

Используйте элемент управления WebBrowser и откройте авторизационную веб-страницу в настольном приложении. Когда пользователь нажимает "Разрешить", возьмите текст ответа из этого элемента управления WebBrowser, извлеките PIN-код автоматически, а затем получите токены доступа. Вы отправляете 5 или 6 HTTP-запросов, но пользователю нужно увидеть только один диалог "Разрешить/Запретить". Простой.

Вот так:
alt text


Если у вас настроен пользовательский интерфейс, единственная проблема, которая остается, заключается в том, чтобы создавать запросы, подписанные oauth. Это вызывает множество людей, потому что требования к подписи oauth являются определенными. Это то, что делает упрощенный класс OAuth Manager.

Пример кода для запроса токена:

var oauth = new OAuth.Manager();
// the URL to obtain a temporary "request token"
var rtUrl = "https://api.twitter.com/oauth/request_token";
oauth["consumer_key"] = MY_APP_SPECIFIC_KEY;
oauth["consumer_secret"] = MY_APP_SPECIFIC_SECRET;    
oauth.AcquireRequestToken(rtUrl, "POST");

ЭТО. Просто. Как вы можете видеть из кода, способ доступа к параметрам oauth - это строковый индексатор, что-то вроде словаря. Метод AcquireRequestToken отправляет oauth-подписанный запрос на URL-адрес службы, которая предоставляет токены запроса, например временные токены. Для Twitter этот URL-адрес: https://api.twitter.com/oauth/request_tokenСпецификация oauth указывает, что вам необходимо собрать набор параметров oauth (токен, токен_секунды, nonce, timestamp, consumer_key, версию и обратный вызов) определенным образом (кодируется по URL-адресу и соединен амперсандами) и в лексикографически упорядоченный порядок, сгенерируйте подпись на этом результате, затем скомбинируйте те же параметры вместе с сигнатурой, хранящейся в новом параметре oauth_signature, по-другому (объединенные запятыми). Класс менеджера OAuth делает это для вас автоматически. Он автоматически генерирует ноты и временные метки, а также версии и подписи - вашему приложению не нужно заботиться или знать об этом. Просто установите значения параметра oauth и выполните простой вызов метода. Класс менеджера отправляет запрос и анализирует ответ для вас.

Хорошо, тогда что? После того, как вы получите токен запроса, вы откроете интерфейс веб-браузера, в котором пользователь явно предоставит разрешение. Если вы все сделаете правильно, вы поместите его во встроенный браузер. Для Twitter URL для этого " https://api.twitter.com/oauth/authorize?oauth_token=" с добавлением oauth_token. Сделайте это в коде так:

var url = SERVICE_SPECIFIC_AUTHORIZE_URL_STUB + oauth["token"];
webBrowser1.Url = new Uri(url);

(Если вы делали это во внешнем браузере, вы использовали бы System.Diagnostics.Process.Start(url).)

Настройка свойства Url приводит к тому, что элемент управления WebBrowser автоматически переходит на эту страницу.

Когда пользователь нажимает кнопку "Разрешить", загружается новая страница. Это HTML-форма, и она работает так же, как в полном браузере. В своем коде зарегистрируйте обработчик для события DocumentedCompleted элемента управления WebBrowser и в этом обработчике возьмите вывод:

var divMarker = "<div id=\"oauth_pin\">"; // the div for twitter oauth pin
var index = webBrowser1.DocumentText.LastIndexOf(divMarker) + divMarker.Length;
var snip = web1.DocumentText.Substring(index);
var pin = RE.Regex.Replace(snip,"(?s)[^0-9]*([0-9]+).*", "$1").Trim();

Это немного скрипит экран HTML.

После захвата булавки вам больше не нужен веб-браузер, поэтому:

webBrowser1.Visible = false; // all done with the web UI

... и вы можете также вызвать Dispose().

Следующий шаг - получить токен доступа, отправив другое сообщение HTTP вместе с этим контактом. Это еще один подписанный oauth-вызов, построенный с использованием порядка и форматирования oauth, описанных выше. Но еще раз это действительно просто с классом OAuth.Manager:

oauth.AcquireAccessToken(URL_ACCESS_TOKEN,
                         "POST",
                         pin);

Для Twitter этот URL-адрес " https://api.twitter.com/oauth/access_token".

Теперь у вас есть токены доступа, и вы можете использовать их в подписанных HTTP-запросах. Вот так:

var authzHeader = oauth.GenerateAuthzHeader(url, "POST");

... где url - конечная точка ресурса. Чтобы обновить статус пользователя, это будет " http://api.twitter.com/1/statuses/update.xml?status=Hello".

Затем установите эту строку в заголовке HTTP с именем Авторизация.

Чтобы взаимодействовать со сторонними службами, такими как TwitPic, вам нужно создать немного другой заголовок OAuth, например:

var authzHeader = oauth.GenerateCredsHeader(URL_VERIFY_CREDS,
                                            "GET",
                                            AUTHENTICATION_REALM);

Для Твиттера значения для URL-адресов проверки creds и "are" https://api.twitter.com/1/account/verify_credentials.json" и " http://api.twitter.com/" соответственно.

... и поместите эту строку авторизации в HTTP-заголовок X-Verify-Credentials-Authorization. Затем отправьте это на свой сервис, например TwitPic, вместе с любым запросом, который вы отправляете.

Что это.

Все вместе, код для обновления статуса твиттера может быть примерно таким:

// the URL to obtain a temporary "request token"
var rtUrl = "https://api.twitter.com/oauth/request_token";
var oauth = new OAuth.Manager();
// The consumer_{key,secret} are obtained via registration
oauth["consumer_key"] = "~~~CONSUMER_KEY~~~~";
oauth["consumer_secret"] = "~~~CONSUMER_SECRET~~~";
oauth.AcquireRequestToken(rtUrl, "POST");
var authzUrl = "https://api.twitter.com/oauth/authorize?oauth_token=" + oauth["token"];
// here, should use a WebBrowser control. 
System.Diagnostics.Process.Start(authzUrl);  // example only!
// instruct the user to type in the PIN from that browser window
var pin = "...";
var atUrl = "https://api.twitter.com/oauth/access_token";
oauth.AcquireAccessToken(atUrl, "POST", pin);

// now, update twitter status using that access token
var appUrl = "http://api.twitter.com/1/statuses/update.xml?status=Hello";
var authzHeader = oauth.GenerateAuthzHeader(appUrl, "POST");
var request = (HttpWebRequest)WebRequest.Create(appUrl);
request.Method = "POST";
request.PreAuthenticate = true;
request.AllowWriteStreamBuffering = true;
request.Headers.Add("Authorization", authzHeader);

using (var response = (HttpWebResponse)request.GetResponse())
{
    if (response.StatusCode != HttpStatusCode.OK)
        MessageBox.Show("There been a problem trying to tweet:" +
                        Environment.NewLine +
                        response.StatusDescription);
}

OAuth 1.0a довольно сложно под крышками, но использовать его не нужно. OAuth.Manager обрабатывает генерацию исходящих запросов oauth и прием и обработку содержимого oauth в ответах. Когда запрос Request_token дает вам oauth_token, вашему приложению не нужно его хранить. Oauth.Manager достаточно умен, чтобы сделать это автоматически. Аналогично, когда запрос access_token возвращает токен доступа и секрет, вам не нужно явно хранить их. OAuth.Manager обрабатывает это состояние для вас.

В последующих прогонах, когда у вас уже есть токен доступа и секрет, вы можете создать экземпляр OAuth.Manager следующим образом:

var oauth = new OAuth.Manager();
oauth["consumer_key"] = CONSUMER_KEY;
oauth["consumer_secret"] = CONSUMER_SECRET;
oauth["token"] = your_stored_access_token;
oauth["token_secret"] = your_stored_access_secret;

... и затем создайте заголовки авторизации, как указано выше.

// now, update twitter status using that access token
var appUrl = "http://api.twitter.com/1/statuses/update.xml?status=Hello";
var authzHeader = oauth.GenerateAuthzHeader(appUrl, "POST");
var request = (HttpWebRequest)WebRequest.Create(appUrl);
request.Method = "POST";
request.PreAuthenticate = true;
request.AllowWriteStreamBuffering = true;
request.Headers.Add("Authorization", authzHeader);

using (var response = (HttpWebResponse)request.GetResponse())
{
    if (response.StatusCode != HttpStatusCode.OK)
        MessageBox.Show("There been a problem trying to tweet:" +
                        Environment.NewLine +
                        response.StatusDescription);
}

Вы можете загрузить DLL, содержащую класс OAuth.Manager. В этой загрузке есть также файл справки. Или вы можете просмотреть файл справки в Интернете.

См. пример Windows Form, который использует этот менеджер здесь.


РАБОЧИЙ ПРИМЕР

Загрузите рабочий пример инструмента командной строки, который использует описанный здесь класс и метод: