#How to extract a jwt from a request, but with websockets?

1 messages · Page 1 of 1 (latest)

brisk oracle
#

subsequently, if this approach does work, how would I be able to get the passed in userId to also join this socket as well?

#

the schema is also fairly simple as well

#

I'm not sure if I need to create new namespaces/not sure what namespaces really do besides give the actual socket a name

dire girder
#

We do check JWT token on handshake request with custom auth service.

cunning bay
# brisk oracle subsequently, if this approach does work, how would I be able to get the passed ...
GitHub

Uno Online is a real-time multiplayer game built with cutting-edge technologies such as Nest.js, React, Socket.io, and Redux. Play Uno with friends and experience fast-paced and engaging gameplay o...

cunning bay
cunning bay
#

or you can write a guard for ws and add the client user object and get the decorator and user information.

// guard
import { ExecutionContext } from "@nestjs/common";
import { AuthGuard } from "./auth.guard";

export class WsAuthGuard extends AuthGuard {
    canActivate(context: ExecutionContext): boolean {
        const client = context.switchToWs().getClient();
        const headers = client.handshake.headers;
        if (!headers.authorization) {
            return false;
        }
        const user = this.validateToken(headers.authorization);
        client['user'] = user;
        return true;
    }
}```

```ts
// Decorator
import { createParamDecorator, ExecutionContext } from '@nestjs/common';

const UserDecorator = createParamDecorator((data: undefined, ctx:ExecutionContext) => {
    const user = ctx.switchToWs().getClient()
    return data ? user.user[data] : user.user;
})

export default UserDecorator```


    ```ts
// use
@SubscribeMessage('start')
    @UseGuards(WsAuthGuard)
    async start(@ConnectedSocket() socket: GameSocket, @UserDecorator() user: IGetUserType) {
       const result =  await this.rulesService.start(user,socket.gameId)
       socket.to(socket.gameId.toString()).emit('game_start',result)
    }```
brisk oracle
#

thank you so much!!

brisk oracle
cunning bay
brisk oracle
#

okay sorry for the follow up question, but how where does this statement return the message to? socket.gameId or game_start?

#

i'm fairly new to understanding sockets and this is the only way I can get a response from the initial socket request is to use the

@WebSocketServer()
server: Server

using

@ConnectedSocket()
socket: Socket 

never returns the emitted message from the server

#

this was the only way I was able to return a message from a listening websocket

cunning bay
brisk oracle
#

so that would be when I do something like


@SubscribeMessage('joinRoom')
async joinRoom(
  @ConnectedSocket()
  socket: Socket,
  @MessageBody()
  data: any
) {
  socket.join('room');
}
#

if this is correct how would I access that room from another function?

cunning bay
brisk oracle
#

how would you create a room then?

#

cause I thought by default the connected socket creates a room with it's respective ID?

#

or is that room the one you are referring to?

#

sorry if if I sound a little dumb on the subject I'm very new to learning websockets

cunning bay
#

When the client connects via socket i check which room they are in by using the token in the header and then add it to the socket object.

#

example user creates a room with HTTP requests and another user joins the room I add these users to the database

When the client connects with a socket I retrieve the room where the user is located by taking the token from the header and add it to the Socket object this way, I can access the gameId from my events.

#

actually, you can join rooms with sockets but I dont think it makes much sense to create rooms

brisk oracle
#

okay that makes a lot more sense

#

if we were to take this example how would I add a the chatRoomId to the socket?

#

as far as I know this just spits out the Id back to the original socket

#

I would first have to add @ConnectedSocket() socket: Socket to my params correct?

cunning bay
brisk oracle
#

what would my next step be cause you stated previously that you didn't have to use socket.join('room') how else would you add the roomId to the socket Object?

#

I noticed that you created an extended class of the Socket object and had a gameId is that what you're referring to?

#

and I would do something similar and create a ChatSocket? and extend the class and add a chatId to that?

cunning bay
brisk oracle
#

oh okay I see

#

cause I was looking at it and just trying to make sense of it all

cunning bay
#

It's actually easy in essence, but there are many factors.

brisk oracle
#

looking at your code I'm assuming that once you call the joinGame endpoint on your game controller once that response is good you actually connect them to the socket?

#

if I'm understanding that is correct?

cunning bay
# brisk oracle if I'm understanding that is correct?

it seems like you have found a bug, thank you
The current implementation works in a way that if a successful response is received from the request it enters the room but it is not mandatory to establish a socket connection However if the game has already started the socket cannot be connected
I forgot to check whether the game has started or not here

brisk oracle
#

omg hahaa that's so funny

#

but yea my idea of a successful response is whether or not they are connected to that game

cunning bay
#

what you said is actually true

brisk oracle
#

is there some different logic that I'm missing that would cause this to not run properly or properly emit a message? because when I have previously tried this it doesn't want to emit a message through the @ConnectedSocket() socket: Socket but if I use @WebSocketServer() server: Server it actually emits the message

#

where would I find this connectedSocket on postman or is it something that I can't use postman for and need an actual UI to test?

cunning bay
brisk oracle
#

yes that is correct

#

I've actually made sure that was the correct import when testing it

cunning bay
# brisk oracle where would I find this connectedSocket on postman or is it something that I can...

make sure you download the correct packages
https://docs.nestjs.com/websockets/gateways

brisk oracle
#

yep I have them

#

I can only receive the socket when using this.server.emit('test', 'this returns something')

#

if I tried using the socket it wouldn't return a message or anything

cunning bay
brisk oracle
#

sorry there's too many characters

cunning bay
brisk oracle
#

yea

#
import { Logger, UseGuards } from '@nestjs/common';
import { ConnectedSocket,
  MessageBody, 
  SubscribeMessage, 
  WebSocketGateway, 
  WebSocketServer 
} from '@nestjs/websockets';
import { Socket, Server } from 'socket.io';
import { ChatService } from './chat.service';
import { AuthService, PrismaService, } from 'src/modules';
import { CreateChatDto, CreateChatRoomDto } from 'src/utils/types';
import { JwtPayload } from 'src/utils/types/jwt';
import { WsGuard } from '../auth/guards';
import { GetWsUserId } from 'src/decorators';

@WebSocketGateway(80, {
  cors: {
    origin: process.env.CORS_ORIGIN,
  }
})
export class ChatGateway { 
  private logger: Logger = new Logger(ChatGateway.name);
  constructor(
    private readonly authService: AuthService,
    private readonly chatService: ChatService,
    private readonly prisma: PrismaService,
  ) { }

  @WebSocketServer()
  server: Server

  @SubscribeMessage('message')
  async sendMessage(
    @ConnectedSocket()
    socket: Socket,
    @MessageBody() 
    message: CreateChatDto
  ) {
    return await this.chatService.sendMessage(this.server, message);
  }

  @SubscribeMessage('createChatRoom')
  async createChatRoom(
    @ConnectedSocket()
    socket: Socket,
    @MessageBody() 
    data: CreateChatRoomDto,
  ) {
    const { id }: JwtPayload = await this.authService.parseJwt(data.jwt);
    const users = [id, data.userId];

    const chatRoom = await this.prisma.chatRoom.create({
      data: {
        users: {
          connect: users.map(id => ({ id: id }))
        }
      }
    });

    socket.join(chatRoom.id);
    this.server.emit('createChatRoom', chatRoom.id);
  }
}
cunning bay
#

result?
are you sure you're listening to the createChatRoom event?

brisk oracle
#

it works

#

when I use socket.emit('createChatRoom', chatRoom.id) it doesn't work

#

another example would be this.server.to(chatRoom.id).emit('message', data) where would I have to be listening to grab this message?

brisk oracle
#

but it would only listen to that response once I used this.server.emit('createChatRoom', chatRoom.id)

brisk oracle
#

so it didn't work for you either? or no difference to what? it's the same thing?

#

I would listen to the message event?

#

currently when I do
this.server.to('test').emit('message', data)
it doesn't work

works
this.server.emit('message', data)

#

not entirely sure what the difference is

cunning bay
#

first join room
socket.join("test")
send only to those in this room
socket.to("test").emit("message",message)

brisk oracle
#

is there a way I can join a room in postman to see this happening?

#

or can that only be done from an actual client?

cunning bay
brisk oracle
#

if we take this example test example

#

how would I receive this emitted message on hello?

#

I am seeing that I am joining the socket but now I'm not receiving the message

cunning bay
#

You should listen to postman hello event from a different tab

brisk oracle
#

it did not receive the message

#

because wouldn't I also have to join the test room?

#

for this to work?

cunning bay
#

yep

brisk oracle
cunning bay
#

Exactly

brisk oracle
#

so I woulnd't be able to test it on postman

#

I would need to actually connect to the server from some sort of UI to see this actually working in practice

#

if I'm understanding correctly

cunning bay
#

@SubscribeMessage('send1')
async test(@MessageBody() body:,@ConnectedSocket() sokcet:GameSocket){
sokcet.join("1")
}

@SubscribeMessage('send2')
async test123(@MessageBody() body:,@ConnectedSocket() sokcet:GameSocket){
    sokcet.to("1").emit("test",2 | body)
}
#

try this

cunning bay
# brisk oracle if I'm understanding correctly

open 2 Postman tabs and connect

in the first tab and second tab send a message to the address send1 the content of the message doesnt matter.

then in the first tab listen for a test and in the second tab send a request to the address send2

brisk oracle
#

OHHHHHHHHH

#

I get it now

#

yea I just tried

#

it

#

it all makes sense now

#

thank you sooooooo mcuh

#

for spending so much time with me

#

I appreciate it soooo much

#

lastly

#

is there a way to force a user to join a room? kinda to replicate how a messaging system would work where you have 1 user create a room to send a message to x person, and the person that receives the message is forced to join that room because they received a message?

#

bit of a long shot, but I would assume there are ways to replicate this type of behavior

#

I would also probably assume that this is something that would be done from the UI because the server wouldn't know about x user that received a message

#

but regardless if you know or care to share thank you so much for the time you spent to help me understand how this all works

cunning bay
# brisk oracle is there a way to force a user to join a room? kinda to replicate how a messagin...

maybe this coud be
lets say there are two users in an database user A and user B. User A follows user B and a unique key is generated from this relationship
If user A follows user B via socket connection he can creat an room with this switch If user A is not following user B they should not be allowed to send messages
message from the relationship that user A follows are sent from a room created with the unique key

brisk oracle
#

okay that makes sense

#

but from a perspective if they both follow each other

#

and user A sends a message to User B, how would user B get that notification that a message has been sent their messages?

brisk oracle
#

could something potentially be the case where I could do a find all where user B in chat room and make that user join each room that user B is found in?

cunning bay
#

@brisk oracle and ı have a request if u could reply to my msg by right click and selecting reply and then say thank you after, the bot could see that @opal shore

brisk oracle
#

also what does the reputation bot even do lol