Autenticación y Autorización

Cuando estamos diseñando una aplicación web, tenemos una serie de acciones que puede realizar cualquier usuario y otra serie de acciones que solo puede realizar un usuario que esté autorizado para ello.

Vamos a ver un par de conceptos relacionados con la seguridad de una aplicación web.

  • Autenticación: Es el proceso por el cual se identifica y se asegura que un usuario es quien dice ser.
  • Autorización: Es el proceso mediante el cual se asegura que un usuario puede acceder a los recursos y realizar las acciones a las que esté autorizado.

Veamos de una forma más específica de estos conceptos para tenerlos más claros.

Imaginemos una aplicación web bancaria, donde tenemos una parte pública que cualquier usuario puede visualizar, como podría ser la página principal, datos de contacto, información sobre servicios, etc., y una parte privada donde únicamente aquellos usuarios pertenecientes al banco pueden realizar acciones como ver su estracto bancario, realizar transferencias, etc.

Para poder acceder a esta parte privada, se requiere que el usuario se identifique en el sistema para saber que es un usuario dado de alta en el banco y puede acceder a la parte privada. Esto es lo que se conoce como autenticación.

Por otro lado, no todos los usuarios identificados en el sistema pueden realizar cualquier acción. Por ejemplo, un usuario solo debería poder ver y realizar transferencias desde sus cuentas bancarias o aquellas a las que tuviera permiso, pero no sería lógico que pudiera hacer transferencias desde la cuenta bancaria de otro usuario. También puede darse el caso que queramos dar acceso a nuestra cuenta bancaria a ciertos usuarios, pero solo permitir que realicen transferencias menores de cierta cantidad. Esto es lo que se conoce como autorización.

Una vez tenemos claros estos conceptos, a la hora de diseñar e implementar una aplicación web, debemos identificar qué recursos deben estar protegidos de forma que para poder acceder a ellos y después debemos autenticar al usuario y verificar que tiene los privilegios adecuados para acceder a dichos recursos.

Existen diferentes métodos de autenticación de un usuario en el lado del servidor:

  • HTTP Basic: es el mecanísmo estándar de autenticación en HTTP. En cada petición se envía una cabecera Authorization: Basic con el usuario y contraseña codificados en base64. No es un mecanismo muy seguro, ya que aunque las credenciales vayan codificadas, esto no significa que estén cifradas. Se podría usar HTTPs para las comunicaciones y usar HTTP Digest (que hace un hash MD5 de los datos), pero no es la mejor manera de autenticarse.
  • Autenticación basada en Cookies de sesión: las cookies son un mecanismo que nos permite almacenar datos entre peticiones/respuestas por parte del cliente y del servidor. Las cookies de sesión son identificadores bastante largos que se generan en el servidor cuando nos autenticamos y se envían al usuario, las cuales pueden ser usadas posteriormente por el usuario para identificarse como usuario autenticado. Aunque este mecanismo tiene ventajas sobre HTTP Basic (por ejemplo, es más sencillo invalidar cookies de sesión que obligar al usuario a cambiar su login/contraseña), también tiene una serie de desventajas. Es susceptible al robo de sesión si por ejemplo nuestra web es vulnerable a Cross Site Scripting (xss), también se pueden «forzar» al usuario a realizar acciones que no desea si la web es vulnerable a un ataque de Cross Site Request Forgery (csrf). Además, si estamos implementando microservicios, por su naturaleza deben ser APIs sin estado, por lo que almacenar datos en la sesión es algo contraproducente.
  • Autenticación basada en tokens: este método consiste en el envío de un token (una cadena alfanumérica con caracteres aleatorios) que contenga toda la información necesaria para identificar al usuario. Cuando el usuario se identifique por primera vez en el servidor, éste genera un token que envía al usuario. Este token es después utilizado por el usuario en cada petición para identificarse como un usuario autenticado en el sistema. Existe una versión de este método que se ha convertido en un estándar en la autenticación de aplicaciones, JSON Web Tokens (JWT), el cual permite de una forma sencilla identificar al usuario en el servidor mediante este token.

Un JWT es un token con una estructura definida: header, payload y signature.

Cada sección del token tiene un significado:

  • Header: es la primera parte del token, la cual almacena información como el tipo de token (normalmente JWT) y el algoritmo de firma usado, como como HMAC SHA25 o RSA. La cabecera se codifica en base64 y se añade como primera parte del token.
  • Payload: la segunda parte del token es la carga y almacena información relativa al usuario. El payload se codifica también en base64 y se añade a la segunda parte del token.
  • Signature: por último tenemos la firma, que sirve para verificar que el token no haya sido modificado y, en caso de usar clave privada, verificar que el emisor del token es quien dice ser. Para generar la firma, tenemos que coger la cabecera codificada y el payload codificado y firmarlo usando un algoritmo y una clave secreta. Finalmente, esta firma se añade al final del token para completarlo.

La forma de usar los JSON Web Tokens es, una vez que el usuario envía sus credenciales al servidor (introduciendo su usuario y contraseña), el servidor verifica que estas credenciales sean correctas y genera un token que devuelve al usuario el cual debe almacenarlo, bien usando cookies (no recomendable) o bien en el LocalStorage del navegador (recomendable). Después, cada vez que el usuario necesite realizar una petición al servidor, incluirá dicho token en una cabecera de la petición de manera que, cuando el servidor reciba dicha petición, sea capaz de identificar al usuario de forma satisfactoria a través del token.

Categorías