OAuth con verificación en .NET

Intento crear una aplicación de cliente basada en .NET (en WPF, aunque por el momento solo lo estoy haciendo como una aplicación de consola) para integrarla con una aplicación habilitada para OAuth, específicamente Mendeley ( http: // dev .mendeley.com ), que aparentemente usa OAuth de 3 patas.

Esta es la primera vez que uso OAuth, y estoy teniendo muchas dificultades para empezar a usarlo. He encontrado varias bibliotecas .NET OAuth o ayudantes, pero parecen ser más complicadas de lo que creo que necesito. ¡Todo lo que quiero hacer es poder emitir solicitudes REST a la API de Mendeley y obtener respuestas!

Hasta ahora, lo he intentado:

  • DotNetOpenAuth
  • http://github.com/bittercoder/DevDefined.OAuth
  • http://oauth.googlecode.com/svn/code/csharp/

El primero (DotNetOpenAuth) parece que podría hacer lo que necesitaba si pasara horas y horas tratando de averiguar cómo. El segundo y el tercero, lo mejor que puedo decir, no son compatibles con los códigos de verificación que Mendeley está enviando, aunque podría estar equivocado al respecto 🙂

Tengo una clave de consumidor y un secreto de Mendeley, y con DotNetOpenAuth logré que se lanzara un navegador con la página de Mendeley que proporciona un código de verificación para que el usuario ingrese a la aplicación. Sin embargo, en este punto me perdí y no pude encontrar la manera de volver a proporcionar la aplicación.

Estoy muy dispuesto a admitir que no tengo ni idea de dónde comenzar con esto (aunque parece que hay una curva de aprendizaje bastante empinada). Si alguien puede indicarme la dirección correcta, ¡lo agradecería!

Estoy de acuerdo contigo. Las clases de soporte de OAuth de código abierto disponibles para aplicaciones .NET son difíciles de entender, demasiado complicadas (¿cuántos métodos están expuestos por DotNetOpenAuth?), Mal diseñadas (mire los métodos con 10 parámetros de cadena en el módulo OAuthBase.cs de ese google el enlace que proporcionó – no hay administración estatal en absoluto), o de otra manera insatisfactorio.

No necesita ser tan complicado.

No soy un experto en OAuth, pero he producido una clase de administrador del lado del cliente OAuth, que uso con éxito con Twitter y TwitPic. Es relativamente simple de usar. Es de código abierto y está disponible aquí: Oauth.cs

Para revisar, en OAuth 1.0a … es un poco raro, hay un nombre especial y parece un “estándar”, pero hasta donde sé, el único servicio que implementa “OAuth 1.0a” es Twitter. Supongo que es lo suficientemente estándar. ok, de todos modos en OAuth 1.0a, la forma en que funciona para aplicaciones de escritorio es esta:

  1. Usted, el desarrollador de la aplicación, registra la aplicación y obtiene una “clave de consumidor” y un “secreto de consumidor”. En Arstechnica, hay un análisis bien escrito de por qué este modelo no es el mejor , pero como dicen, es lo que es .

  2. Tu aplicación se ejecuta La primera vez que se ejecuta, necesita que el usuario otorgue explícitamente la aprobación para que la aplicación realice solicitudes de REST autenticadas a Twitter y sus servicios asociados (como TwitPic). Para hacerlo, debe pasar por un proceso de aprobación que implica la aprobación explícita del usuario. Esto ocurre solo la primera vez que se ejecuta la aplicación. Me gusta esto:

    • solicite un “token de solicitud”. Token temporal de Aka.
    • abrir una página web, pasar ese token de solicitud como un param de consulta. Esta página web presenta la interfaz de usuario para el usuario y pregunta “¿desea otorgar acceso a esta aplicación?”
    • el usuario inicia sesión en la página web de Twitter y otorga o niega el acceso.
    • aparece la página html de respuesta. Si el usuario ha otorgado acceso, se muestra un PIN en una fuente de 48 puntos
    • el usuario ahora necesita cortar / pegar ese pin en un cuadro de formulario de Windows y hacer clic en “Siguiente” o algo similar.
    • la aplicación de escritorio luego realiza una solicitud autenticada por oauth para un “token de acceso”. Otra solicitud REST.
    • la aplicación de escritorio recibe el “token de acceso” y el “secreto de acceso”.

Después del baile de aprobación, la aplicación de escritorio puede usar el “token de acceso” y el “secreto de acceso” específicos del usuario (junto con la “clave del consumidor” y el “secreto del consumidor” específicos de la aplicación) para realizar solicitudes autenticadas en nombre del usuario a Twitter Estos no caducan, aunque si el usuario anula la autorización de la aplicación, o si Twitter por algún motivo lo desautoriza, o si pierde su token de acceso y / o su contraseña secreta, tendrá que volver a bailar de nuevo. .


Si no es inteligente, el flujo de la interfaz de usuario puede reflejar el flujo de mensajes de OAuth de varios pasos. Hay una mejor manera.

Utilice un control WebBrowser y abra la página web autorizar dentro de la aplicación de escritorio. Cuando el usuario hace clic en “Permitir”, toma el texto de respuesta de ese control WebBrowser, extrae el PIN automáticamente y luego obtén los tokens de acceso. Envía 5 o 6 solicitudes HTTP pero el usuario necesita ver solo un diálogo de Permitir / Denegar. Sencillo.

Me gusta esto:
texto alternativo


Si tiene la IU ordenada, el único desafío que queda es producir solicitudes con firma automática. Esto hace tropezar a muchas personas porque los requisitos de firma de oauth son bastante particulares. Eso es lo que hace la clase simplificada OAuth Manager.

Código de ejemplo para solicitar un token:

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

ESO ES . Sencillo. Como puede ver en el código, la manera de obtener los parámetros es a través de un indexador basado en cadenas, algo así como un diccionario. El método AcquireRequestToken envía una solicitud oauth-signed a la URL del servicio que concede los tokens de solicitud, también conocidos como tokens temporales. Para Twitter, esta URL es ” https://api.twitter.com/oauth/request_token “. La especificación oauth dice que debe empaquetar el conjunto de parámetros oauth (token, token_secret, nonce, timestamp, consumer_key, version y callback), de una cierta manera (codificada en url y unida por ampersands), y de forma lexicográficamente- ordenado, genere una firma en ese resultado, luego empaquete esos mismos parámetros junto con la firma, almacenada en el nuevo parámetro oauth_signature, de una manera diferente (unida por comas). La clase de administrador de OAuth hace esto automáticamente. Genera nonces y marcas de tiempo y versiones y firmas automáticamente: su aplicación no necesita preocuparse ni tener en cuenta esas cosas. Simplemente configure los valores del parámetro oauth y realice una llamada a un método simple. la clase de administrador envía la solicitud y analiza la respuesta por usted.

¿OK entonces que? Una vez que obtenga el token de solicitud, abrirá la interfaz de usuario del navegador web en la que el usuario otorgará aprobación explícitamente. Si lo haces bien, lo mostrarás en un navegador integrado. Para Twitter, la URL para esto es ” https://api.twitter.com/oauth/authorize?oauth_token= ” con el oauth_token adjunto. Haz esto en código así:

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

(Si estuviera haciendo esto en un navegador externo, usaría System.Diagnostics.Process.Start(url) .

Establecer la propiedad Url hace que el control WebBrowser navegue a esa página automáticamente.

Cuando el usuario hace clic en el botón “Permitir”, se cargará una nueva página. Es un formulario HTML y funciona igual que en un navegador completo. En su código, registre un controlador para el evento DocumentadoCompletado del control WebBrowser, y en ese controlador, agarre el pin:

 var divMarker = "
"; // the div for twitter's 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();

Eso es un poco de raspado de pantalla HTML.

Después de tomar el pin, ya no necesita el navegador web, entonces:

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

… y es posible que desee llamar a Dispose () también.

El siguiente paso es obtener el token de acceso, al enviar otro mensaje HTTP junto con ese pin. Esta es otra llamada oauth firmada, construida con el orden y el formato Oauth que describí anteriormente. Pero una vez más, esto es realmente simple con la clase OAuth.Manager:

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

Para Twitter, esa URL es ” https://api.twitter.com/oauth/access_token “.

Ahora tiene tokens de acceso y puede usarlos en solicitudes HTTP firmadas. Me gusta esto:

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

… donde url es el punto final del recurso. Para actualizar el estado del usuario, sería ” http://api.twitter.com/1/statuses/update.xml?status=Hello “.

A continuación, configure esa cadena en el encabezado HTTP denominado Autorización .

Para interactuar con servicios de terceros, como TwitPic, debe construir un encabezado OAuth ligeramente diferente , como este:

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

Para Twitter, los valores para verificar la URL de creds y el reino son ” https://api.twitter.com/1/account/verify_credentials.json ” y ” http://api.twitter.com/ ” respectivamente.

… y ponga esa cadena de autorización en un encabezado HTTP llamado X-Verify-Credentials-Authorization . Luego, envíe eso a su servicio, como TwitPic, junto con cualquier solicitud que envíe.

Eso es.

En conjunto, el código para actualizar el estado de Twitter podría ser algo como esto:

 // 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's been a problem trying to tweet:" + Environment.NewLine + response.StatusDescription); } 

OAuth 1.0a es algo complicado bajo las sábanas, pero no es necesario usarlo. OAuth.Manager maneja la generación de solicitudes de salida de oauth, y la recepción y el procesamiento de contenido de Oauth en las respuestas. Cuando la solicitud Request_token te otorga oauth_token, tu aplicación no necesita almacenarla. El Oauth.Manager es lo suficientemente inteligente como para hacerlo automáticamente. Del mismo modo, cuando la solicitud access_token recupera un token de acceso y un secreto, no es necesario que los almacene explícitamente. El OAuth.Manager maneja ese estado por ti.

En ejecuciones posteriores, cuando ya tiene el token de acceso y el secreto, puede crear una instancia del OAuth.Manager de la siguiente manera:

 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; 

… y luego generar encabezados de autorización como se indicó anteriormente.

 // 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's been a problem trying to tweet:" + Environment.NewLine + response.StatusDescription); } 

Puede descargar una DLL que contiene la clase OAuth.Manager aquí . También hay un archivo de ayuda en esa descarga. O puede ver el archivo de ayuda en línea .

Vea un ejemplo de Windows Form que usa este administrador aquí .


EJEMPLO DE TRABAJO

Descargue un ejemplo de trabajo de una herramienta de línea de comandos que usa la clase y la técnica descrita aquí: