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 に登録しました。