¿Cómo usar pasaporte con express y socket.io?

Actualmente estoy tratando de configurar un sistema de autenticación básico para mi aplicación node.js. Por ahora estoy usando Express (3.0.0rc5), pasaporte (0.1.12) y socket.io (0.9.10) con Mongoose como Tienda para datos de sesión. También he estado jugando con everyauth pero no me gustaba trabajar con promesas.

Situación actual:

La autenticación mediante pasaporte (estrategia de Facebook) es exitosa, se establece una cookie session.sid en el cliente después de la redirección y puedo ver un documento de sesión en mi base de datos. Puedo acceder a la cookie de sesión en socket.io través de socket.handshake.headers.cookie .

Si entendí correctamente el concepto de pasaporte, después de una authentication passport.serializeUser exitosa se llama a authentication passport.serializeUser lo que me permite agregar información a la sesión. En mi caso, la información más importante es el correo electrónico, así que configuré el serializador de la siguiente manera:

 passport.serializeUser(function(user, done) { done(null, user.email); }); 

Ahora estoy en el punto en el que tengo que usar solo la información de las cookies en mi evento socket.io para extraer la dirección de correo electrónico de la sesión.

 var connect = require('connect'), parseSignedCookie = connect.utils.parseSignedCookie, cookie = require('express/node_modules/cookie'); io.on('connection', function(socket) { if(socket.handshake.headers.cookie) { var cookie = cookie.parse(socket.handshake.headers.cookie); var sessionID = parseSignedCookie(cookie['connect.sid'], 'secret'); } }); passport.deserializeUser(function(id, done) { // so, what is supposed to be done here? }); 

Entonces, si no me equivoco, la tarea ahora es usar deserializeUser para acceder a la dirección de correo electrónico correspondiente.

¿Como podría hacerlo? Cualquier puntero es muy apreciado.

Aquí hay una solución usando Socket.IO 1.0 y Express 4.0 . Es similar en espíritu a la respuesta de Patrick. El truco es que, dado que Socket.IO 1.0 tiene una nueva API de middleware, podemos envolver el middleware de Express y ponerlo en la canalización de Socket.IO sin profundizar en la implementación de bajo nivel de las tiendas de sesión.

 // Set up the Session middleware using a MongoDB session store expressSession = require("express-session"); var sessionMiddleware = expressSession({ name: "COOKIE_NAME_HERE", secret: "COOKIE_SECRET_HERE", store: new (require("connect-mongo")(expressSession))({ url: "mongodb://localhost/DATABASE_NAME_HERE" }) }); // Set up the Express server var app = require("express")() .use(sessionMiddleware) .use(passport.initialize()) .use(passport.session()) // ... more middleware ... .listen(8000); // Set up the Socket.IO server var io = require("socket.io")(app) .use(function(socket, next){ // Wrap the express middleware sessionMiddleware(socket.request, {}, next); }) .on("connection", function(socket){ var userId = socket.request.session.passport.user; console.log("Your User ID is", userId); }); 

La variable sessionMiddleware es una función que está diseñada para caber directamente en la tubería Express. Toma exactamente tres argumentos: el objeto de solicitud, el objeto de respuesta y una callback.

Sin embargo, el proyecto de Socket.IO espera que su middleware tome solo dos argumentos: el objeto socket (que contiene el objeto request en socket.request ) y una callback. Afortunadamente, sessionMiddleware no requiere que el objeto de respuesta lea la sesión desde la tienda, por lo que simplemente le pasamos un objeto vacío como segundo argumento.

Tenga en cuenta que algunos comentarios a continuación observan que este código representa la sesión de solo lectura. Esta es la funcionalidad que perdemos al no tener un objeto de respuesta adecuado con Socket.IO.

En el ejemplo anterior, uso una tienda de sesión MongoDB (connect-mongo). Puede usar cualquier tienda de sesión que se adapte a su gusto. Consulte la wiki de Connect para obtener una lista de las tiendas de sesión.

Yo tengo que trabajar. Lo que tuve que hacer es acceder a la tienda de sesiones. Aquí está el código en caso de que alguien más tropiece con este problema en particular:

 // # app.js var express = require('express'), routes = require('./routes'), http = require('http'), path = require('path'), app = express(), passport = require('passport'), SessionMongoose = require("session-mongoose"), mongooseSessionStore = new SessionMongoose({ url: "mongodb://localhost/login", interval: 120000 }); var config = require('game/config.js'), // holds my whole server configuration server = require('game/lib/server.js'); // save sessionStore to config for later access config.setSessionStore(mongooseSessionStore); // configure express to use passport and mongooseSessionStore app.configure(function(){ app.set('port', config.port); app.set('env', config.environment); app.set('dbPrefix', config.dbPrefix); app.set('views', __dirname + '/views'); app.set('view engine', 'jade'); app.use(express.favicon()); app.use(express.bodyParser()); app.use(express.cookieParser()); app.use(express.session({secret : 'totallysecret', store : mongooseSessionStore })), app.use(express.methodOverride()); app.use(passport.initialize()); app.use(passport.session()); app.use(app.router); app.use(express['static'](path.join(__dirname, 'public'))); }); app.get('/', routes.index); app.get('/auth/facebook', passport.authenticate('facebook', { scope: 'email' })); app.get('/auth/facebook/callback', passport.authenticate('facebook', { successRedirect: '/', failureRedirect: '/' })); // #### Init httpserver var httpServer = http.createServer(app); httpServer.listen(app.get('port')); // #### Server startup server.init(httpServer); 

Mis funciones de serialización se ven así de simple:

 passport.serializeUser(function(user, done) { // saves user.email to session.passport.user done(null, user.email); }); passport.deserializeUser(function(obj, done) { done(null, obj); }); 

Y finalmente la implementación de socket.io:

 var util = require('util'), connect = require('connect'), parseSignedCookie = connect.utils.parseSignedCookie, cookie = require('express/node_modules/cookie'), io = require('socket.io').listen(httpServer); var config = require('../config.js'); io.configure(function () { io.set('authorization', function (data, callback) { if(data.headers.cookie) { // save parsedSessionId to handshakeData data.cookie = cookie.parse(data.headers.cookie); data.sessionId = parseSignedCookie(data.cookie['connect.sid'], 'totallysecret'); } callback(null, true); }); io.on('connection', function(socket) { // reference to my initialized sessionStore in app.js var sessionStore = config.sessionStore; var sessionId = socket.handshake.sessionId; sessionStore.get(sessionId, function(err, session) { if( ! err) { if(session.passport.user) { console.log('This is the users email address %s', session.passport.user); } }); }); }); 

Usando el módulo session-mongoose tengo acceso a:

 sessionStore.get(sessionId, callback) sessionStore.set(sessionId, data, callback) sessionStore.destroy(sessionId, callback) sessionStore.all(callback) // returns all available sessions sessionStore.clear(callback) // deletes all session data sessionStore.length(callback) // returns number of sessions in the 

Puede hacer uso de express-socket.io-session . Puede obtener el usuario de la sesión de pasaporte con socket.handshake.session.passport.user . Es compatible con lectura y escritura en la tienda de sesiones.

NB: Funciona con express> 4.0.0 y socket.io> 1.0.0 y no será compatible con versiones anteriores

    Intereting Posts