Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Force logout live clients on E2EE keys reset #31958

Merged
merged 12 commits into from
Apr 20, 2024
5 changes: 5 additions & 0 deletions .changeset/eighty-pans-joke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Force logout the clients which are actively online, whenever a user resets E2EE keys.
4 changes: 4 additions & 0 deletions apps/meteor/server/lib/resetUserE2EKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Subscriptions, Users } from '@rocket.chat/models';
import { Meteor } from 'meteor/meteor';

import * as Mailer from '../../app/mailer/server/api';
import { Notifications } from '../../app/notifications/server';
import { settings } from '../../app/settings/server';
import { i18n } from './i18n';
import { isUserIdFederated } from './isUserIdFederated';
Expand Down Expand Up @@ -64,6 +65,9 @@ export async function resetUserE2EEncriptionKey(uid: string, notifyUser: boolean
throw new Meteor.Error('error-not-allowed', 'Federated Users cant have TOTP', { function: 'resetTOTP' });
}

// force logout the live sessions
Notifications.notifyUser(uid, 'force_logout');
scuciatto marked this conversation as resolved.
Show resolved Hide resolved

await Users.resetE2EKey(uid);
await Subscriptions.resetUserE2EKey(uid);

Expand Down
30 changes: 29 additions & 1 deletion apps/meteor/tests/e2e/e2e-encryption.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { faker } from '@faker-js/faker';

import { createAuxContext } from './fixtures/createAuxContext';
import injectInitialData from './fixtures/inject-initial-data';
import { Users, storeState, restoreState } from './fixtures/userStates';
import { AccountProfile, HomeChannel } from './page-objects';
Expand Down Expand Up @@ -134,11 +135,13 @@ test.describe.serial('e2e-encryption', () => {
expect(statusCode).toBe(200);

poHomeChannel = new HomeChannel(page);

await page.goto('/home');
});

test.afterAll(async ({ api }) => {
// inject initial data, so that tokens are restored after forced logout
await injectInitialData();

const statusCode = (await api.post('/settings/E2E_Enable', { value: false })).status();

await expect(statusCode).toBe(200);
Expand Down Expand Up @@ -213,6 +216,31 @@ test.describe.serial('e2e-encryption', () => {
await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
});

test('expect force logout on e2e keys reset', async ({ page, browser }) => {
const poAccountProfile = new AccountProfile(page);
// creating another logged in client, to check force logout
const { page: anotherClientPage } = await createAuxContext(browser, Users.admin);

await page.goto('/account/security');

await poAccountProfile.securityE2EEncryptionSection.click();
await poAccountProfile.securityE2EEncryptionResetKeyButton.click();

await page.locator('role=button[name="Login"]').waitFor();
await anotherClientPage.locator('role=button[name="Login"]').waitFor();

await expect(page).toHaveURL('/home');
await expect(anotherClientPage).toHaveURL('/home');

await expect(page.locator('role=button[name="Login"]')).toBeVisible();
await expect(anotherClientPage.locator('role=button[name="Login"]')).toBeVisible();

await expect(page.locator('role=banner')).toContainText('Your session was ended on this device, please log in again to continue.');
await expect(anotherClientPage.locator('role=banner')).toContainText('Your session was ended on this device, please log in again to continue.');

await anotherClientPage.close();
});

test('expect create a private encrypted channel and send an attachment with encrypted file description', async ({ page }) => {
const channelName = faker.string.uuid();

Expand Down
2 changes: 1 addition & 1 deletion packages/i18n/src/locales/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -3304,7 +3304,7 @@
"Log_Trace_Subscriptions_Filter": "Trace subscription filter",
"Log_Trace_Subscriptions_Filter_Description": "The text here will be evaluated as RegExp (`new RegExp('text')`). Keep it empty to show trace of every call.",
"Log_View_Limit": "Log View Limit",
"Logged_Out_Banner_Text": "Your workspace admin ended your session on this device. Please log in again to continue.",
"Logged_Out_Banner_Text": "Your session was ended on this device, please log in again to continue.",
MarcosSpessatto marked this conversation as resolved.
Show resolved Hide resolved
"Logged_out_of_other_clients_successfully": "Logged out of other clients successfully",
"Login": "Login",
"Log_in_to_sync": "Log in to sync",
Expand Down
Loading