Sistema de autorización y autenticación para microservicios y consumidores.


15

Planeamos refactorizar el sistema de nuestra compañía en un sistema basado en microservicios. Estos microservicios serán utilizados por nuestras propias aplicaciones internas de la compañía y por socios externos si es necesario. Uno para reservar, uno para productos, etc.

No estamos seguros de cómo manejar roles y ámbitos. La idea es crear 3 roles de usuario básicos, como administradores, agentes y usuarios finales, y permitir que las aplicaciones de los consumidores ajusten los ámbitos si es necesario.

  • Los administradores pueden crear, actualizar, leer y eliminar todos los recursos de forma predeterminada (para su empresa).
  • Los agentes pueden crear, actualizar y leer datos para su empresa.
  • Los usuarios finales pueden crear, actualizar, eliminar y leer datos, pero no pueden acceder a los mismos puntos finales que los agentes o administradores. También podrán crear o modificar datos, pero no en el mismo nivel que los agentes o administradores. Por ejemplo, los usuarios finales pueden actualizar o leer la información de su cuenta, igual que el agente podrá hacerlo por ellos, pero no pueden ver ni actualizar las notas del administrador.

Digamos que los agentes por defecto pueden crear, leer y actualizar cada recurso para su empresa y ese es su alcance máximo que se puede solicitar para su token / sesión, pero los desarrolladores de la aplicación cliente (API consumidor) han decidido que uno de sus agentes puede leer y crear solo ciertos recursos.

¿Es una mejor práctica manejar esto en nuestra seguridad interna y dejar que escriban esos datos en nuestra base de datos, o dejar que los clientes lo manejen internamente solicitando un token con menor alcance y dejar que escriban qué agente tendrá qué alcance en su base de datos? ? De esta manera, tendríamos que rastrear solo los alcances de token.

La desventaja de esto es que nuestro equipo también necesitaría crear mecanismos de acceso ajustados en nuestras aplicaciones internas.

Con esta forma de pensar, los microservicios y su sistema de autorización no deben preocuparse por las necesidades de los clientes, ya que son solo consumidores y no parte del sistema (a pesar de que algunos de esos consumidores son nuestras propias aplicaciones internas).

¿Es esta delegación un buen enfoque?

Respuestas:


14

La autenticación y la autorización son siempre buenos temas.

Trataré de explicarle cómo manejamos las autorizaciones en el servicio multiinquilino actual en el que estoy trabajando. La autenticación y la autorización se basan en tokens, utilizando el estándar abierto JSON Web Token. El servicio expone una API REST a la que puede acceder cualquier tipo de cliente (aplicaciones web, móviles y de escritorio). Cuando un usuario se autentica correctamente, el servicio proporciona un token de acceso que debe enviarse en cada solicitud al servidor.

Permítanme presentarles algunos conceptos que utilizamos en función de cómo percibimos y tratamos los datos en la aplicación del servidor.

Recurso : es cualquier unidad o grupo de datos a los que un cliente puede acceder a través del servicio. A todos los recursos que queremos controlar les asignamos un solo nombre. Por ejemplo, teniendo las siguientes reglas de punto final podemos nombrarlas de la siguiente manera:

product

/products
/products/:id

payment

/payments/
/payments/:id

order

/orders
/orders/:id
/orders/:id/products
/orders/:id/products/:id

Entonces, digamos que hasta ahora tenemos tres recursos en nuestro servicio; product, paymentY order.

Acción : es una operación que se puede realizar en un recurso, como leer, crear, actualizar, eliminar, etc. No es necesario ser solo las operaciones CRUD clásicas, puede tener una acción llamada follow, por ejemplo, si desea exponer un servicio que propaga algún tipo de información utilizando WebSockets.

Habilidad : La capacidad de realizar un actionen un resource. Por ejemplo; leer productos, crear productos, etc. Básicamente es solo un par recurso / acción. Pero también puede agregarle un nombre y una descripción.

Rol : Un conjunto de habilidades que un usuario puede poseer. Por ejemplo, un rol Cashierpodría tener las capacidades "leer pago", "crear pago" o un rol Sellerpuede tener las capacidades "leer producto", "leer pedido", "actualizar pedido", "eliminar pedido".

Finalmente, un usuario puede tener varios roles asignados a él.


Explicación

Como dije antes, usamos JSON Web Token y las capacidades que posee un usuario se declaran en la carga útil del token. Entonces, supongamos que tenemos un usuario con los roles de cajero y vendedor al mismo tiempo, para una pequeña tienda minorista. La carga útil se verá así:

{
    "scopes": {
        "payment": ["read", "create"],
        "order": ["read", "create", "update", "delete"]
    }
}

Como puede ver en el scopesreclamo, no especificamos el nombre de los roles (cajero, vendedor), en cambio, solo se especifican los recursos y las acciones implicadas. Cuando un cliente envía una solicitud a un punto final, el servicio debe verificar si el token de acceso contiene el recurso y la acción requerida. Por ejemplo, una GETsolicitud al punto final /payments/88será exitosa, pero una DELETEsolicitud al mismo punto final debe fallar.


  • Los desarrolladores decidirán cómo agrupar y nombrar los recursos y cómo definir y nombrar las acciones y habilidades .

  • Cuáles son los roles y qué habilidades tendrán esos roles, son decisiones tomadas por los clientes.


Por supuesto, debe agregar propiedades adicionales a la carga útil para identificar al usuario y al cliente (inquilino) que emitió el token.

{
    "scopes": {
        ...
    },
    "tenant": "acme",
    "user":"coyote"
}

Con este método, puede ajustar el acceso de cualquier cuenta de usuario a su servicio. Y lo más importante, no tiene que crear varios roles estáticos y predefinidos, como Admin, Agentes y Usuarios finales, como señala en su pregunta. Un Super User será un usuario que posee una rolecon toda la resourcesy actionsdel servicio asignado a la misma.

Ahora, ¿qué pasa si hay 100 recursos y queremos un rol que dé acceso a todos o casi todos? Nuestra carga de token sería enorme. Eso se resuelve anidando los recursos y simplemente agregando el recurso principal en el alcance del token de acceso.


La autorización es un tema complicado que debe abordarse en función de las necesidades de cada aplicación.


Gracias por su respuesta. Esto es muy útil. Tengo una pregunta relacionada con múltiples roles por usuario. ¿Alguna vez ha tenido un caso donde los permisos de roles se superponen? Tal como el cajero tiene payment:[read], el vendedor tiene payment: [create]. ¿Agrega permisos en este caso?
Robert

Si tiene roles con habilidades repetidas (resource/action), debe fusionarlos. Si los permisos se superponen, debe agregarlos. La idea es definir solo los recursos y las acciones permitidas en el token, dejando los roles como una abstracción utilizada para dar a los clientes una forma menos complicada de lidiar con la autorización.
miso

1
¿Qué pasa si un usuario solo puede tener la capacidad de tomar medidas sobre los recursos que posee? Al igual que una cuenta bancaria, por ejemplo, seguramente "bank_account": ["leer", "actualizar"] no especifica eso. Además, ¿exactamente DÓNDE se lleva a cabo el proceso de autorización en un sistema de microservicios? En un servidor de autorización centralizado, ¿o cada servicio tiene su propia autorización?
rocketspacer

@rocketspacer. Es por eso que el token tiene la userpropiedad en su carga útil. La forma en que bloqueo un recurso propiedad de un usuario es asignando el userreclamo a la URL. Por ejemplo: /users/coyote/back-accountsería accesible solo por un token con userreclamo igual a coyote. Espero que te sirva de ayuda.
miso

3

Creo que pase lo que pase, querrá que sus servicios acepten un token de autenticación proporcionado por un servicio de autenticación que escriba para validar a los usuarios. Esta es la forma más directa / segura de evitar el mal uso de sus microservicios. Además, en general, si desea que un cliente tenga una buena experiencia, debe implementar las características críticas usted mismo y realizar pruebas exhaustivas para asegurarse de que las características que ofrece estén bien implementadas.

Dado que todas las personas que llaman deben proporcionar a sus microservicios evidencia de que se han autenticado, también puede vincular los permisos a esa autenticación. Si proporciona la capacidad de vincular a un usuario a un grupo de acceso arbitrario (o grupos si desea hacerse más sofisticado, aunque los permisos de agregar versus restar son más difíciles de tratar aquí), sus clientes recibirán menos preguntas sobre por qué el usuario x pudo realizar una operación no deseada. En cualquier caso, alguien tiene que hacer una verificación de la lista de acceso para cada servicio, por lo que también puede ser usted. Es algo que se codificaría muy fácilmente al comienzo de todos los servicios (if ( !TokenAuthorized(this.ServiceName, this.token) { Raise error }) Que también puede hacerlo y realizar un seguimiento de los grupos de usuarios usted mismo. Es cierto que tendrá que tener un administrador de grupo de permisos y trabajarlo en la interfaz de usuario de administración de usuarios (use el grupo existente / cree un nuevo grupo para los permisos de usuario) Definitivamente enumere los usuarios vinculados a un grupo cuando edite la definición, para evitar confusiones . Pero, no es un trabajo duro. Solo tenga metadatos para todos los servicios y conecte la búsqueda entre el grupo y el servicio en el manejo de token de autenticación.

De acuerdo, hay bastantes detalles, pero cada uno de sus clientes que deseen esta funcionalidad tendría que codificar esto en cualquier caso, y si admite los permisos de usuario de tres niveles, también puede extenderlo para que sea por acceso de usuario grupos Probablemente, una intersección lógica entre los permisos del grupo base y los permisos específicos del usuario sería la agregación correcta, pero si desea poder agregar y quitar permisos base, de los permisos de base de administrador, agente y usuario final, deberá hacerlo el indicador de tres estados ususal en los grupos de permisos: Agregar permiso, Denegar permiso, Permiso predeterminado y combinar permisos de manera adecuada.

(Como nota, todo esto debería suceder por algo como SSL o incluso SSL bidireccional si le preocupa la seguridad de ambos extremos de la conversación. Si "filtra" estas fichas a un atacante, él está como si él " d descifró una contraseña)


Mientras pensaba en la infraestructura y la implementación, me olvidé por completo de la experiencia del cliente. Me gusta la idea de crear un conjunto de reglas que sean más adecuadas para nuestro negocio. Los administradores, agentes y usuarios finales son demasiado genéricos y planeamos implementar más tipos de usuarios, que son más descriptivos y vinculados con nuestro negocio y nuestro lenguaje ubicuo.
Robert

No pude corregir el error tipográfico "anded" en la última oración porque no podía entenderlo.
Tulains Córdova

No es necesariamente un error tipográfico, pero lo
aclararé

1

Mi opinión es que tienes dos opciones aquí.

  • Si solo necesita tener acceso configurable a la misma aplicación, haga que los servicios verifiquen los permisos y brinden a sus clientes una interfaz que les permita cambiar los permisos otorgados a cada rol. Esto permite a la mayoría de los usuarios utilizar la configuración de roles predeterminada, que los clientes 'problemáticos' pueden modificar o crear roles nuevos para satisfacer sus necesidades.

  • Si sus clientes están desarrollando sus propias aplicaciones, deben presentar su propia API intermedia. Que se conecta con la suya como administrador, pero verifica la solicitud entrante con sus propios requisitos de autenticación personalizados antes de llamar a sus servicios


1

Consideración de seguridad

Si entiendo bien su diseño, tiene la intención de delegar algunos mecanismos de control de acceso a recursos en el lado del cliente, es decir, una aplicación que consume reduce los elementos que un usuario puede ver. Su suposición es:

los microservicios y su sistema de autorización no deben preocuparse por las necesidades de los clientes, ya que solo son consumidores y no forman parte del sistema

Veo aquí dos problemas serios para negocios serios:

  • ¿Qué sucede si un usuario malintencionado (por ejemplo, en una de las plantas de su socio) aplica ingeniería inversa a la aplicación del cliente y se entera de la API, elude las restricciones que su empresa ha impuesto al cliente y utiliza esa información para perjudicar a su empresa? Su empresa reclamará daños, pero la empresa parnter argumentará que usted no dio los medios para proteger sus datos lo suficientemente bien.
  • Por lo general, es solo cuestión de tiempo que los datos confidenciales se usen incorrectamente (o la auditoría descubrirá el riesgo) y su gerencia terminará pidiendo un control más estricto de esos datos.

Es por eso que aconsejaría anticipar tales eventos y atender las solicitudes de autorización. Está en una fase de reingeniería temprana y será mucho más fácil tenerlos en cuenta en su arquitectura (incluso si no los implementa todos) que más adelante.

Si continúa con su puesto actual, consulte al menos a su oficial de seguridad de la información.

Cómo implementarlo

Tienes el truco:

De esta manera, tendríamos que rastrear solo los alcances de token.

Ok, tiene la intención de utilizar algunos tokens generales elegidos por el cliente. Otra vez una debilidad en mi ojo, porque algunos clientes pueden estar fuera de su control.

No sé si ya usa JWT o si usa otras técnicas. Pero si usa JWT, podría tener un token de identidad que lleve la identidad del usuario (e incluso un segundo token que identifique de forma segura la aplicación de origen, lo que podría permitirle diferenciar el nivel de confianza entre clientes internos y clientes externos) )

Como tiene la intención de optar por una arquitectura de microservicio, me gustaría sugerir que marque la diferencia entre la gestión de usuarios y el proceso de autenticación (que debe ejecutarse como un servicio dedicado) y el control de acceso (que es específico de cada microservicio, y debería ser manejado localmente por cada uno de ellos). Por supuesto, algún cliente administrador debe ofrecer una visión general completa de varios servicios, para facilitar su uso).


1
Muy buen consejo aquí. Me gusta la idea con el segundo token.
Robert

1

Aquí, también hay una respuesta corta. Debe implementar todas las funciones principales que desea ofrecer a sus "clientes" usted mismo. Parece problemático que los clientes agreguen un comportamiento tan fundamental como los permisos de los usuarios, ya que ya está realizando la autenticación de usuario; si deja que el cliente lo implemente, puede terminar "admitiendo" múltiples implementaciones del mismo código de permisos. Aunque no lo "posea", habrá errores en su código y desea que sus clientes tengan la funcionalidad que esperaban, dentro de lo razonable, por lo que respalda la resolución de los problemas que tiene un cliente. Soportar múltiples bases de código no es divertido.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.