Prevent banned user from trying to validate auth token multiple times. close #9798

This commit is contained in:
Joao Siebel 2020-06-12 13:24:11 -03:00
parent 6da65c3c84
commit 45f99fed8b
6 changed files with 95 additions and 33 deletions

View File

@ -9,6 +9,7 @@ import createNote from '/imports/api/note/server/methods/createNote';
import createCaptions from '/imports/api/captions/server/methods/createCaptions';
import { addAnnotationsStreamer } from '/imports/api/annotations/server/streamer';
import { addCursorStreamer } from '/imports/api/cursor/server/streamer';
import BannedUsers from '/imports/api/users/server/store/bannedUsers';
export default function addMeeting(meeting) {
const meetingId = meeting.meetingProp.intId;
@ -145,6 +146,7 @@ export default function addMeeting(meeting) {
// better place we can run this post-creation routine?
createNote(meetingId);
createCaptions(meetingId);
BannedUsers.init(meetingId);
}
if (numChanged) {

View File

@ -15,7 +15,12 @@ const clearOtherSessions = (sessionUserId, current = false) => {
};
export default function handleValidateAuthToken({ body }, meetingId) {
const { userId, valid, authToken, waitForApproval } = body;
const {
userId,
valid,
authToken,
waitForApproval,
} = body;
check(userId, String);
check(authToken, String);
@ -26,7 +31,7 @@ export default function handleValidateAuthToken({ body }, meetingId) {
if (!valid) {
pendingAuths.forEach(
pendingAuth => {
(pendingAuth) => {
try {
const { methodInvocationObject } = pendingAuth;
const connectionId = methodInvocationObject.connection.id;
@ -40,7 +45,7 @@ export default function handleValidateAuthToken({ body }, meetingId) {
} catch (e) {
Logger.error(`Error closing socket for meetingId '${meetingId}', userId '${userId}', authToken ${authToken}`);
}
}
},
);
return;
@ -49,7 +54,7 @@ export default function handleValidateAuthToken({ body }, meetingId) {
if (valid) {
// Define user ID on connections
pendingAuths.forEach(
pendingAuth => {
(pendingAuth) => {
const { methodInvocationObject } = pendingAuth;
/* Logic migrated from validateAuthToken method ( postponed to only run in case of success response ) - Begin */
@ -58,7 +63,7 @@ export default function handleValidateAuthToken({ body }, meetingId) {
const User = Users.findOne({
meetingId,
userId: userId,
userId,
});
if (!User) {
@ -67,7 +72,7 @@ export default function handleValidateAuthToken({ body }, meetingId) {
setConnectionIdAndAuthToken(meetingId, userId, methodInvocationObject.connection.id, authToken);
/* End of logic migrated from validateAuthToken */
}
},
);
}

View File

@ -2,6 +2,8 @@ import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import RedisPubSub from '/imports/startup/server/redis';
import { extractCredentials } from '/imports/api/common/server/helpers';
import Users from '/imports/api/users';
import BannedUsers from '/imports/api/users/server/store/bannedUsers';
export default function removeUser(userId, banUser) {
const REDIS_CONFIG = Meteor.settings.private.redis;
@ -18,5 +20,9 @@ export default function removeUser(userId, banUser) {
banUser,
};
const removedUser = Users.findOne({ meetingId, userId }, { extId: 1 });
if (banUser && removedUser) BannedUsers.add(meetingId, removedUser.extId);
return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, ejectedBy, payload);
}

View File

@ -2,12 +2,16 @@ import { Meteor } from 'meteor/meteor';
import RedisPubSub from '/imports/startup/server/redis';
import Logger from '/imports/startup/server/logger';
import pendingAuthenticationsStore from '../store/pendingAuthentications';
import BannedUsers from '../store/bannedUsers';
export default function validateAuthToken(meetingId, requesterUserId, requesterToken) {
export default function validateAuthToken(meetingId, requesterUserId, requesterToken, externalId) {
const REDIS_CONFIG = Meteor.settings.private.redis;
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
const EVENT_NAME = 'ValidateAuthTokenReqMsg';
// Check if externalId is banned from the meeting
if (externalId && BannedUsers.has(meetingId, externalId)) return;
// Store reference of methodInvocationObject ( to postpone the connection userId definition )
pendingAuthenticationsStore.add(meetingId, requesterUserId, requesterToken, this);

View File

@ -0,0 +1,35 @@
import Logger from '/imports/startup/server/logger';
class BannedUsers {
constructor() {
Logger.debug('BannedUsers :: Initializing');
this.store = {};
}
init(meetingId) {
Logger.debug('BannedUsers :: init', meetingId);
if (!this.store[meetingId]) this.store[meetingId] = new Set();
}
add(meetingId, externalId) {
Logger.debug('BannedUsers :: add', { meetingId, externalId });
if (!this.store[meetingId]) this.store[meetingId] = new Set();
this.store[meetingId].add(externalId);
}
delete(meetingId) {
Logger.debug('BannedUsers :: delete', meetingId);
delete this.store[meetingId];
}
has(meetingId, externalId) {
Logger.debug('BannedUsers :: has', { meetingId, externalId });
if (!this.store[meetingId]) this.store[meetingId] = new Set();
return this.store[meetingId].has(externalId);
}
}
export default new BannedUsers();

View File

@ -207,7 +207,7 @@ class Auth {
}
validateAuthToken() {
return new Promise((resolve, reject) => {
return new Promise(async (resolve, reject) => {
let computation = null;
const validationTimeout = setTimeout(() => {
@ -218,9 +218,18 @@ class Auth {
});
}, CONNECTION_TIMEOUT);
const result = await makeCall('validateAuthToken', this.meetingID, this.userID, this.token, this.externUserID);
if (!result) {
reject({
error: 401,
description: 'User has been banned.',
});
return;
}
Tracker.autorun((c) => {
computation = c;
makeCall('validateAuthToken', this.meetingID, this.userID, this.token);
Meteor.subscribe('current-user');
const selector = { meetingId: this.meetingID, userId: this.userID };
@ -237,6 +246,7 @@ class Auth {
}
if (User.ejected) {
computation.stop();
reject({
error: 401,
description: 'User has been ejected.',