FoalTS / foal

Full-featured Node.js framework, with no complexity. 🚀 Simple and easy to use, TypeScript-based and well-documented.
https://foalts.org/
MIT License
1.9k stars 140 forks source link

JWT support for SocketIO #1205

Open everythingspirals opened 1 year ago

everythingspirals commented 1 year ago

Is there a way we can integrate JWT into the SocketIO controller. One recommendation is to add a middleware like so:

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

How can we access the io object to connect such a middleware?

warren-gallagher commented 1 year ago

I implemented support for JWT upon connection in the onConnection() method like the following.

export class ConnectionErrorException extends Error {

    constructor(statusCode: number, message: string) {
        super(JSON.stringify({status: statusCode, message: message}));
    }
}

export class WebsocketService extends SocketIOController {
    async onConnection(ctx: WebsocketContext) {
        const logPrefix = `${new Date().toISOString()} onConnection`;
        const authorizationHeader = ctx.socket.handshake.headers['authorization'];
        if( authorizationHeader == null || authorizationHeader == "" || !authorizationHeader.startsWith('Bearer ') ) {
            const msg = 'BadRequest - missing or invalid Authorization header. Disconnecting.';
            console.error(`${logPrefix} ${msg}`);
            throw new ConnectionErrorException(400, msg);
        }
        const token = authorizationHeader.split(' ')[1];
        /// the following is pseudo code for verification, replace as appropriate
        const verified = verifyJwt( token, secret );
        if( !verified ) {
            const msg = 'Unauthorized - verify Authorization Bearer token failed. Disconnecting.';
            console.error(`${logPrefix} ${msg}`);
            throw new ConnectionErrorException(401, msg);
        }
   }
}