2022-11-19 追記
こちらの方法の方がより簡単です(原理は同じ)。
Passport で認証したユーザ情報を socket.io に引き継ぐモジュールを作ってみた。
プログラム
module.exports = (session, passport)=>{
return {
express_session:
(socket, next)=>{session(socket.request, {}, next)},
passport_initialize:
(socket, next)=>{passport.initialize()(socket.request, {}, next)},
passport_session:
(socket, next)=>{passport.session()(socket.request, {}, next)}
}
}
利用例
const express = require('express');
const session = require('express-session')({
secret:'secret',
resave:false,
saveUninitialized:false });
const passport = require('passport');
const socket_io_session
= require('./socket.io-passport-session')(session, passport);
const app = express();
app.use(session);
app.use(passport.initialize());
app.use(passport.session());
const server = require('http').createServer(app);
const io = require('socket.io')(server);
io.use(socket_io_session.express_session);
io.use(socket_io_session.passport_initialize);
io.use(socket_io_session.passport_session);
io.on('connection', socket=>{
console.log(socket.request.user);
socket.on('hello', msg=>{
console.log(socket.request.user);
console.log('hello', msg);
});
});
server.listen(3000);
動作原理
WebSocketは最初HTTPで接続し、その接続をWebSocketに「流用」する訳だが、最初のHTTPリクエストには認証のための Cookie ヘッダも含まれている。Cookie の値さえ分かればユーザ情報は復元可能なのだが、
- Cookie の値からセッションデータを復元
- セッションデータからユーザ情報を復元
する手順は express-session と passport に隠蔽されている1。1はミドルウェア関数の session() で、2は passport.session() で処理されるので、これらのミドルウェア関数を呼び出してあげればよい。2
ただし、app.use() から呼び出されるミドルウェアの引数は、(req, res, next) なのに対し、io.use() から呼び出される関数は (socket, next) なので変換が必要になる。具体的には (socket, next) → (socket.request, {}, next) とすればよい。
結果のユーザ情報は socket.request.user に設定される。この情報は connect 時だけでなく emit の際にも設定されるようであるが、送信元の識別はユーザ情報ではなく socket.id で行うべき。
npm モジュール
ちょっと手直しして npm に登録しました。