- Cómo securizar aplicaciones web usando ACS y tokens JWT.
- Desplegar aplicaciones web en Windows Azure WebSites que hagan uso de WIF.
- Cómo securizar servicios WebAPI usando ACS y tokens JWT.
- Cómo securizar una aplicación MVC que contenga tanto aplicaciones web como servicios WebAPI.
- Cómo securizar aplicaciones web usando Windows Azure Active Directory ( WAAD ).
- Cómo hacer uso del tenant de WAAD de Office 365 para securizar aplicaciones web
En los ejemplos anteriores hemos visto cómo securizar una aplicación ASP.NET MVC y una aplicación WebAPI haciendo uso de ACS y tokens JWT.
¿Pero qué pasa si en el mismo proyecto tenemos las dos cosas? Una aplicación web a la cuál un usuario puede acceder a través del navegador y un servicio WebAPI que se usa tanto desde el javascript de la aplicación web, como desde otros clientes como pueden ser una aplicación Windows 8 o Windows Phone.
En este caso, tendremos que hacer los pasos vistos en los dos post anteriores, pero veremos cómo una vez juntos no van a funcionar las llamadas al servicio WebAPI, salvo las propias que podamos hacer desde el javascript de la aplicación.
Cuando hacemos uso de WIF para autenticar la aplicación web, TODAS las llamadas que se realizar deben estar autenticadas. En caso de no estar autenticadas, se nos redirige a la pantalla de login para que podamos introducir las credenciales.
Si las llamadas las intentamos realizar por código, por ejemplo desde una aplicación Windows 8 haciendo uso de httpClient, estas llamadas serán igualmente redirigidas a la pantalla de login, aunque mandemos en las cabeceras el token de seguridad.
Solución? En mi caso lo he solucionado de la siguiente manera:
Lo primero es añadir la posibilidad de llamar a los servicios WebAPI a través de dos rutas diferentes. Una de las rutas será usada por la aplicación web, cuando desde el código JavaScript quiera llamar a estos servicios, mientras la otra ruta será usada para el resto de clientes; Windows 8, Windows Phone…
config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); config.Routes.MapHttpRoute( name: "DefaultApiJs", routeTemplate: "apijs/{controller}/{id}", defaults: new { id = RouteParameter.Optional } );
En el fichero de configuración establezco que la ruta que va a ser usada por las “aplicaciones externas” permita llamadas anónimas.
<location path="api"> <system.web> <authorization> <allow users="*" /> </authorization> </system.web> </location>
y por último, en el DelegationHandler haré que sólo se valide el token si la llamada no es autenticada.
if (Thread.CurrentPrincipal.Identity.IsAuthenticated) { return base.SendAsync(request, cancellationToken); }
De esta manera conseguimos:
Si un usuario accede a través del navegador se le pedirán las credenciales para poder entrar en la web. Una vez autenticado, todas las llamadas que se hagan desde el JavaScript ya estarán autenticadas, por lo que no es necesario que el DelegationHandler haga nada.
Cuando hacemos por código desde una aplicación externa, haremos uso de la ruta que permite llamada anónimas y así evitar que se nos mande a la página de login. En este caso, el DelagationHandler sí tendrá que validar el token de seguridad y establecer la identidad en la llamada.
Hola, siguiendo tu articulo, hago la siguiente pregunta, no debería también las llamadas a los servicios mediante clientes como Windows pone y Windows 8, también estar autenticadas. Por lo menos que dichas cliente tengas su propio formulario de login. No dejarlo como anonimante.
Saludos.
Romny
Hola,
Todas las llamadas son autenticadas, si un cliente WP o Windows 8 intenta hacer una llamada sin autenticación fallará.
En el post anterior – http://www.estoyenlanube.com/cmo-securizar-servicios-webapi-usando-acs-y-tokens-jwt – se ve el código que usaría una aplicación cliente para hacer la llamada. Ese código sacar una UI en cliente para autenticarse y obtener un token de seguridad que pasa en las cabeceras.
Un saludo,