El módulo de autenticación 'Passport' requiere un método FindOrCreate para iniciar sesión. Estoy usando mangosta con el fin de salvar a mis usuarios con el siguiente esquema:Cómo lidiar con la asincronización. Método findOrCreate para pasaporte y mangosta
var UserSchema = new Schema({
firstname: String,
lastname: String,
email: String,
accounts: []
});
La matriz de cuentas contiene objetos que representan cuentas de facebook, como {provider: "facebook", uid: "someFacebookId"}
.
Mi estrategia de autenticación es el siguiente:
// Authentication Strategy
passport.use(new FacebookStrategy({
clientID: CONFIG.fb.appId,
clientSecret: CONFIG.fb.appSecret,
callbackURL: CONFIG.fb.callbackURL
},
function(accessToken, refreshToken, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function() {
User.find({ 'accounts.uid': profile.id, 'accounts.provider': 'facebook' }, function(err, olduser) {
if(olduser._id) {
console.log('User: ' + olduser.firstname + ' ' + olduser.lastname + ' found and logged in!');
done(null, olduser);
} else {
var newuser = new User();
var account = {provider: "facebook", uid: profile.id};
newuser.accounts.push(account);
newuser.firstname = profile.name.givenName;
newuser.lastname = profile.name.familyName;
newuser.email = "TBD...";
newuser.save(function(err) {
if(err) { throw err; }
console.log('New user: ' + newuser.firstname + ' ' + newuser.lastname + ' created and logged in!');
done(null, newuser);
});
}
});
});
}
));
Problema: Después de la consulta de mi base de datos (User.find(...)
) la función de devolución de llamada se ejecuta inmediatamente sin esperar a mi base de datos para responder. Esto da como resultado un objeto olduser
indefinido. Así que estoy recibiendo una copia del mismo usuario en mi base de datos cada vez que este usuario intenta iniciar sesión.
¿Cómo manejo esta devolución de llamada asincrónica correctamente?
Sé que esto no está directamente relacionado con la pregunta, pero ¿no es esa consulta algo peligrosa? Busca un usuario con cualquier account.uid del valor dado y con cualquier accounts.provider de 'facebook'. Pero, ¿qué los fuerza a ser el mismo elemento de la lista de cuentas? Es decir, ¿qué pasaría si otro usuario tuviera un uid correspondiente con un proveedor diferente? – StevenC
Supongo que está buscando la combinación de ambos valores, que deben ser únicos. – Sven
Esto asumiendo es un peligro. Porque encuentra en una matriz de cuentas emparejadas si el usuario tiene una cuenta de Facebook y * CUALQUIER * cuenta tiene ese uid. Si alguien tiene un servidor OpenAuth, entonces puede iniciar sesión como cualquier usuario devolviendo el uid que desea. – tangxinfa