Aquí hay muchas preguntas que tratan sobre la mecánica de autenticación y autorización de las API RESTful, pero ninguna de ellas parece entrar en detalles sobre cómo implementar servicios seguros a nivel de aplicación.
Por ejemplo, supongamos que mi aplicación web (tengo en mente Java pero esto se aplica a cualquier backend) tiene un sistema de autenticación seguro que permite a los usuarios de la API iniciar sesión con un nombre de usuario y contraseña. Cuando el usuario realiza una solicitud, en cualquier momento durante el proceso de procesamiento de la solicitud, puedo llamar a un getAuthenticatedUser()
método que devolverá el usuario nulo si el usuario no ha iniciado sesión o un objeto de dominio de Usuario que representa al usuario conectado.
La API permite a los usuarios autenticados acceder a sus datos, por ejemplo, GET para /api/orders/
devolver la lista de pedidos de ese usuario. Del mismo modo, GET to /api/tasks/{task_id}
devolverá datos relacionados con esa tarea específica.
Supongamos que hay varios objetos de dominio diferentes que pueden asociarse con la cuenta de un usuario (los pedidos y las tareas son dos ejemplos, también podríamos tener clientes, facturas, etc.). Solo queremos que los usuarios autenticados puedan acceder a los datos sobre sus propios objetos, por lo que cuando un usuario realiza una llamada, /api/invoices/{invoice_id}
debemos verificar que el usuario esté autorizado para acceder a ese recurso antes de que lo sirvamos.
Mi pregunta es, entonces, ¿existen patrones o estrategias para tratar este problema de autorización? Una opción que estoy considerando es crear una interfaz auxiliar (es decir SecurityUtils.isUserAuthorized(user, object)
), a la que se pueda llamar durante el procesamiento de la solicitud para garantizar que el usuario esté autorizado para recuperar el objeto. Esto no es ideal ya que contamina el código de punto final de la aplicación con muchas de estas llamadas, por ejemplo
Object someEndpoint(int objectId) {
if (!SecurityUtils.isUserAuthorized(loggedInUser, objectDAO.get(objectId)) {
throw new UnauthorizedException();
}
...
}
... y luego está la cuestión de implementar este método para cada tipo de dominio que podría ser un poco difícil. ¡Esta podría ser la única opción, pero me interesaría escuchar sus sugerencias!