Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use authenticate web sockets using node, ws and passport with JWT?

I have a web server written in node/express which uses passport to authenticate users with JSON Web Tokens (JWT).

For regular HTTP methods this is what I use:

app.get('/api/stuff', isLoggedIn(), (req, res) => {
    //get stuff
    res.send( whatever );
});

Where isLoggedIn is this function:

function isLoggedIn() {
    return passport.authenticate('local-jwt', { session: false });
}

The authentication itself is handled by the 'local-jwt' configuration in passport using a JWTStrategy object and it works as expected.

Now I need to add web sockets to this app. I'm using the ws library. Here is what I have so far:

const wss = new WebSocket.Server({
    port: 8080,
    verifyClient: async (info, done) => {
        // ???
        done( result );
    }
});

wss.on('connection', ws => {
    // web socket events
});

How do I use the passport authentication to only allow clients with the correct token to connect to the web socket server?

like image 311
Znorg Avatar asked Jan 18 '26 23:01

Znorg


1 Answers

You can sign the token with the user's id or anything you are using to differentiate users

var today = new Date();
var exp = new Date(today);
exp.setDate(today.getDate() + 60);
jwt.sign({
        id: user._id,
        exp: parseInt(exp.getTime() / 1000),
    }, secret);

then pass the token to the frontend and use it to initialize your Websocket connection with it appended to the url then take and decode it in the server like this

const wss = new WebSocket.Server({
  verifyClient: async (info, done) => {
    console.log(info.req.url);
    console.log('------verify client------');

    const token = info.req.url.split('/')[1];
    var decoded = jwt.verify(token, secret);

    info.req.user = await User.findById(decoded.id).exec();

    /*info.req.user is either null or the user and you can destroy the connection
     if its null */

    done(info.req);
  },
  server
});

This is one of many ways. There is a way with sessions but I see you don't want to use them. Also I don't know if you use mongo but it's the same for any database you just have to change some code.

like image 134
C.Gochev Avatar answered Jan 20 '26 15:01

C.Gochev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!