Me ha interesado implementar un método de autenticación para una aplicación web que se ejecuta en navegadores modernos, sin tener que enviar la contraseña por cable.
¿Puede alguien sugerir mejoras o incluso decirme si me estoy yendo mal?
La autenticación se realiza a través de una conexión HTTP no segura mediante AJAX.
Mi comprensión actual de una implementación de protocolo de autenticación
El servidor tiene una contraseña de usuario que se ocultó utilizando bcrypt y se almacenó durante el registro.
El usuario ingresa id
y password
. Se envía un XMLHttpRequest
al servidor para comenzar la autenticación, X-R1
es un entero aleatorio creado en el cliente.
GET /auth/{id} HTTP/1.1
X-R1: 123412341234
-
El servidor obtiene valores.
-
ServerPassword
: los usuarios no pueden codificar la contraseña de la base de datos de contraseñas -
X-Salt
: extrae la sal deServerPassword
-
X-R1
- del cliente en el encabezado de la solicitud -
X-R2
- entero generado aleatoriamente en el servidor.
-
-
El servidor crea valores
-
X-Session
- clave de sesión, concatenandoX-R1 + X-R2 + id
, de esta manera una forma hash esta cadena -
Verifier
- secreto compartido, concatenandoX-R1 + X-R2 + ServerPassword
y luego una forma de hashing de esta cadena. -
Guarda estos valores en un almacén de sesión.
-
Respuesta del servidor.
HTTP/1.1 202 ACCEPTED
X-R2: 432143214321
X-Salt: $2a$10$rBV2JDeWW3.vKyeQcM8fFO
X-Session: 92429d82a41e930486c6de5ebda9602d55c39986
-
El cliente obtiene valores
-
X-R1
: el mismo valor desde antes de enviar la solicitud. -
ClientPassword
: texto sin formato, lo que ingresó el usuario. -
X-R2
- desde el encabezado del servidor enviado -
X-Salt
- desde el encabezado del servidor enviado.
-
-
El cliente crea valores
-
HashedPassword
: se creó usando una implementación de JavaScript de bcrypt usandoClientPassword
yX-Salt
-
Verifier
- ConcatenandoX-R1 + X-R2 + HashedPassword
y luego una forma de hash de este valor. El cliente utiliza una implementación de JavaScript de bcrypt para codificar la contraseña que el usuario ingresó con la cadenaX-Salt
.
-
Ahora, tanto el cliente como el servidor creen que tienen el mismo verificador, por lo que para confirmar este cliente envía una solicitud adicional, pero esta vez se combinan los encabezados y el cuerpo de la solicitud con el verificador y luego se agrega 'X-Auth' a los encabezados con hash resultante.
POST /auth/{id} HTTP/1.1
X-Session: 92429d82a41e930486c6de5ebda9602d55c39986
X-Auth: ad801198a9fab4e4ef79eb97624a4bf9c78b450a
El servidor ahora busca los X-Sessions
's en su tienda de sesión. Realiza el mismo hash de los encabezados y el cuerpo de la solicitud y luego verifica si el hash coincide con el valor de X-Auth
, si el servidor asume que el cliente está autorizado y responde en consecuencia.
HTTP/1.1 200 OK
El cliente sabe que el servidor tiene el mismo Verifier
y lo almacena en localStorage
usando el valor de X-Session
para la clave, para futuras solicitudes.
Preocupaciones
Soy un desarrollador promedio y no soy experto en criptografía y, según tengo entendido, no puedo ver ningún problema que pueda ocurrir con este método.
Puedo ver las grandes ventajas, como:
-
La contraseña nunca se envía a través del cable. Evite que MITM obtenga su contraseña.
-
MITM no puede modificar la solicitud, ya que se revisa con el verificador y luego se envía.
-
El servidor no necesita usar bcrypt cada vez que un usuario quiera autenticar.