Olá klawdyo. Tudo bem?
Sobre a autenticação, você terá de controlar manualmente. Seja por eventos ou controlando os usuários da sua aplicação. O envio de um token por JWT através dos sockets funciona sem problemas e você pode pegar o payload dos dois lados. Inclusive, os parâmetros de informação trafegadas não precisam ser texto, mas podem ser bytes. Se o próprio socket.IO tem uma autenticação dele? Não.
Sobre a eventos dinâmicos, criá-los não será para você a melhor prática, apesar de funcionar. No lado server, você tem conhecimento de todas as salas enquanto no lado client, você pode armazenar em qual sala aquele socket está em uma constante e mandar a sala como parâmetro para o server e o server consegue mandar para a sala com o to. Exemplo:
socket.on('mensagem', function(Sala, Mensagem){
socket.to(Sala).emit('mensagem', Mensagem);
});
socket.on('mensagem', function(Mensagem){
});
socket.emit('mensagem', 'minhaSala','minha Mensagem');
Para além disso, caso você tenha um evento personalizado para cada sala, você ficará limitado ao número de salas e não conseguirá fazer isso escalável e dinâmico. Por exemplo, se você tiver 500 salas, você não irá, no lado server, fazer o método on para 500 salas, apesar de no lado cliente, você conseguir fazer um emit para um evento com nome dinâmico. Caso queira fazer isso, mesmo assim, você pode usar o evento onAny no lado server. Esse evento dispara com qualquer evento recebido pelo socket.IO e tem como primeiro parâmetro, o nome do evento que foi lançado pelo emit no lado cliente.