Estoy construyendo una API RESTful que usa tokens JWT para la autenticación de usuarios (emitida por un login
punto final y enviada en todos los encabezados después), y los tokens deben actualizarse después de un período de tiempo fijo (invocando un renew
punto final, que devuelve un token renovado )
Es posible que la sesión de API de un usuario se vuelva inválida antes de que caduque el token, por lo tanto, todos mis puntos finales comienzan verificando que: 1) el token sigue siendo válido y 2) la sesión del usuario sigue siendo válida. No hay forma de invalidar directamente el token, porque los clientes lo almacenan localmente.
Por lo tanto, todos mis puntos finales deben indicar a mis clientes dos posibles condiciones: 1) que es hora de renovar el token o 2) que la sesión se ha vuelto inválida y ya no se les permite acceder al sistema. Puedo pensar en dos alternativas para que mis puntos finales indiquen a sus clientes cuando se produce una de las dos condiciones (supongamos que los clientes pueden adaptarse a cualquiera de las opciones):
- Devuelve un código http 401 (no autorizado) si la sesión se ha vuelto inválida o devuelve un código 412 (condición previa fallida) cuando el token ha expirado y es hora de llamar al
renew
punto final, que devolverá un código 200 (ok). - Devuelva 401 para indicar que la sesión no es válida o que el token ha expirado. En este caso, el cliente llamará inmediatamente al
renew
punto final, si devuelve 200, el token se actualiza, pero sirenew
también devuelve 401, significa que el cliente está fuera del sistema.
¿Cuál de las dos alternativas anteriores recomendaría? ¿Cuál sería más estándar, más simple de entender y / o más RESTANTE? ¿O recomendarías un enfoque completamente diferente? ¿Ve algún problema obvio o riesgos de seguridad con cualquiera de las opciones? Puntos adicionales si su respuesta incluye referencias externas que respaldan su opinión.
ACTUALIZAR
Chicos, concéntrense en la pregunta real: ¿ cuál de las dos alternativas de código http para señalar una renovación / invalidación de sesión es la mejor? No importa el hecho de que mi sistema usa JWT y sesiones del lado del servidor, esa es una peculiaridad de mi API para reglas comerciales muy específicas, y no la parte para la que busco ayuda;)
fuente
Respuestas:
Esto suena como un caso de autenticación versus autorización .
Los JWT son reclamos firmados criptográficamente sobre el creador de una solicitud. Un JWT puede contener notificaciones como "Esta solicitud es para el usuario X" y "El usuario X tiene roles de administrador". Obtener y proporcionar esta prueba a través de contraseñas, firmas y TLS es el dominio de la autenticación , lo que demuestra que usted es quien dice ser.
Lo que esas afirmaciones significan para su servidor (lo que los usuarios y roles específicos pueden hacer) es el problema de la autorización . La diferencia entre los dos se puede describir con dos escenarios. Supongamos que Bob quiere ingresar a la sección de almacenamiento restringido del almacén de su empresa, pero primero debe tratar con un guardia llamado Jim.
Escenario A - Autenticación
Escenario B - Autorización
Los tiempos de vencimiento de JWT son un dispositivo de autenticación utilizado para evitar que otros los roben. Si todos sus JWT tienen tiempos de vencimiento de cinco minutos, no es tan importante si se los roban porque rápidamente se volverán inútiles. Sin embargo, la regla de "caducidad de la sesión" que discute suena como un problema de autorización. Algún cambio en el estado significa que el usuario X ya no puede hacer algo que solía hacer. Por ejemplo, el usuario Bob podría haber sido despedido; no importa que su credencial diga que ya es Bob, porque el simple hecho de ser Bob ya no le otorga ninguna autoridad con la compañía.
Estos dos casos tienen códigos de respuesta HTTP distintos:
401 Unauthorized
y403 Forbidden
. El código 401, lamentablemente llamado, es para problemas de autenticación tales como credenciales faltantes, caducadas o revocadas. 403 es para autorización, donde el servidor sabe exactamente quién es usted, pero simplemente no tiene permitido hacer lo que intenta hacer. En el caso de que se elimine la cuenta de un usuario, intentar hacer algo con un JWT en un punto final daría como resultado una respuesta 403 Prohibida. Sin embargo, si el JWT caduca, el resultado correcto sería 401 no autorizado.Un patrón JWT común es tener tokens "de larga duración" y "de corta duración". Los tokens de larga duración se almacenan en el cliente como tokens de corta duración, pero tienen un alcance limitado y solo se usan con su sistema de autorización para obtener tokens de corta duración. Los tokens de larga duración, como su nombre lo indica, tienen períodos de vencimiento muy largos; puede usarlos para solicitar nuevos tokens durante días o semanas. Los tokens de corta duración son los que estás describiendo, utilizados con tiempos de vencimiento muy cortos para interactuar con tu sistema. Los tokens de larga duración son útiles para implementar la funcionalidad Remember Me, por lo que no necesita proporcionar su contraseña cada cinco minutos para obtener un nuevo token de corta duración.
El problema de "invalidación de sesión" que está describiendo suena similar a intentar invalidar un JWT de larga duración, ya que los de corta duración rara vez se almacenan en el lado del servidor, mientras que los de larga duración se rastrean en caso de que necesiten ser revocados. En dicho sistema, intentar adquirir credenciales con un token revocado de larga duración daría como resultado 401 no autorizado, porque el usuario técnicamente podría ser capaz de adquirir credenciales, pero el token que están utilizando no es adecuado para la tarea. Luego, cuando el usuario intenta adquirir un nuevo token de larga duración utilizando su nombre de usuario y contraseña, el sistema podría responder con 403 Prohibido si es expulsado del sistema.
fuente
Su sesión de API es algo que no debería existir en un mundo RESTful en absoluto. Se supone que las operaciones RESTful no tienen estado, la sesión contiene estado y, por lo tanto, no tiene lugar en un mundo RESTful.
El JWT debería ser su única forma de determinar si un usuario aún es elegible para acceder a un punto final o no. Una sesión no debe desempeñar absolutamente ningún papel en ella. Si es así, no tiene una API RESTful.
Cuando elimina la sesión por completo, lo que si está buscando una API RESTful que debe hacer, y solo usa el JWT como factor de autenticación, un usuario está autorizado a usar su punto final o no, en cuyo caso el
401 Unauthorized
código de respuesta es apropiado - y debe llamar alrenew
punto final congrant_type=refresh_token
o cualquier identificación de renovación que esté utilizando.Actualizar:
Según el comentario, parece que el flujo de validación del JWT que está utilizando actualmente no es correcto. Se supone que la validación se verá así:
El servidor
RESTful API
tiene que verificar la validez del token que se envía como Autorización. Esa no es responsabilidad delClient
. Parece que actualmente no estás haciendo esto. Implemente la verificación del JWT de esta manera y no necesitará sesiones en absoluto.fuente
Por lo tanto, confesaré que no tiene mucho sentido para mí preocuparme sobre qué enfoque es más RESTANTE cuando ya está rompiendo las convenciones REST con la sesión, pero entiendo que satisface sus requisitos comerciales.
Desde el punto de vista REST, el cliente está autenticado o no. A la arquitectura no le importa mucho por qué (eso es inyectar un estado innecesario), por lo que para responder a su pregunta principal, no tendría un punto final renovado. Un cliente conectado siempre enviará su JWT y el servidor siempre lo validará y lo aceptará enviando el código de éxito apropiado basado en la acción 200, 201, etc.) o lo rechazará con un 401 o 403 según corresponda.
Ahora, el JWT se asociará con una cuenta de algún tipo. Esa cuenta puede estar bloqueada o restringida o lo que sea, por lo que el token en sí puede ser válido, pero la acción aún se rechazará en otro lugar. Si el caso es que la cuenta de usuario está bloqueada debido a las reglas comerciales, entonces sigue siendo un 401 o 403, dependiendo de la cantidad de información que desee proporcionar al cliente (las diferentes empresas tienen diferentes opiniones al respecto).
Finalmente, si está afirmando que la cuenta podría estar desbloqueada y ser válida pero el JWT solo necesita ser revocado, TODAVÍA me quedaría con el 401 o 403 y mantendría algo así como una Lista de revocación de certificados de JWT inválidos en los que puede poner uno , siempre y cuando se limpie cuando JWT haya expirado (la mayoría de las bases de datos tienen una manera de hacerlo o puede tener eventos en el código de la aplicación).
fuente