Skip to content

Commit 6e6adf4

Browse files
committed
:bug fix(auth-refresh): prevent ws attempt to refresh the session
1 parent 5fb1dda commit 6e6adf4

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed

packages/backend/src/common/middleware/supertokens.middleware.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ export const initSupertokens = () => {
7676

7777
webSocketServer.handleUserRefreshToken(socketId!);
7878

79+
logger.debug(
80+
`Session refreshed for user ${data.sub} client.`,
81+
);
82+
7983
return session;
8084
},
8185
);

packages/backend/src/servers/websocket/websocket.server.ts

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1-
import { Request } from "express";
1+
import { NextFunction, Request, Response } from "express";
22
import { Server as HttpServer } from "node:http";
33
import { 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";
512
import {
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";
1927
import { Logger } from "@core/logger/winston.logger";
2028
import { UserMetadata } from "@core/types/user.types";
2129
import {
@@ -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

Comments
 (0)