backend: enhance room member token info handling to include participant identity in request session service
This commit is contained in:
parent
2453ce2760
commit
9cf48fc49e
@ -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'),
|
||||
|
||||
@ -11,7 +11,7 @@ import {
|
||||
*/
|
||||
export interface RequestContext {
|
||||
user?: MeetUser;
|
||||
roomMember?: MeetRoomMemberTokenMetadata;
|
||||
roomMember?: MeetRoomMemberTokenMetadata & { participantIdentity?: string };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user