From 9cf48fc49efc01341c24e2d7dd8996b7f016788e Mon Sep 17 00:00:00 2001 From: juancarmore Date: Thu, 5 Mar 2026 11:03:03 +0100 Subject: [PATCH] backend: enhance room member token info handling to include participant identity in request session service --- .../src/middlewares/auth.middleware.ts | 67 +++++++++---------- .../src/models/request-context.model.ts | 2 +- .../src/services/request-session.service.ts | 27 ++++---- 3 files changed, 45 insertions(+), 51 deletions(-) diff --git a/meet-ce/backend/src/middlewares/auth.middleware.ts b/meet-ce/backend/src/middlewares/auth.middleware.ts index 68f39023..9b1db605 100644 --- a/meet-ce/backend/src/middlewares/auth.middleware.ts +++ b/meet-ce/backend/src/middlewares/auth.middleware.ts @@ -1,4 +1,4 @@ -import { MeetUser, MeetUserRole } from '@openvidu-meet/typings'; +import { MeetUserRole } from '@openvidu-meet/typings'; import { NextFunction, Request, RequestHandler, Response } from 'express'; import rateLimit from 'express-rate-limit'; import ms from 'ms'; @@ -192,7 +192,7 @@ export const roomMemberTokenValidator: AuthValidator = { try { // Verify the token and extract the room member token metadata const tokenService = container.get(TokenService); - const { metadata: tokenMetadata } = await tokenService.verifyToken(token); + const { sub: participantIdentity, metadata: tokenMetadata } = await tokenService.verifyToken(token); if (!tokenMetadata) { throw new Error('Missing required token claims'); @@ -205,7 +205,9 @@ export const roomMemberTokenValidator: AuthValidator = { // If the token has a memberId, validate that permissions haven't been updated after token issuance if (memberId) { const roomMemberRepository = container.get(RoomMemberRepository); - const roomMember = await roomMemberRepository.findByRoomAndMemberId(roomId, memberId, ['permissionsUpdatedAt']); + const roomMember = await roomMemberRepository.findByRoomAndMemberId(roomId, memberId, [ + 'permissionsUpdatedAt' + ]); // If member not found or permissions were updated after token issuance, invalidate token if (!roomMember || iat < roomMember.permissionsUpdatedAt) { @@ -223,19 +225,14 @@ export const roomMemberTokenValidator: AuthValidator = { } // Set room member token metadata in the session - requestSessionService.setRoomMemberTokenMetadata(parsedMetadata); + requestSessionService.setRoomMemberTokenInfo(parsedMetadata, participantIdentity); } catch (error) { const logger = container.get(LoggerService); logger.error('Invalid room member token:', error); throw errorInvalidToken(); } - // Set authenticated user if present - const user = await getAuthenticatedUserOrAnonymous(req); - - if (user) { - requestSessionService.setUser(user); - } + await setAuthenticatedUserIfPresent(req); } }; @@ -294,39 +291,39 @@ export const allowAnonymous: AuthValidator = { }, async validate(req: Request): Promise { - const user = await getAuthenticatedUserOrAnonymous(req); + await setAuthenticatedUserIfPresent(req); + } +}; + +/** + * Set authenticated user in request context if access token is present and valid + */ +const setAuthenticatedUserIfPresent = async (req: Request): Promise => { + // Check if there is a user already authenticated + const token = getAccessToken(req); + + if (!token) { + return; + } + + try { + const tokenService = container.get(TokenService); + const payload = await tokenService.verifyToken(token); + const userId = payload.sub; + + const userService = container.get(UserService); + const user = userId ? await userService.getUser(userId) : null; if (user) { const requestSessionService = container.get(RequestSessionService); requestSessionService.setUser(user); } + } catch (error) { + const logger = container.get(LoggerService); + logger.debug('Token found but invalid:' + error); } }; -// Return the authenticated user if available, otherwise return null -const getAuthenticatedUserOrAnonymous = async (req: Request): Promise => { - let user: MeetUser | null = null; - - // Check if there is a user already authenticated - const token = getAccessToken(req); - - if (token) { - try { - const tokenService = container.get(TokenService); - const payload = await tokenService.verifyToken(token); - const userId = payload.sub; - - const userService = container.get(UserService); - user = userId ? await userService.getUser(userId) : null; - } catch (error) { - const logger = container.get(LoggerService); - logger.debug('Token found but invalid:' + error); - } - } - - return user; -}; - // Limit login attempts to avoid brute force attacks const loginLimiter = rateLimit({ windowMs: ms('5m'), diff --git a/meet-ce/backend/src/models/request-context.model.ts b/meet-ce/backend/src/models/request-context.model.ts index 1acf0806..5d7a742b 100644 --- a/meet-ce/backend/src/models/request-context.model.ts +++ b/meet-ce/backend/src/models/request-context.model.ts @@ -11,7 +11,7 @@ import { */ export interface RequestContext { user?: MeetUser; - roomMember?: MeetRoomMemberTokenMetadata; + roomMember?: MeetRoomMemberTokenMetadata & { participantIdentity?: string }; } /** diff --git a/meet-ce/backend/src/services/request-session.service.ts b/meet-ce/backend/src/services/request-session.service.ts index e5cb524d..37abb818 100644 --- a/meet-ce/backend/src/services/request-session.service.ts +++ b/meet-ce/backend/src/services/request-session.service.ts @@ -1,10 +1,4 @@ -import { - MeetRoomMemberPermissions, - MeetRoomMemberRole, - MeetRoomMemberTokenMetadata, - MeetUser, - MeetUserRole -} from '@openvidu-meet/typings'; +import { MeetRoomMemberPermissions, MeetRoomMemberTokenMetadata, MeetUser, MeetUserRole } from '@openvidu-meet/typings'; import { AsyncLocalStorage } from 'async_hooks'; import { injectable } from 'inversify'; import { RequestContext } from '../models/request-context.model.js'; @@ -84,15 +78,18 @@ export class RequestSessionService { } /** - * Sets the room member token metadata (room ID, base role, permissions) - * in the current request context. + * Sets the room member token information in the current request context. * If called outside a request context, this operation is silently ignored. + * + * @param metadata - The room member token metadata to store in the context + * @param participantIdentity - The participant identity (token subject) to store in the context */ - setRoomMemberTokenMetadata(metadata: MeetRoomMemberTokenMetadata): void { + setRoomMemberTokenInfo(metadata: MeetRoomMemberTokenMetadata, participantIdentity?: string): void { const context = this.getContext(); if (context) { context.roomMember = metadata; + context.roomMember.participantIdentity = participantIdentity; } } @@ -111,16 +108,16 @@ export class RequestSessionService { } /** - * Gets the room member base role from the current request context. + * Gets the participant identity from the current request context. */ - getRoomMemberBaseRole(): MeetRoomMemberRole | undefined { - return this.getContext()?.roomMember?.baseRole; + getParticipantIdentity(): string | undefined { + return this.getContext()?.roomMember?.participantIdentity; } /** - * Gets the room member effective permissions from the current request context. + * Gets the room member permissions from the current request context. */ getRoomMemberPermissions(): MeetRoomMemberPermissions | undefined { - return this.getContext()?.roomMember?.effectivePermissions; + return this.getContext()?.roomMember?.permissions; } }