Autenticação de conexões socket io usando JWT

106

Como posso autenticar uma conexão socket.io? Meu aplicativo usa um ponto de extremidade de login de outro servidor (python) para obter um token, como posso usar esse token sempre que um usuário abre uma conexão de soquete no lado do nó?

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

E do lado do cliente:

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

Se o token for criado em python:

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

Como posso usar este token para autenticar uma conexão de soquete no nó?

el_pup_le
fonte

Respostas:

226

Não importa se o token foi criado em outro servidor. Você ainda pode verificar se possui a chave secreta e o algoritmo corretos.

Implementação com jsonwebtokenmódulo

cliente

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

Servidor

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);
    });
});

Implementação com socketio-jwtmódulo

Este módulo torna a autenticação muito mais fácil no lado do cliente e do servidor. Basta verificar seus exemplos.

cliente

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
});

Servidor

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
fonte
Estou enfrentando um problema, embora não haja uma conexão de entrada para o soquete, quando iniciei o servidor de soquete, ele ainda tem o token antigo. Isso é estranho ?
Lamour
Quais são as opções disponíveis com io.connect na API do cliente
rocketspacer de
2
Como você se reconectaria ao servidor caso o usuário não fosse originalmente autorizado e não tivesse segredo na primeira tentativa?
sznrbrt
9
Olá, preciso perguntar, o token é necessário uma vez na conexão ou em cada evento de emissão?
Krunal Limbad
2
Para quem está recebendo Cannot read property 'on' of undefined; apenas remova o socketde function(socket).
Thomas Orlita
-28

você pode usar este url.

var socket = SocketIOClient(socketURL: URL(string: "http://00.00.00.00:port")!, config: SocketIOClientConfiguration(arrayLiteral: SocketIOClientOption.connectParams(["token": "your secret key"])))
Vikash Sharma
fonte
9
Você deve declarar que está escrevendo uma linguagem rápida. Outras pessoas simplesmente não sabem disso.
Espada Jason
6
Você precisa explicar esta resposta, caso contrário, isso não será útil para todos. Além disso, se estiver escrito em linguagem rápida, mencione isso em sua resposta
Freddy Daniel