Todavía estoy tratando de encontrar la mejor solución de seguridad para proteger la API REST, porque la cantidad de aplicaciones móviles y API aumenta cada día.
He intentado diferentes formas de autenticación, pero todavía tengo algunos malentendidos, por lo que necesito el consejo de alguien más experimentado.
Déjame decirte cómo entiendo todo esto. Si entiendo algo incorrectamente, avíseme.
En la medida en que la API REST no tiene estado y la WEB en general, debemos enviar algunos datos de autenticación en cada solicitud (cookies, token ...). Conozco tres mecanismos ampliamente utilizados para autenticar usuarios
Token con HTTPS. He usado este enfoque muchas veces, es lo suficientemente bueno con HTTPS. Si el usuario proporciona la contraseña y el inicio de sesión correctos, recibirá un token en respuesta y lo usará para otras solicitudes. La ficha es generada por el servidor y almacenada, por ejemplo, en la tabla separada o la misma donde se almacena la información del usuario. Entonces, para cada solicitud, el servidor verifica si el usuario tiene un token y es el mismo que en la base de datos. Todo es bastante sencillo.
Token JWT. Este token es autodescriptivo, contiene toda la información necesaria sobre el token en sí, el usuario no puede cambiar, por ejemplo, la fecha de vencimiento o cualquier otro reclamo, porque este token es generado (firmado) por el servidor con una palabra clave secreta. Esto también está claro. Pero un gran problema, personalmente para mí, es cómo invalidar el token.
OAuth 2. No entiendo por qué este enfoque debería usarse cuando la comunicación se establece directamente entre el servidor y el cliente. Según tengo entendido, el servidor OAuth se usa para emitir tokens con un alcance restringido para permitir que otras aplicaciones accedan a la información del usuario sin almacenar la contraseña y el inicio de sesión. Esta es una gran solución para las redes sociales, cuando el usuario desea registrarse en alguna página, el servidor puede solicitar permisos para obtener información del usuario, por ejemplo de Twitter o Facebook, y llenar los campos de registro con datos del usuario, etc.
Considere el cliente móvil para la tienda en línea.
Primera pregunta, ¿debería preferir JWT sobre el primer tipo de token? En la medida en que necesite un usuario de inicio de sesión / cierre de sesión en el cliente móvil, necesito almacenar un token en algún lugar o, en el caso de JWT, el token debe invalidarse al cerrar sesión. Se utilizan diferentes enfoques para invalidar el token, uno de los cuales es crear una lista de tokens no válida (lista negra). Hmm La tabla / archivo tendrá un tamaño mucho mayor que si el token se almacenara en la tabla y se asociara con el usuario, y simplemente se eliminara al cerrar sesión.
Entonces, ¿cuáles son los beneficios del token JWT?
Segunda pregunta sobre OAuth, ¿debería usarla en caso de comunicación directa con mi servidor? ¿Cuál es el propósito de una capa más entre el cliente y el servidor solo para emitir token, pero la comunicación no será con el servidor oauth sino con el servidor principal? Según tengo entendido, el servidor OAuth es responsable solo de otorgar permisos de aplicaciones de terceros (tokens) para acceder a la información privada del usuario. Pero mi aplicación de cliente móvil no es de terceros.
Respuestas:
Considere el primer caso. Cada cliente obtiene una identificación aleatoria que dura la duración de la sesión, que podría ser de varios días si lo desea. Luego almacena la información relevante para esa sesión en algún lado del servidor. Podría estar en un archivo o una base de datos. Supongamos que pasa la identificación a través de una cookie pero podría usar la URL o un encabezado HTTP.
ID de sesión / Cookies
Pros:
Contras:
Tokens web JSON (JWT)
En el segundo caso, los datos se almacenan en un JWT que se pasa en lugar de en el servidor.
Pros:
Contras:
El lado del servidor necesita código para generar, validar y leer JWT. No es difícil, pero hay una pequeña curva de aprendizaje y la seguridad depende de ello.
Cualquiera que obtenga una copia de la clave de firma puede crear JWT. Es posible que no sepa cuándo sucede esto.
Hubo (¿hay?) Un error en algunas bibliotecas que aceptaba cualquier JWT firmado con el algoritmo "ninguno" para que cualquiera pudiera crear JWT en los que el servidor confiara.
Para revocar un JWT antes de que caduque, debe usar una lista de revocación. Esto lo lleva de regreso a los problemas de almacenamiento del lado del servidor que intentaba evitar.
OAuth
A menudo, OAuth se usa para autenticación (es decir, identidad), pero se puede usar para compartir otros datos, como una lista de contenido que el usuario ha comprado y tiene derecho a descargar. También se puede usar para otorgar acceso para escribir en los datos almacenados por el tercero. Puede usar OAuth para autenticar a los usuarios y luego usar el almacenamiento del lado del servidor o JWT para los datos de la sesión.
Pros:
Contras:
Diverso
fuente
Pregúntese por qué necesita invalidar el token original.
Un usuario inicia sesión, se genera un token y se apaga la aplicación.
El usuario presiona cerrar sesión, se genera un nuevo token y reemplaza el token original. Una vez más, todo está bien.
Parece que te preocupa el caso en el que ambas fichas cuelgan. ¿Qué pasa si el usuario cierra sesión y luego de alguna manera realiza una solicitud utilizando el token conectado? ¿Cuán realista es este escenario? ¿Es solo un problema durante el cierre de sesión o hay muchos escenarios posibles donde múltiples tokens pueden ser un problema?
Yo mismo no creo que valga la pena preocuparse. Si alguien está interceptando y decodificando sus datos https encriptados, entonces tiene problemas mucho mayores.
Puedes darte una protección adicional poniendo un tiempo de vencimiento en el token original. Entonces, si termina siendo robado o algo así, solo sería bueno por un corto período de tiempo.
De lo contrario, creo que necesitaría tener información de estado en el servidor. No ponga en la lista negra los tokens, sino que incluya en la lista blanca la firma del token actual.
fuente
Puede manejar los problemas de JWT que mencionó almacenando un valor de sal junto con el usuario y utilizando la sal como parte del token para el usuario. Luego, cuando necesite invalidar el token, simplemente cambie la sal.
Sé que han pasado un par de años, pero ahora lo haría de manera diferente. Creo que me aseguraría de que los tokens de acceso tuvieran una vida relativamente corta, digamos una hora. También me aseguraría de usar tokens de actualización con estado en el servidor y luego, cuando quisiera finalizar la sesión de alguien, revocaría el token de actualización eliminándolo del servidor. Luego, después de una hora, el usuario cerrará sesión y tendrá que iniciar sesión nuevamente para recuperar el acceso.
fuente