ADFS - Seguridad en Servicios Web

Seguramente si estás leyendo este artículo es porque ya implementaste seguridad con Adfs en tus sitios y ahora necesitás extender esa seguridad a los servicios web.

Sino te recomiendo que empieces por la serie dedicada a la autenticación y autorización en sitios web con Adfs.

Lo que vamos a hacer es permitir que la aplicación web indique al servicio web quien la está usando de una manera confiable y segura. A este proceso se lo llama Delegación de la Identidad.

Objetivos de la delegación

  • Controlar el acceso al servicio web tanto a nivel de la aplicación que lo utiliza como del usuario final.
  • Conocer, en el servicio web, quien es el usuario de la aplicación.

Escenario de delegación

El proceso de delegación ocurre en dos etapas, la primera es para acceder al sitio web donde el usuario presenta sus credenciales. La segunda etapa es para acceder al servicio web actuando como el usuario autenticado en el sitio. De aquí en adelante nos referiremos a “Juan” como el usuario y a “AppWeb” como las credenciales con que se autentica la aplicación web (ya sea indicando usuario y password o siendo la cuenta con que ejecuta el application pool del sitio).

ADFS - esquema de delegación

La negociación que incluyen los mensajes 1 y 2 es para obtener el token de ingreso a la “Aplicación Web”, a este token lo llamaremos “Token A”. Esta negociación en aplicaciones web se suele obtener en forma pasiva (a base de redirecciones del browser).

La negociación que incluye los mensajes 3 y 4 es la correspondiente al token para que AppWeb acceda a “Servicio Web” actuando como Juan, a este token lo llamaremos “Token B”. Esta negociación se realiza en forma activa, invocando alguno de los endpoints de los publicados en Adfs. En dicha invocación se incluye las credenciales de AppWeb y el “Token A”.

Pipeline de ejecución del Claim Engine

El siguiente gráfico es la representación de lo que sucede dentro de ADFS en el escenario de delegación. La mitad izquierda del gráfico corresponde a la negociación del “Token A” para acceder a la “Aplicación Web” mientras que la mitad derecha corresponde a la negociación del “Token B” para que la aplicación pueda acceder al “Servicio Web” actuando en nombre del usuario autenticado, es decir en nombre de Juan.

ADFS - flujo de claims con delegación

El pipeline de ejecución para obtener un token actuando como otro usuario (delegación) tiene diferencias con el pipeline de autenticación donde no se delega la identidad, algunas de estas son:

Existen dos conjuntos de claims de entrada, el correspondiente a AppWeb y el correspondiente a Juan. El primero proviene de la autenticación de AppWeb ya sea que AppWeb indica su password o utilizando kerberos o mediante un certificado. El segundo conjunto de claims proviene del “Token A” que identifica a Juan en la “Aplicación Web”.

La ejecución de reglas para la obtención del “Token B” alterna operaciones sobre los claims de AppWeb (quien delega) y los claims de Juan (en nombre de quien se actúa).

  1. Se ejecutan las “Delegation Authorization Rules” sobre los claims de AppWeb.
  2. Se ejecutan las “Issuance Authorization Rules” sobre los claims de AppWeb.
  3. Se ejecutan las “Issuance Authorization Rules” sobre los claims de Juan.
  4. Se ejecutan las “Issuance Transform Rules” sobre los claims de AppWeb.
  5. Se ejecutan las “Issuance Transform Rules” sobre los claims de Juan.

Si en alguno de los pasos 1, 2 o 3 no fuese autorizado el ingreso, se aborta la generación del “Token B” en ese paso.

Los claims de entrada para Juan en la obtención del “Token B” son los correspondientes a los claims del “Token A”, obtenido durante la autenticación de Juan a “Aplicación Web”.

Es necesario guardar el token inicial del usuario (Token A), esto se hace poniendo la propiedad saveBootstrapTokens en true (en microsoft.identityModel –> service).

Referencias

Implementando SOLID – LSP

Este es el tercer post de la serie Implementando SOLID, la cual surge de compartir con otros colegas las resoluciones que cada uno implementaría  al aplicar los principios SOLID. En esta ocasión vamos a implementar el principio de sustitución de Liskov pero antes de comenzar les comparto los links a otras resoluciones:

Resolución por Fernando: http://blog.kudewe.com/2012/08/implementando-solid-lsp.html

Liskov substitution principle:

El principio de sustitución de Liskov junto al principio abierta cerrado (OCP) son los que nos definen el camino para aplicar correctamente la herencia en el diseño orientado a objetos. Esto se debe a que, juntos, dan robustez al diseño y con robustez me refiero a la “capacidad para adaptarse a los cambios” en forma estable. Mientras que OCP hace que nuestro diseño pueda evolucionar de forma “segura” (principalmente utilizando herencia), LSP nos marca el camino de esa evolución para no abusar de dicha herencia.

Siguiente con los ejercicios utilizados en el evento, refactorizaremos el llamado LSP.MailBuilder de la siguiente forma:

  1. Ejecutamos los tests, todo verde, empezamos a refactorizar.
  2. Identificamos al método WithEntity de la clase ContactInformationMailBuilder como el objetivo de nuestra refactorización, según LSP no debería ser necesario conocer las clases derivadas de ContactInformation para funcionar, sino que debería funcionar con la clase base (en este caso ContactInformation) siendo sus derivadas las encargadas de extender el comportamiento.
  3. Pasamos el método ParseContactInformation a la clase ContactInformation.
  4. Ejecutamos los tests, todos verde.
  5. Sobrescribimos el método ParseContactInformation en la clase ContactInformationSubsidiary, agregando el comportamiento del método ParseContactInformationSubsidiary.
  6. Ejecutamos los tests, todos verde.
  7. Sobrescribimos el método ParseContactInformation en la clase ContactInformationAuction, agregando el comportamiento del método ParseContactInformationAuction.
  8. Ejecutamos los tests, todos verde.
Unable to display content. Adobe Flash is required.

En este momento, la familia de la clase ContactInformation aun tiene una pequeña responsabilidad en el parseo y es la de determinar la forma de relacionar el nombre de la propiedad con el valor, para solucionar esto hacemos un refactor mas: “Cambiar los parámetros de AddBodyLine a propertyName y propertyValue”.

Unable to display content. Adobe Flash is required.

Por último y para respetar el principio de responsabilidad única (SRP), podríamos hacer que el parser sea un objeto aparte y no una Action (callback), separando así la responsabilidad de parsear un ContactInformation de la de construir un Mail.

Unable to display content. Adobe Flash is required.

 

Otros artículos de la serie:

  • Principio de responsabilidad única
  • Principio abierto / cerrado