backend: enhance room member token info handling to include participant identity in request session service

This commit is contained in:
juancarmore 2026-03-05 11:03:03 +01:00
parent 2453ce2760
commit 9cf48fc49e
3 changed files with 45 additions and 51 deletions

View File

@ -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<void> {
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<void> => {
// 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<MeetUser | null> => {
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'),

View File

@ -11,7 +11,7 @@ import {
*/
export interface RequestContext {
user?: MeetUser;
roomMember?: MeetRoomMemberTokenMetadata;
roomMember?: MeetRoomMemberTokenMetadata & { participantIdentity?: string };
}
/**

View File

@ -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;
}
}