1- import { Request } from "express" ;
1+ import { NextFunction , Request , Response } from "express" ;
22import { Server as HttpServer } from "node:http" ;
33import { ExtendedError , Server as SocketIOServer } from "socket.io" ;
4- import { verifySession } from "supertokens-node/recipe/session/framework/express" ;
4+ import { SessionRequest } from "supertokens-node/framework/express" ;
5+ import {
6+ ExpressRequest ,
7+ ExpressResponse ,
8+ } from "supertokens-node/lib/build/framework/express/framework" ;
9+ import SessionError from "supertokens-node/lib/build/recipe/session/error" ;
10+ import SessionRecipe from "supertokens-node/lib/build/recipe/session/recipe" ;
11+ import { makeDefaultUserContextFromAPI } from "supertokens-node/lib/build/utils" ;
512import {
613 EVENT_CHANGED ,
714 EVENT_CHANGE_PROCESSED ,
@@ -16,6 +23,7 @@ import {
1623 USER_REFRESH_TOKEN ,
1724 USER_SIGN_OUT ,
1825} from "@core/constants/websocket.constants" ;
26+ import { Status } from "@core/errors/status.codes" ;
1927import { Logger } from "@core/logger/winston.logger" ;
2028import { UserMetadata } from "@core/types/user.types" ;
2129import {
@@ -197,6 +205,46 @@ class WebSocketServer {
197205 return this . notifyClient ( socketId ! , event , ...payload ) ;
198206 }
199207
208+ /**
209+ * verifySession
210+ *
211+ * We are manually verifying the session here
212+ * to prevent the default supertokens behavior
213+ * of attempting to refresh the session if it is expired internally
214+ * since the socket's session might be stale.
215+ * We offload the refresh mechanism to the client.
216+ */
217+ private async verifySession (
218+ req : SessionRequest ,
219+ res : Response ,
220+ next : NextFunction ,
221+ ) {
222+ try {
223+ const request = new ExpressRequest ( req ) ;
224+ const response = new ExpressResponse ( res ) ;
225+ const userContext = makeDefaultUserContextFromAPI ( request ) ;
226+ const sessionRecipe = SessionRecipe . getInstanceOrThrowError ( ) ;
227+ const session = await sessionRecipe . verifySession (
228+ { sessionRequired : false } ,
229+ request ,
230+ response ,
231+ userContext ,
232+ ) ;
233+
234+ Object . assign ( req , { session } ) ;
235+
236+ next ( ) ;
237+ } catch ( err ) {
238+ const error = err as SessionError ;
239+
240+ res . writeHead ( Status . UNAUTHORIZED , {
241+ "Content-Type" : "application/json" ,
242+ } ) ;
243+
244+ res . end ( JSON . stringify ( { type : error . type , message : error . message } ) ) ;
245+ }
246+ }
247+
200248 init ( server : HttpServer ) {
201249 this . wsServer = new SocketIOServer <
202250 ClientToServerEvents ,
@@ -205,7 +253,7 @@ class WebSocketServer {
205253 SocketData
206254 > ( server , { cors : { origin : ENV . ORIGINS_ALLOWED , credentials : true } } ) ;
207255
208- this . wsServer . engine . use ( verifySession ( ) ) ;
256+ this . wsServer . engine . use ( this . verifySession . bind ( this ) ) ;
209257
210258 this . wsServer . engine . generateId = this . generateId . bind ( this ) ;
211259
0 commit comments