¿Las mejores prácticas en torno a la generación de tokens OAuth?

100

Me doy cuenta de que la especificación de OAuth no especifica nada sobre el origen del código ConsumerKey, ConsumerSecret, AccessToken, RequestToken, TokenSecret o Verifier, pero tengo curiosidad por saber si existen mejores prácticas para crear tokens significativamente seguros (especialmente Token / Combinaciones secretas).

Como lo veo, hay algunos enfoques para crear los tokens:

  1. Simplemente use bytes aleatorios, almacénelos en la base de datos asociada con el consumidor / usuario
  2. Hash algunos datos específicos del usuario / consumidor, almacenar en la base de datos asociada con el consumidor / usuario
  3. Cifrar datos específicos del usuario / consumidor

Las ventajas de (1) son que la base de datos es la única fuente de información que parece la más segura. Sería más difícil ejecutar un ataque contra (2) o (3).

El hash de datos reales (2) permitiría volver a generar el token a partir de datos presumiblemente ya conocidos. Es posible que en realidad no proporcione ninguna ventaja a (1), ya que de todos modos necesitaría almacenar / buscar. Más CPU intensiva que (1).

Cifrar datos reales (3) permitiría descifrar información conocida. Esto requeriría menos almacenamiento y potencialmente menos búsquedas que (1) y (2), pero también potencialmente menos seguro.

¿Existen otros enfoques / ventajas / desventajas que deban considerarse?

EDITAR: otra consideración es que DEBE haber algún tipo de valor aleatorio en los Tokens, ya que debe existir la capacidad de caducar y volver a emitir nuevos tokens, por lo que no debe estar solo compuesto por datos reales.

Siga las preguntas :

¿Existe una longitud mínima del Token para que sea criptográficamente segura? Según tengo entendido, los Token Secrets más largos crearían firmas más seguras. ¿Es correcto este entendimiento?

¿Hay ventajas de usar una codificación particular sobre otra desde una perspectiva de hash? Por ejemplo, veo muchas API que utilizan codificaciones hexadecimales (por ejemplo, cadenas GUID). En el algoritmo de firma de OAuth, el token se usa como una cadena. Con una cadena hexadecimal, el conjunto de caracteres disponible sería mucho más pequeño (más predecible) que, digamos, con una codificación Base64. Me parece que para dos cadenas de igual longitud, la que tiene el conjunto de caracteres más grande tendría una distribución de hash mejor / más amplia. Esto me parece que mejoraría la seguridad. ¿Es esta suposición correcta?

La especificación OAuth plantea este mismo problema en 11.10 Entropy of Secrets .

mckamey
fuente
¿Por qué el cifrado? ¿No es lo suficientemente bueno el hash? Si el hash es lo suficientemente bueno para la contraseña, ¿no debería ser aún mejor para los tokens de acceso más largos?
AlikElzin-kilaka
Han pasado 7,5 años desde que hice la pregunta. Sinceramente, no puedo recordar.
mckamey
1
La lectura de nuevo, el hash y el cifrado fueron dos enfoques diferentes sugeridos. El cifrado permitiría al servidor obtener información sin una búsqueda en la base de datos. Fue una compensación entre muchas.
mckamey

Respuestas:

93

OAuth no dice nada sobre el token, excepto que tiene un secreto asociado. Entonces, todos los esquemas que mencionaste funcionarían. Nuestro token evolucionó a medida que los sitios crecían. Aquí están las versiones que usamos antes,

  1. Nuestro primer token es un BLOB cifrado con nombre de usuario, token secreto y vencimiento, etc. El problema es que no podemos revocar tokens sin ningún registro en el host.

  2. Así que lo cambiamos para almacenar todo en la base de datos y el token es simplemente un número aleatorio utilizado como clave para la base de datos. Tiene un índice de nombre de usuario, por lo que es fácil enumerar todos los tokens de un usuario y revocarlo.

  3. Realizamos bastantes actividades de piratería. Con número aleatorio, tenemos que ir a la base de datos para saber si el token es válido. Así que volvimos a BLOB cifrado de nuevo. Esta vez, el token solo contiene el valor cifrado de la clave y el vencimiento. Entonces podemos detectar tokens inválidos o caducados sin tener que ir a la base de datos.

Algunos detalles de implementación que pueden ayudarlo,

  1. Agregue una versión en el token para que pueda cambiar el formato del token sin romper los existentes. Todo nuestro token tiene el primer byte como versión.
  2. Use la versión de Base64 segura para URL para codificar el BLOB para que no tenga que lidiar con los problemas de codificación de URL, lo que dificulta la depuración con la firma OAuth, porque puede ver una cadena base con codificación triple.
Codificador ZZ
fuente
2
Excelente, gracias. La idea de la versión es buena. Tengo la Base64 compatible con URL, pero deseo tener una codificación estrictamente alfanumérica para una lectura aún más fácil.
mckamey
No había pensado en eso antes, ¡muy interesante! Estaba planeando el almacenamiento en caché de claves APC para mantener la carga innecesaria fuera de la base de datos antes de leer esto. Aún no estoy seguro de si esto no puede ser mucho más lento que lo que hace un APC de búsqueda de memoria compartida (al menos en la segunda, tercera, etc.) solicitud dentro de un período de tiempo razonable.
Philzen