En este artículo vamos a hablar de un sistema para realizar autenticación y autorización de forma segura.
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.
¿Por qué son importantes la autenticación y la autorización?
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?
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?
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.)
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
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.
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
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.
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.
Repasemos rápidamente las tablas. Estamos usando 6 mesas.
Usuarios: para almacenar toda la información del usuario.
Credenciales: para almacenar las credenciales de acceso/actualización una vez que el usuario ha sido autorizado.
Contraseñas: para almacenar las contraseñas de usuario cifradas del usuario.
PasswordRequests: para almacenar las solicitudes de cambio de contraseña que llegan para un usuario en particular.
Sesiones: para almacenar cuándo el usuario tuvo una sesión activa y cuándo fue su última actividad.
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
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
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.