Websockets token authentication using middleware and express in node.js

房东的猫 提交于 2020-01-22 02:30:32

问题


I use node.js, express and express-ws that is based on ws

Express-ws allows to create express-like endpoints for websockets.

I am looking for a solution to authenticate users in websocket connections, based on a token. Since my ws server is based on an HTTP one

const wsHttpServer = http.createServer();
wsHttpServer.listen(5001);
const expressWs = require('express-ws')(app , wsHttpServer);

and since the ws connection is based on an HTTP one that gets upgraded to a ws, WHY I cannot pass a token in my ws that the express route checks, like any other one? My logic is, send the token, check it, if it is ok, proceed to upgrade to a ws connection. So, I can reuse the token-middleware solution that I have in my HTTP connections.

In node

My ws server

const wsHttpServer = http.createServer();
wsHttpServer.listen(5001);
const expressWs = require('express-ws')(app , wsHttpServer);

//set the route

app.use('/ws', require('./routes/wsroute')); 

In that route, I would like to use the token.validate() middleware -that in HTTP connections, checks the Authorization header

router.ws('/user/:name/:id', token.validate(),  (ws, req) => { 
    console.log('ws route data : ',vessel, req.params.name, req.params.id);
});

In my client

    const socket = new WebSocket('ws://localhost',{
        path: '/user/Nick/25/',
        port: 5001, // default is 80
        protocol : "echo-protocol", // websocket protocol name (default is none)
        protocolVersion: 13, // websocket protocol version, default is 13
        keepAlive: 60,
        headers:{ some:'header', 'ultimate-question':42 } // websocket headers to be used e.g. for auth (default is none)
      });

this errors Failed to construct 'WebSocket': The subprotocol '[object Object]' is invalid

I also tried

const socket = new WebSocket('ws://localhost:5001/user/Nick/25', ["Authorization", localStorage.getItem('quad_token')]);

I dont get any errors, but I dont know how to get the Authorization "header" in node

I could

just send const socket = new WebSocket(currentUrl); with some data and include a valid token in that data. But to check it, I have to allow the connection first. I dont want that, I would like to use a middleware solution that automatically checks a token and allows or not to continue.

Questions

Please help me understand:

1 Is it possible to use a token-based, middleware-based solution in ws?

2 How to set a header with a token in a ws connection?

3 How to get that token in node?


回答1:


1) In my experience there is no available express.js middleware and the solution i found requires to listen to the upgrade event on your http server and blocking access to your socket connection before it reaches ws routes.

2) Your browser will not allow setting additional headers during websocket connection on the client side. It will send though the cookies so you can make use of express-session to authorize on your server first the user, a cookie will be set on the browser and that cookie will be sent over during the websocket connection.

3) You can do like in this answer Intercept (and potentially deny) web socket upgrade request Copying the code here from there for your own perusal.

**wsHttpServer**.on('upgrade', function (req, socket, head) {
      var validationResult = validateCookie(req.headers.cookie);
      if (validationResult) {
        //...
      } else {
        socket.write('HTTP/1.1 401 Web Socket Protocol Handshake\r\n' +
                     'Upgrade: WebSocket\r\n' +
                     'Connection: Upgrade\r\n' +
                     '\r\n');
                     socket.close();
                     socket.destroy();
                     return;
      }
      //...
    });


来源:https://stackoverflow.com/questions/59070321/websockets-token-authentication-using-middleware-and-express-in-node-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!