Recientemente he hecho esta pregunta en SO. Como la pregunta no fue respondida todavía, se me ocurrió un enfoque. Pero quería comprobar si no hay ningún defecto de seguridad en esta solución.
Pregunta
Había escrito un complemento de administración de sesión en node.js para el marco web de Muneem. Aquí está el pseudo código para crear una nueva sesión;
function createSession(){
// read encrypted session-id from the request
if( sessionId ){
// decrypt it
if (decryptedSessionId ) {
//read session detail from the store
options.store.get(decryptedSessionId, (err, sessionFromStore) => {
if(err){
throw Error(err);
}else if( sessionFromStore){
if( shouldRenew(sessionFromStore) ){
//delete previous session
options.store.destroy(sessionFromStore.id, err=> {
//update the session object in memory
});
}
}else{ //session detail is not present in store
// create new session
}
});
} else { //invalid or tempered session
// throw error
}
}else{ //session-id is not presnet in request
// create new session
}
}
Como puede observar, estoy renovando una sesión cuando sea válida y cumpla ciertas condiciones al eliminar la sesión anterior. Pero no lo actualizo en la tienda de inmediato. En su lugar, actualizo la información de la sesión en la tienda y configuro las cookies cuando la respuesta se envía al cliente.
Supongamos ahora una condición, cuando el servidor recibe varias solicitudes con el mismo id de sesión que se puede renovar. Renuevo la sesión en la primera solicitud.
Escenarios
- La sesión no se actualiza en la tienda. Así que renovaré la sesión anterior con otro nuevo ID de sesión. Un usuario tendrá múltiples ID de sesión en este caso.
- La sesión se actualiza en la tienda. Ahora, la sesión anterior no estará disponible en la tienda. Tendré que pedirle al usuario que vuelva a iniciar sesión si se trata de una sesión autorizada. O crearé otra sesión.
Solución
Para resolver esta condición de carrera, estaba pensando en crear una tabla de base de datos donde los registros puedan caducar por sí mismos después de una duración fija, por ejemplo, el tiempo de transición. Cuando se debe renovar una sesión, hacemos una entrada en la tabla expired-session con el ID de sesión anterior y la nueva. El resto de las operaciones son las mismas que para el pseudo código anterior. Ahora, si la próxima solicitud con el identificador de sesión caducado llega al servidor dentro del tiempo de transición, digamos 10 segundos, luego recuperaremos el nuevo identificador de sesión y continuaremos la sesión.
Aquí está el código completo, en caso de que lo necesitemos.