Autenticar conexiones de socket io mediante JWT

106

¿Cómo puedo autenticar una conexión socket.io? Mi aplicación usa un punto final de inicio de sesión de otro servidor (python) para obtener un token, ¿cómo puedo usar ese token cada vez que un usuario abre una conexión de socket en el lado del nodo?

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

Y el lado del cliente:

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

Si el token se crea en python:

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

¿Cómo puedo usar este token para autenticar una conexión de socket en el nodo?

el_pup_le
fuente

Respuestas:

227

No importa si el token se creó en otro servidor. Aún puede verificarlo si tiene la clave secreta y el algoritmo correctos.

Implementación con 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);
    });
});

Implementación con socketio-jwtmódulo

Este módulo facilita la autenticación tanto en el lado del cliente como en el del servidor. Solo mira sus ejemplos.

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
fuente
Estoy enfrentando un problema, aunque no hay una conexión entrante al socket, cuando encendí el servidor de socket, todavía tiene el token anterior. Eso es raro ?
Lamour
¿Cuáles son las opciones disponibles con io.connect en la api del cliente?
Rocketspacer
2
¿Cómo se volvería a conectar al servidor en caso de que el usuario no estuviera autorizado originalmente y no tuviera un secreto en el primer intento?
sznrbrt
9
hola, necesito preguntar, ¿se requiere token por una vez en la conexión o en cada evento de emisión?
Krunal Limbad
2
Para cualquiera que obtenga Cannot read property 'on' of undefined; simplemente quite el socketde function(socket).
Thomas Orlita
-28

puede utilizar esta URL.

var socket = SocketIOClient(socketURL: URL(string: "http://00.00.00.00:port")!, config: SocketIOClientConfiguration(arrayLiteral: SocketIOClientOption.connectParams(["token": "your secret key"])))
Vikash Sharma
fuente
9
Debe indicar que está escribiendo un idioma rápido. Otras personas simplemente no lo saben.
Sword Jason
6
Debe explicar esta respuesta, de lo contrario, esto no es útil para todos. Además, si está escrito en un lenguaje rápido, menciónelo en su respuesta
Freddy Daniel