SOA / Microservicios: ¿Cómo manejar la autorización en las comunicaciones entre servicios?

18

Primer plano

Estamos pasando de una plataforma monolítica a una arquitectura más orientada al servicio. Estamos aplicando principios DDD muy básicos y dividiendo nuestro dominio en diferentes contextos delimitados. Cada dominio se distribuye y expone un servicio a través de una API web (REST).

Debido a la naturaleza de nuestro negocio, tenemos servicios como reservas , servicios , clientes , productos , etc.

También hemos configurado un servidor de identidad (basado en Thinktecture Identity Server 3) cuya función principal es:

  • Centralice la autenticación (dadas las credenciales que emite tokens)
  • Agregue reclamos en los tokens como: los ámbitos del cliente (según el cliente me refiero a la aplicación que realiza la solicitud), el identificador del cliente (según el cliente me refiero a la persona que usa la aplicación)

También presentamos el rol de una API Gateway que centraliza el acceso externo a nuestros servicios. API Gateway proporciona funcionalidades que no requieren un conocimiento profundo de los dominios internos, tales como:

  • Proxy inverso: enruta las solicitudes entrantes al servicio interno apropiado
  • Control de versiones: una versión de API Gateway se asigna a diferentes versiones de los servicios internos
  • Autenticación: las solicitudes de los clientes incluyen el token emitido por el servidor de identidad y la puerta de enlace API valida el token (asegúrese de que el usuario sea quien dice que es)
  • Limitación: limitar el número de solicitudes por cliente

Autorización

En lo que respecta a la autorización, esto no se gestiona en la API Gateway sino en los servicios internos en sí. Actualmente estamos haciendo 2 tipos principales de autorizaciones:

  • Autorización basada en los ámbitos del cliente. Ejemplo: un cliente (aplicación externa que consume nuestras API) requiere el alcance "reservas" para acceder a los puntos finales de la API del servicio Reservas
  • Autorización basada en el cliente. Ejemplo: solo si un cliente (persona física que utiliza la aplicación) es un participante de una reserva puede acceder al punto final GET / reservas desde el servicio de Reservas

Para poder manejar la autorización en los servicios internos, API Gateway simplemente reenvía el token (al enrutar la solicitud al servicio interno) que incluye tanto la información sobre el cliente (la aplicación que realiza la solicitud) como el cliente como un reclamo (en aquellos casos en los que una persona inicia sesión en la aplicación del cliente).

Descripción del problema

Hasta ahora todo bien hasta que introdujimos la comunicación entre servicios (algunos servicios pueden comunicarse con otros servicios para obtener algunos datos).

Pregunta

¿Cómo debemos abordar la autorización en las comunicaciones entre servicios?

Opciones consideradas

Para discutir las diferentes opciones, usaré el siguiente escenario de muestra:

  • Tenemos una aplicación externa llamada ExternalApp que accede a nuestra API ( ExternalApp puede verse como el cliente ) para construir el flujo de reserva
  • ExternalApp necesita acceso al servicio de reservas , por lo tanto, le otorgamos a ExternalApp el alcance "reservas"
  • Internamente (esto es algo completamente transparente para la aplicación externa ), el servicio de reservas accede al servicio de servicios para obtener los servicios predeterminados de una reserva, como los vuelos, los seguros o el alquiler de un automóvil.

Cuando discutimos este problema internamente, aparecieron varias opciones, pero no estamos seguros de cuál es la mejor:

  1. Cuando Bookings se comunica con los Servicios , simplemente debe reenviar el token original que recibió de API Gateway (lo que indica que el cliente es la aplicación externa )
    • Implicaciones: es posible que debamos otorgar ámbitos a la aplicación externa que no deberían haberse otorgado. Ejemplo: ExternalApp podría necesitar tener el alcance "reservas" y "servicios" mientras que solo el alcance "reservas" podría haber sido suficiente
  2. Cuando Bookings se comunica con los Servicios , reenvía un token que indica que el cliente ahora se ha convertido en Bookings (en lugar de ExternalApp ) + agrega un reclamo que indica que Bookings se hace pasar por el cliente original ExternalApp
    • Al incluir también la información de que el cliente original es el ExternalApp, el servicio de Servicios también podría hacer lógica, como filtrar algunos servicios dependiendo del llamador original (por ejemplo, para aplicaciones internas, deberíamos devolver todas las peleas, para aplicaciones externas solo algunas)
  3. Los servicios no deberían comunicarse entre sí (por lo que ni siquiera deberíamos enfrentar esta pregunta)

Gracias de antemano por sus comentarios.

Josep Serra
fuente
1
Cómo resolviste este problema ? Estamos en una situación similar.
Varun Mehta
+1: Estoy interesado en cómo finalmente resuelves tu problema.
Dypso
Para hacer el punto 3: los servicios no se comunican entre sí, necesita una IU compuesta. Ver particular.net/blog/secret-of-better-ui-composition
stevie_c

Respuestas:

3

Te aconsejo que tengas un canal interno de comunicación entre los microservicios.

Por ejemplo, para utilizar internamente algún intermediario de mensajes como RabbitMQ para enviar / recibir o publicar / suscribir los mensajes entre microservicios.

Luego, su primer servicio para el usuario final "en su ejemplo, el servicio de reserva" será responsable de validar el token y autorizar al cliente a realizar esta operación específica mediante la comunicación con IdentityServer.

Luego se comunicará con el servicio de Servicios a través de Message Broker y, en ese caso, no es necesario volver a validar el token.

Supongo que este modelo será más simple y te dará un mejor rendimiento.

Wahid Bitar
fuente