[Windows Phone 7.5] Tip: Cookies HttpOnly en HttpWebRequest y depurar peticiones web

Hola a todos!

Estos días jugando con HttpWebRequest para una aplicación que necesitaba consumir unos servicios REST me encontré con un pequeño problema cuya solución no es demasiado obvia, así que os la traigo por si estáis en la misma situación en algún momento.

Resulta que estos servicios requerían autenticación, devolviendo un token de sesión que tienes que usar en el resto de llamadas pero… sorpresa: el token se devolvía como una cookie HttpOnly, con lo que necesitaba acceder a la misma para conservar el token y reutilizarlo en las siguientes llamadas.

Para empezar, si queremos trabajar con cookies y con la clase HttpWebRequest, tenemos que usar la pila Http de cliente y no del navegador, indicándolo mediante el método RegisterPrefix de HttpWebRequest:

RegisterPrefix
  1.  
  2. bool httpResult = HttpWebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);

De esta forma, en nuestro HttpWebRequest podremos usar un CookieContainer que nos será de utilidad más adelante.

Ahora solo tenemos que crear la llamada y al recibir la respuesta, obtener la colección de cookies disponibles y extraer la que nos interesa:

Request / Response
  1. HttpWebRequest request;
  2. CookieContainer cookies = new CookieContainer();
  3.  
  4. bool httpResult = HttpWebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
  5.  
  6. request = (HttpWebRequest)WebRequest.Create("http://miwebservice/method");
  7. request.Headers["Accept-Language"] = "es-ES";
  8. request.Accept = "text/html, application/xhtml+xml, */*";
  9. request.Method = "GET";
  10.  
  11. request.BeginGetResponse(new AsyncCallback((ar) =>
  12. {
  13.     HttpWebRequest Request = (HttpWebRequest)ar.AsyncState;
  14.     if (Request != null)
  15.     {
  16.         using (HttpWebResponse webResponse = (HttpWebResponse)Request.EndGetResponse(ar))
  17.         {
  18.             var session = webResponse.Cookies["SESSIONID"];
  19.         }
  20.     }
  21. }), request);

Pero aquí nos encontramos con un muro, aunque la cookie SESSIONID está llegando correctamente si usamos una aplicación como Fiddler para examinar las peticiones y respuestas HTTP, la colección Cookies de nuestro HttpWebResponse no contiene la misma. Al examinar la respuesta veo que efectivamente la cookie está allí por lo que se tiene que tratar de un problema al recibirla.

Después de mucha prueba y error, basándome en que una de las características de las cookies HttpOnly es que no pueden ser accedidas desde scripts se me ocurrió que quizás la cookie si estaba siendo recibida, simplemente no podía verla… ¿que pasa si hacemos lo siguiente?:

Response with HttpOnly cookie
  1. cookies.Add(new Uri("http://miwebservice"), webResponse.Cookies);
  2. request = (HttpWebRequest)WebRequest.Create("http://miwebservice/method2");
  3. request.CookieContainer = cookies;
  4. request.BeginGetResponse(new AsyncCallback((asyncResult) =>
  5. {
  6.     Request = (HttpWebRequest)asyncResult.AsyncState;
  7.     if (Request != null)
  8.     {
  9.         using (HttpWebResponse resp = (HttpWebResponse)Request.EndGetResponse(asyncResult))
  10.         {
  11.  
  12.         }
  13.     }
  14. }), request);

Añado la colección de cookies que me ha devuelto mi petición a un CookieContainer y en las siguientes peticiones asigno a la propiedad CookieContainer de HttpWebRequest el contenedor con las cookies que me ha devuelto mi primera petición… y voilá! efectivamente, la cookie HttpOnly se encontraba allí, solo que no podía acceder a ella.

Lo único que necesitamos es guardarnos la colección de cookies devuelta y tendremos todo lo que necesitamos. No es que me haga demasiada ilusión no poder trabajar directamente con la cookie, comprobar si realmente existe, etc… pero es la única forma que hay de poder usarla, así que tendremos que conformarnos.

Fiddler2

Para todo este trabajo, la ayuda de un depurador web como Fiddler se hace indispensable, te permite ver que están haciendo tus peticiones exactamente y extraer todos los datos que necesites. Si lo instalas con  el enlace que he puesto más arriba, al iniciarlo no recibirá ninguna petición desde el emulador de Windows Phone, tenemos que hacer unos pocos pasos para que funcione correctamente:

  1. Iniciar Fiddler 2 (v2.3.0.7 o superior) e ir a Tools > Fiddler Options
  2. Ir a la pestaña Connections y marchar el check Allow remote computers to connect
  3. Presionamos OK y reiniciamos la aplicación
  4. En la pantalla inicial, abajo a la izquierda tenemos una caja de texto negra, escribir en ella: prefs set fiddler.network.proxy.registrationhostname HostName donde HostName es el nombre de tu PC.
  5. Reinicia tanto el emulador como la aplicación y abre internet explorer en el emulador, verás el trafico en Fiddler

Con estos sencillos pasos, tendremos una forma sencilla de ver el tráfico de nuestras aplicaciones y que está pasando en concreto. En el caso que os explico al hacer la petición al método de autenticación pude ver que la cookie era HttpOnly:

fiddler2

Vemos que la respuesta nos devuelve una cabecera Set-Cookie con el parámetro HttpOnly (Abajo, recuadro rojo). También es interesante poder ver que aplicación del dispositivo a realizado la petición si examinamos el Referer de la petición (Arriba, recuadro azul). Al mirar que efecto tenía al pasar la colección de cookies devuelta directamente a otra petición pude ver gracias a Fiddler que en la petición se estaba incluyendo la cookie correctamente:

fiddler2_2

Y esto es todo lo que os quería contar hoy, espero que os sea útil, tanto para no volveros locos buscando la Cookie perdida como para aprovecharos de Fiddler en vuestros desarrollos.

Un saludo y Happy Coding!

Published 4/5/2012 6:21 por Josué Yeray Julián Ferreiro
Comparte este post:

Comentarios

# re: [Windows Phone 7.5] Tip: Cookies HttpOnly en HttpWebRequest y depurar peticiones web

Friday, May 4, 2012 4:08 PM por Omar del Valle Rodríguez

Muy bueno lo de los cookie. Me pasó lo mismo pero con suerte de que el servicio además de por cookie, me retornaba el valor en el Title del reponse... y claro, me fuí por el camino más facil... :)

Si me lo permites, quisiera adicionar un minúsculo detalle: Si usas muy a menudo el Fiddler, puede ser un poco molesto dejar la configuracón que incluimos para poder ver las peticiones del emulador. Mas q nada pq estamos diciendo que todas las peticiones que se hacen desde nuestro ordenador pasen por el fiddler...

Cuando se necesite quitarlo, solo tienen que ir al mismo lugar del punto (4) descrito en el artículo y escribir "about:config". Esto mostrará la configuración del Fiddler, buscamos la línea q contiene fiddler.network.proxy.registrationhostname y la eliminamos...

Un salu2

# re: [Windows Phone 7.5] Tip: Cookies HttpOnly en HttpWebRequest y depurar peticiones web

Thursday, June 21, 2012 5:35 PM por migdomingo

Un post muy útil que pone en práctica lo que especifica Microsoft en la documentación del CookieContainer msdn.microsoft.com/.../system.net.cookiecontainer(v=vs.95).aspx

El problema real viene cuando combinamos el flag HTTP-Only con tombstombing, ya que WP7 no es capaz de serializar el CookieContainer (social.msdn.microsoft.com/.../676d89e4-14aa-48af-8671-19274e2574f7) , y al no tener acceso directo a las cookies marcadas como HTTP-Only las perdemos, y es muy posible que con ellas la sesión.

De momento esto está en la lista de las "mejoras" que algunos usuarios desearían para Windows Phone wpdev.uservoice.com/.../2278081-allow-cookiecontainer-to-be-serialized-deserialize