¿Cómo almacenar de forma segura tokens de portador en el servidor?

5

Imagine que está ejecutando un servicio que implementa un flujo de OAuth 2.0 para permitir a sus usuarios finales iniciar sesión en aplicaciones de terceros y autorizar a esas aplicaciones a consumir los datos de su servicio a través de algunas API.
Al autenticar con éxito una aplicación de terceros a través de su flujo de OAuth, su servicio envía a la aplicación de terceros un token de portador que autentica (y autoriza) a la aplicación de terceros (en nombre del usuario final) para utilizar la API de su servicio.

Tal token de portador debe almacenarse en sus servidores para poder realizar la autenticación de las llamadas API entrantes. Dado que el token del portador autentica (y autoriza) a los clientes, debe almacenarlo de forma segura, como si almacenara una contraseña.
Sin embargo, mientras que las contraseñas se incluyen con sal y hash antes de guardarlas en el disco, también se consultan por su principal correspondiente (nombre de usuario / dirección de correo electrónico), en lugar de hacerlo por la representación segura de la contraseña.

En el caso de un token de portador, no hay ningún principal que usar para buscar credenciales / tokens coincidentes. Suponiendo que desee almacenar tokens de portador como contraseñas (salado + hash), tendrá que buscar todas las sal posibles, aplicar cada una, luego codificar el token salado y luego verificar si existe en algún lugar de su sistema. Eso no se escala.

Entonces, mi pregunta es: ¿Cómo puede almacenar con seguridad tokens de portador en su servidor? Es decir, sin tener que generar cada representación segura posible cada vez que necesite verificar un token.
Por "almacenar de forma segura los tokens del portador", me refiero a que un atacante que obtenga el archivo de todos los tokens del portador "que estén guardados de forma segura" no podrá usarlos.

    
pregunta derabbink 21.07.2015 - 23:10
fuente

2 respuestas

2

Si las solicitudes de un tercero al proveedor de OAuth tienen otros datos que asocian la solicitud al usuario, por ejemplo, el nombre o la identificación del usuario, el servidor podría almacenar el token de portador como una contraseña regular con sales individuales. Sin embargo, si las solicitudes de terceros no tienen una parte de información identificable, el servidor podría almacenar una versión salted + picada del token de portador con un salt compartido para todos los tokens de portador. Debido a que los tokens de OAuth caducan rápidamente, un salt único no es tan importante en comparación con una contraseña que podría no caducar nunca. Si el token caduca después de 6 a 12 horas, el atacante no puede descifrar de manera realista el hash y utilizarlo para acceder a una cuenta de usuario. El servidor podría entonces rotar periódicamente la sal cada semana para obtener seguridad adicional.

    
respondido por el Justin Moore 21.07.2015 - 23:45
fuente
1

Según la la respuesta de Justin , estoy construyendo la mía propia.

Si los tokens son lo suficientemente largos (en mi caso son 200 caracteres alfanuméricos ( [A-Za-z0-9] ), no hay necesidad de usarlos. El hash solo debería ser suficiente, ya que la complejidad es lo suficientemente alta.

Si las fichas no son lo suficientemente largas como para evitar el hash solo (o si quieres insistir en agregarlas también), puedes modificar el esquema de generación de fichas ligeramente: En lugar de generar un token aleatorio, también genere un principal específico del token. Luego concatene los dos y entregue el resultado a la aplicación del consumidor como un solo token. Esencialmente, eso le pide a los clientes de la API que también envíen información de identificación del usuario, pero está convenientemente integrado en un solo token.

Internamente, salt + hash el token real antes de almacenar y almacena el principal específico del token por separado. Cuando se trata de verificar un token, divide el token enviado en dos, recuperando el token real y el principal específico del token. Este principal se puede usar para buscar el token real salted + hash con el que puede ejecutar un emparejador.

Ejemplo concreto:

  1. Genera un token de portador: por ejemplo, %código%
  2. Genere un principal específico de token de longitud fija: por ejemplo, %código%
  3. generar una sal, por ejemplo, %código%
  4. Sal + hash el token del portador ( a0z9B1Y8c2x7 ), que resultaría en algo como esto: D3W6e4v5F5
  5. almacene el token hasted + hashed junto con el principal específico del token, es decir, almacene una tupla aabbccddeeff00112233445566778899
  6. Proporcione la concatenación del token y el principal al usuario, para tratar como un token portador regular: a0z9B1Y8c2x7
respondido por el derabbink 24.07.2015 - 13:12
fuente

Lea otras preguntas en las etiquetas