paint-brush
Diseño de sistemas funcionales de autenticación y autorizaciónpor@iarunava
451 lecturas
451 lecturas

Diseño de sistemas funcionales de autenticación y autorización

por Arunava12m2024/05/05
Read on Terminal Reader

Demasiado Largo; Para Leer

En este artículo vamos a hablar de un sistema para realizar autenticación y autorización de forma segura.
featured image - Diseño de sistemas funcionales de autenticación y autorización
Arunava HackerNoon profile picture
0-item

En este artículo vamos a hablar de un sistema para realizar autenticación y autorización de forma segura. Para empezar, comprendamos cuál es la diferencia entre autenticación y autorización.


  • La autenticación es el proceso de demostrar que usted es quien dice ser al acceder a una aplicación.
  • La autorización es el proceso de definir y hacer cumplir políticas de acceso, es decir, lo que puede hacer una vez que esté autenticado.

En este artículo veremos:



¿Por qué son importantes la autenticación y la autorización?

Autenticación y autorización (fuente: Jeffrey Marvin Forones|Cultura geek. Modificado)


Digamos que estamos en una reunión y usted es el que dirige la conversación. Para solicitar actualizaciones/estado de algo a la persona adecuada, debe identificar (es decir, autenticar ) a la persona. Incluso para compartir algunos datos confidenciales con una persona, es necesario autenticar a la persona correctamente. Y ahí es donde entra en juego la autenticación.


Ahora digamos que en la misma reunión es necesario tomar algunas decisiones. Entonces, para eso, las personas que tienen derecho a tomar esas decisiones deberían ser quienes tomen la llamada, no podemos simplemente permitir que todos hagan todo. Obviamente, algunas personas no están lo suficientemente atendidas como para tomar algunas decisiones, y algunas seguramente intentarán sacar lo peor de ello. Entonces eso trae Authorization , que otorga a ciertas personas los permisos de derechos para ciertas actividades.

¿Cómo funciona la autenticación?

Autenticación basada en tokens; Token de acceso y token de actualización [SPA=SinglePageApplication, RT=RefreshToken, AT=AccessToken, RS=RefreshServer, AS=AuthorizationServer] (Fuente: Okta)


Para autenticar a una persona, podemos asignar una frase única a cada persona, y dado que la persona dice correctamente la frase y su nombre. Podemos decir que está bien, hemos identificado a la persona. Este es el enfoque habitual de nombres de usuarios y contraseñas. Cuando se proporcionan las credenciales correctas, un sistema considera válida la identidad y otorga acceso. Esto se conoce como 1FA o autenticación de factor único (SFA).


SFA se considera bastante insegura. ¿Por qué? Porque los usuarios son notoriamente malos a la hora de mantener segura su información de inicio de sesión. La autenticación multifactor (MFA) es una alternativa más segura que requiere que los usuarios demuestren su identidad de más de una manera. Algunas de estas formas son:


  • Números PIN de un solo uso / OTP
  • Aplicaciones de autenticación ejecutadas por terceros seguros (por ejemplo, Google/Microsoft Authenticator)
  • Biometría


Una vez autenticada, la persona seguiría realizando acciones libremente en la aplicación. Y se espera que la aplicación reconozca a la persona durante todo su recorrido sin olvidarla. Idealmente, sería demasiado pedirle al usuario que proporcione la contraseña cada vez que se mueve a una página diferente o realiza alguna actividad. Por lo tanto, necesitamos una forma de mantener al usuario autenticado después de haber ingresado sus credenciales y haber sido autenticado una vez. Esto se llama Gestión de sesiones .


2 formas de mantener al usuario autenticado:

  • Autenticación basada en sesión : cuando un usuario inicia sesión en un sitio web en un navegador, el servidor crea una sesión para ese usuario y le asigna un ID de sesión. El servidor almacena este ID de sesión como referencia y se envía de vuelta al usuario para que lo almacene en una cookie en el navegador. Ahora, cada vez que el usuario realice una solicitud, el navegador enviará el ID de sesión junto con la solicitud. Lo que ayudará a autenticar la solicitud. Y, así, preservar la autenticación mientras el usuario esté en el sitio.
  • Autenticación basada en token : para esto, el servidor crea un token cifrado que se envía al usuario y lo guarda únicamente el navegador, como cookies HttpOnly. Toda la información requerida, como la información del usuario, los permisos y la caducidad del token, están cifradas dentro del token. El token se envía junto con las llamadas al servidor. El servidor simplemente descifra el token con la clave secreta y verifica al usuario. Este token se actualiza a intervalos.


La principal diferencia entre estos dos enfoques sería que la autenticación basada en token es Stateless , ya que el token no necesita almacenarse en el lado del servidor. Pero para la autenticación basada en sesiones, el token también debe almacenarse en el lado del servidor, lo que lo convierte en Stateful . Lo que trae complicaciones cuando el sistema se escala o crece el número de usuarios.


Para la autenticación basada en tokens, utilizamos principalmente JWT (JSON Web Tokens).

¿Cómo funciona la autorización?

Control de autorización basado en roles (RBAC) (fuente: Ajay Shekhawat | Dribble)

Una vez que el usuario esté autenticado, aún necesitaremos asegurarnos de que solo pueda acceder a los recursos para los que tenga permiso. El acceso no autorizado a datos confidenciales puede ser un desastre. Según el principio de privilegio mínimo, las empresas normalmente establecerían políticas de acceso de modo que, de forma predeterminada, usted tenga acceso a lo que necesita absolutamente. Y luego, en progresión, tendrá acceso adicional. Las formas comunes de segmentar el acceso son:


  • Control de acceso basado en roles (RBAC) : los usuarios se asignan a un determinado grupo/rol que viene con permisos establecidos. Ejemplos: administrador, miembro, propietario.
  • Control de acceso basado en políticas (PBAC) : determina dinámicamente los privilegios de acceso durante la autorización en función de políticas y reglas. Las políticas se basan en roles de usuario, funciones laborales y requisitos organizacionales.
  • Control de acceso basado en atributos (ABAC) : a los usuarios se les permite el acceso según atributos como título, certificación, capacitación y/o factores ambientales como la ubicación.
  • Listas de control de acceso (ACL) : cada usuario o entidad tiene permisos individuales que se pueden activar o desactivar, similar a instalar una nueva aplicación en su teléfono y decidir qué permisos otorgar (servicios de ubicación, contactos, etc.)


Una pantalla para Listas de Control de Acceso (fuente: Povio)


ACL se usa con más frecuencia a nivel granular que ABAC o RBAC; por ejemplo, para otorgar acceso a usuarios individuales a un determinado archivo. ABAC y RBAC generalmente se instituyen como políticas para toda la empresa.


Diseño del sistema de autenticación

Diseño del sistema de autenticación y autorización (fuente: InterviewPen. Modificado)

Requisitos

Primero comencemos por definir los requisitos funcionales del sistema:

  • Registro : Permitir que los usuarios se registren proporcionando la información necesaria.
  • Iniciar sesión : autentica a los usuarios según sus credenciales.
  • Gestión de sesiones : administre de manera eficiente las sesiones de los usuarios para garantizar la seguridad.
  • Recuperación de contraseña : proporciona un proceso seguro para que los usuarios recuperen sus contraseñas.
  • Control de acceso : defina roles y permisos para diferentes tipos de usuarios.
  • Seguimiento de auditoría : mantenga registros detallados de los eventos de autenticación para realizar auditorías.
  • Rendimiento : garantice una baja latencia y tiempos de respuesta rápidos.


Algunos requisitos no funcionales que no vamos a considerar en el alcance de este artículo son:

  • Autenticación multifactor (MFA) : implemente un sistema MFA sólido.
  • Seguridad : Priorice la seguridad de los datos mediante cifrado, almacenamiento seguro y comunicación segura.
  • Escalabilidad : Diseñe el sistema para manejar un número creciente de usuarios y transacciones.
  • Fiabilidad : Minimice el tiempo de inactividad del sistema y garantice una alta disponibilidad.
  • Usabilidad : desarrolle una interfaz de usuario intuitiva para una experiencia perfecta.


Estimación de capacidad

Estimación de tráfico

Primero, comencemos con la estimación del tráfico . Suponiendo un tráfico promedio de 100.000 por mes, estimamos un tráfico de 100.000 usuarios por mes. Lo que se traduce en 0,04 solicitudes por segundo. Necesitaríamos responder a cada solicitud dentro de 500 ms el 90% del tiempo, es decir, requerimos una latencia p90 de 500 ms.


 assumed_traffic_per_month = 100000 #requests assumed_traffic_per_day = assumed_traffic_per_month / 30 ~= 3350 (assuming on higher end; 3333.33 to be precise) estimated_time_per_request = 500 #ms; P90 of 500ms traffic_per_second = (assumed_traffic_per_month) / (30*24*60*60) = 0.04


Objetivo de nivel de servicio (SLO) : 500 ms (latencia máxima aceptable, independientemente de la carga del sistema). La capacidad promedio que puede tomar 1 instancia, según nuestros cálculos, es de aproximadamente 35 ms para atender una solicitud, suponiendo que no se realice ningún procesamiento pesado para la petición particular.


Generemos dos métricas derivadas más utilizando las métricas anteriores.

  • Capacidad : Trabajo pendiente aceptable por instancia: Número máximo de solicitudes (carga) que puede aceptar una instancia, sin comprometer el SLO.
  • Demanda : Trabajo pendiente por instancia: Número total de solicitudes (carga) que fluyen hacia una unidad/instancia en función del tráfico actual.

De este modo,

 SLO = 500ms approx_response_time_for_one_request = 35 #ms capacity = SLO/approx_response_time_for_one_request = 500 / 35 ~= 20 load_on_one_instance = 0.04 instances_available = 1 demand = traffic_per_second / instances_available = 0.04


Con la demanda y la capacidad disponibles, calculemos el número total de instancias necesarias.

 total_units_required = demand / capacity = 0.04 / 20 = 0.002 ~= 1

Por lo tanto, podríamos manejar fácilmente 100.000 solicitudes por mes, con 0,04 solicitudes por segundo, con 1 instancia. Donde cada unidad puede manejar 20 solicitudes por segundo sin comprometer el SLO.


Estimación de almacenamiento

Idealmente, necesitaríamos almacenar los detalles de cada usuario para el acceso de autenticación y autorización. Suponiendo, 5kb/usuario

 monthly_new_users = 500 monthly_additional_storage = 500 * 5kb = 2500kb ~= 2GB


Entonces, cada mes, suponiendo que incorporemos 500 nuevos usuarios, necesitaremos 2 GB más de almacenamiento. En caso de que quisiéramos mantener registros de autenticación. Se espera que cada solicitud de autenticación requiera 2 kb para almacenarse.

 auth_request_size = 2kb #assumption monthly_storage = monthly_visitors * auth_request_size = 100,000 * 2KB ~= 200MB

Así, cada mes requeriríamos 200 MB adicionales, suponiendo un tráfico mensual de 100k.

Diseño de base de datos

Ahora que hemos realizado la estimación de capacidad. Creemos los esquemas de la base de datos necesarios para soportar los requisitos funcionales.

Esquema de base de datos de autenticación y autorización

Repasemos rápidamente las tablas. Estamos usando 6 mesas.

  1. Usuarios: para almacenar toda la información del usuario.
  2. Credenciales: para almacenar las credenciales de acceso/actualización una vez que el usuario ha sido autorizado.
  3. Contraseñas: para almacenar las contraseñas de usuario cifradas del usuario.
  4. PasswordRequests: para almacenar las solicitudes de cambio de contraseña que llegan para un usuario en particular.
  5. Sesiones: para almacenar cuándo el usuario tuvo una sesión activa y cuándo fue su última actividad.
  6. ActivityApproval: para almacenar solicitudes de aprobación para una actividad realizada por un usuario en particular, que sería verificada por el administrador.


Diseño de alto nivel para el sistema de autenticación

Autenticación y autorización HLD

Puntos finales del sistema

Punto final

Descripción

/acceso

Autenticar las credenciales del usuario.

/cerrar sesión

Finalice la sesión del usuario y revoque los tokens de autenticación.

/registro

Crea un nuevo usuario.

/actualización/:ID de usuario

Actualizar la información del usuario.

/eliminar/:ID de usuario

Eliminar una cuenta de usuario.

/grant/:userId/:permiso

Otorgar permisos específicos a un usuario.

/revocar/:ID de usuario/:permiso

Revocar permisos de un usuario.

/check/:userId/:recurso

Verifique el acceso del usuario a un recurso específico.

/crear/:id de usuario

Crea una nueva sesión de usuario.

/expire/:id de sesión

Caducar una sesión de usuario.

/validar/:id de sesión

Validar una sesión de usuario activa.


Cumplimiento de requisitos

Ahora, con todo lo que tenemos en su lugar, veamos cómo podemos completar todos los requisitos.


Registro


  • Requisito : cuando un nuevo usuario visita nuestra aplicación. Necesitamos almacenar los detalles del usuario para poder autorizar/identificar al usuario la próxima vez que lo visite.
  • Cumplido : cuando un nuevo usuario visita la aplicación e ingresa los detalles del usuario junto con su correo electrónico y contraseña. Eso quedará capturado en la base de datos. Los detalles del usuario se almacenarán en la tabla Usuario. Y la contraseña se almacenará en la tabla de credenciales de forma cifrada.


Acceso

  • Requisito : cuando un usuario existente visita nuestra aplicación. Necesitamos identificar al usuario para poder autorizar/identificar sus acciones y mostrarle datos que le pertenecen.
  • Cumplido : cuando un usuario existente visita la aplicación e ingresa sus datos, correo electrónico y contraseña. Realizamos un hash de la contraseña y lo comparamos con el hash almacenado para el usuario en la tabla de credenciales. Si coincide, hemos podido identificar al usuario correctamente. De lo contrario, deberán ingresar la contraseña correcta que ingresaron al registrarse. Este proceso se llama Autenticación .


Gestión de sesiones

  • Requisito : cuando un usuario se ha autenticado, ingresando su usuario y contraseña. Necesitamos asegurarnos de que permanezcan conectados mientras realizan sus acciones futuras o intentan ver datos confidenciales, sin que tengan que volver a ingresar su contraseña una y otra vez.
  • Cumplido : cuando el usuario se autentica exitosamente. El servidor de autenticación compartirá 2 tokens con el cliente. Un token_acceso y un token_actualización . El token de acceso puede tener datos cifrados y tiene un tiempo de caducidad corto por razones de seguridad. Una vez que el cliente tiene el token de acceso, lo devuelve junto con cada solicitud, lo que ayuda a autenticar la solicitud. Cuando el token de acceso caduca, el cliente debe solicitar un nuevo token de acceso utilizando el token de actualización proporcionado. Esto ayuda a mantener una sesión.


Recuperación de contraseña

  • Requisito : cuando un usuario olvida su contraseña, deberá poder restablecerla de forma segura.
  • Cumplido : cuando el usuario olvida su contraseña, puede enviar su dirección de correo electrónico en la página de contraseña olvidada, generaremos un código único y le enviaremos el enlace a su correo electrónico. Cuando el usuario hace clic en este enlace con el código y la dirección de correo electrónico. Podremos identificar de forma segura que la solicitud de recuperación de contraseña es auténtica. Y proporcione al usuario la posibilidad de establecer su nueva contraseña. Y así poder recuperar la contraseña.


Control de acceso

  • Requisito : cuando un usuario realiza una determinada acción, debemos asegurarnos de que el usuario esté autenticado para realizar esa acción y solo entonces permitir que se lleve a cabo.
  • Cumplido : mantendremos una lista de acciones, digamos del 1 al 12, para simplificar. Para cada usuario mantendremos las acciones autenticadas para ese usuario. Ahora digamos que el usuario intenta realizar una acción #id 4. Verificaremos si el usuario tiene los permisos para realizar la acción 4. En caso afirmativo, continuaremos y completaremos la solicitud. De lo contrario, mostramos que la solicitud no se realizó correctamente debido a la falta de permisos.


Pista de auditoría

  • Requisito : en caso de un incidente de seguridad, deberíamos poder tener suficientes registros para revisar y tener una razón plausible de lo que pudo haber sucedido o cualquier pista sobre cuál podría haber sido una posible causa del mismo.
  • Cumplido : para tales escenarios, podemos mantener registros de cada acción de autenticación que ocurre en el servidor. (a). Para cada solicitud de inicio de sesión, mantendremos un registro de cuándo ocurrió la autenticación, desde dónde, IP y otros detalles relevantes. (b). Para cada solicitud de recuperación de contraseña, mantendremos un registro de cuándo se inició, desde dónde, ips, si la solicitud se completó y otros detalles relevantes. (C). Además, mantendremos registros cada vez que un usuario esté autorizado o no autorizado para una acción y por quién. Estos registros en conjunto deberían poder indicar lo que podría haber sucedido en caso de intentar comprender algún escenario.


Actuación

  • Requisito : el requisito de rendimiento, como se analiza en la sección de estimación de capacidad, es de 0,04 solicitudes/segundo y 100 000 solicitudes por mes.
  • Cumplido : ya hemos manejado el requisito con suficientes servidores en la sección de estimación de capacidad.

Conclusión

Autenticación versus autorización (fuente: OutSystems)

En este artículo, comenzamos por comprender cuál es la diferencia entre autenticación y autorización. A continuación, creamos un Sistema de Autenticación y Autorización. Que sea seguro, ofrezca rendimiento y al mismo tiempo cumpla con los estándares de la industria y cumpla con todos los requisitos deseados. En el futuro, podría actualizar ciertas partes del artículo para que siga siendo relevante y para cubrir más información y conocimientos sobre la construcción de dicho sistema.