Uwierzytelnianie połączeń gniazda io za pomocą JWT

111

Jak mogę uwierzytelnić połączenie socket.io? Moja aplikacja korzysta z punktu końcowego logowania z innego serwera (Python), aby uzyskać token. Jak mogę użyć tego tokenu, gdy użytkownik otwiera połączenie z gniazdem po stronie węzła?

io.on('connection', function(socket) {
    socket.on('message', function(message) {
        io.emit('message', message);
    });
});

A po stronie klienta:

var token = sessionStorage.token;
var socket = io.connect('http://localhost:3000', {
    query: 'token=' + token
});

Jeśli token jest tworzony w Pythonie:

token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')

Jak mogę użyć tego tokenu do uwierzytelnienia połączenia gniazda w węźle?

el_pup_le
źródło

Odpowiedzi:

238

Nie ma znaczenia, czy token został utworzony na innym serwerze. Nadal możesz to zweryfikować, jeśli masz odpowiedni tajny klucz i algorytm.

Wdrożenie z jsonwebtokenmodułem

klient

const {token} = sessionStorage;
const socket = io.connect('http://localhost:3000', {
  query: {token}
});

serwer

const io = require('socket.io')();
const jwt = require('jsonwebtoken');

io.use(function(socket, next){
  if (socket.handshake.query && socket.handshake.query.token){
    jwt.verify(socket.handshake.query.token, 'SECRET_KEY', function(err, decoded) {
      if (err) return next(new Error('Authentication error'));
      socket.decoded = decoded;
      next();
    });
  }
  else {
    next(new Error('Authentication error'));
  }    
})
.on('connection', function(socket) {
    // Connection now authenticated to receive further events

    socket.on('message', function(message) {
        io.emit('message', message);
    });
});

Wdrożenie z socketio-jwtmodułem

Ten moduł znacznie ułatwia uwierzytelnianie zarówno po stronie klienta, jak i serwera. Po prostu sprawdź ich przykłady.

klient

const {token} = sessionStorage;
const socket = io.connect('http://localhost:3000');
socket.on('connect', function (socket) {
  socket
    .on('authenticated', function () {
      //do other things
    })
    .emit('authenticate', {token}); //send the jwt
});

serwer

const io = require('socket.io')();
const socketioJwt = require('socketio-jwt');

io.sockets
  .on('connection', socketioJwt.authorize({
    secret: 'SECRET_KEY',
    timeout: 15000 // 15 seconds to send the authentication message
  })).on('authenticated', function(socket) {
    //this socket is authenticated, we are good to handle more events from it.
    console.log(`Hello! ${socket.decoded_token.name}`);
  });
hassansin
źródło
Mam problem, mimo że nie ma połączenia przychodzącego do gniazda, po uruchomieniu serwera gniazda nadal ma on stary token. Czy to dziwne ?
Lamour
Jakie są dostępne opcje z io.connect w Client API
Rocketspacer
2
W jaki sposób można by połączyć się ponownie z serwerem, gdyby użytkownik był pierwotnie nieautoryzowany i nie posiadał tajemnicy przy pierwszej próbie?
sznrbrt
10
witam, muszę zapytać, token jest wymagany do jednorazowego połączenia lub każdego zdarzenia emitującego?
Krunal Limbad
3
Dla każdego, kto dostaje Cannot read property 'on' of undefined; po prostu usuń socketz function(socket).
Thomas Orlita