Skip to content

Commit bf64af2

Browse files
authored
fix: Roles based mandatory two factor to check all cases (#37338)
1 parent 79c67c7 commit bf64af2

File tree

3 files changed

+61
-3
lines changed

3 files changed

+61
-3
lines changed

.changeset/tall-flies-jump.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@rocket.chat/meteor': patch
3+
---
4+
5+
Improves mandatory role-based two-factor authentication setup to always verify available 2FA methods before enforcement.

apps/meteor/client/views/hooks/useRequire2faSetup.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,26 @@ import { Roles } from '../../stores';
55
export const useRequire2faSetup = () => {
66
const user = useUser();
77
const tfaEnabled = useSetting('Accounts_TwoFactorAuthentication_Enabled', false);
8+
const email2faEnabled = useSetting('Accounts_TwoFactorAuthentication_By_Email_Enabled', false);
9+
const totp2faEnabled = useSetting('Accounts_TwoFactorAuthentication_By_TOTP_Enabled', false);
10+
const is2FAEnabled = tfaEnabled && (email2faEnabled || totp2faEnabled);
811

912
return Roles.use((state) => {
10-
// User is already using 2fa
11-
if (!user || user?.services?.totp?.enabled || user?.services?.email2fa?.enabled) {
13+
if (!user || !is2FAEnabled) {
1214
return false;
1315
}
1416

1517
const mandatoryRole = state.find((role) => !!role.mandatory2fa && user.roles?.includes(role._id));
16-
return mandatoryRole !== undefined && tfaEnabled;
18+
19+
if (mandatoryRole === undefined) {
20+
return false;
21+
}
22+
23+
const hasEmail2FA = !!user?.services?.email2fa?.enabled;
24+
const hasTotp2FA = !!user?.services?.totp?.enabled;
25+
26+
const hasAnyEnabled2FA = (email2faEnabled && hasEmail2FA) || (totp2faEnabled && hasTotp2FA);
27+
28+
return !hasAnyEnabled2FA;
1729
});
1830
};

apps/meteor/tests/e2e/enforce-2FA.spec.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { IS_EE } from './config/constants';
22
import { Users } from './fixtures/userStates';
33
import { HomeChannel, AccountProfile } from './page-objects';
44
import { createCustomRole, deleteCustomRole } from './utils/custom-role';
5+
import { setSettingValueById } from './utils/setSettingValueById';
56
import { test, expect } from './utils/test';
67

78
test.use({ storageState: Users.admin.state });
@@ -62,4 +63,44 @@ test.describe('enforce two factor authentication', () => {
6263
await expect(poHomeChannel.sidenav.sidebarHomeAction).toBeVisible();
6364
await expect(poAccountProfile.securityHeader).not.toBeVisible();
6465
});
66+
67+
test.describe('should still redirect to 2FA setup page when email 2FA is disabled', () => {
68+
test.beforeAll(async ({ api }) => {
69+
await setSettingValueById(api, 'Accounts_TwoFactorAuthentication_By_Email_Enabled', false);
70+
});
71+
72+
test.afterAll(async ({ api }) => {
73+
await setSettingValueById(api, 'Accounts_TwoFactorAuthentication_By_Email_Enabled', true);
74+
});
75+
76+
test('should redirect to 2FA setup page and show totp 2FA setup', async ({ page }) => {
77+
await page.goto('/home');
78+
await poAccountProfile.required2faModalSetUpButton.click();
79+
await expect(poHomeChannel.sidenav.sidebarHomeAction).not.toBeVisible();
80+
81+
await expect(poAccountProfile.securityHeader).toBeVisible();
82+
83+
await expect(poAccountProfile.security2FASection).toHaveAttribute('aria-expanded', 'true');
84+
await expect(poAccountProfile.totp2FASwitch).toBeVisible();
85+
await expect(poAccountProfile.email2FASwitch).not.toBeVisible();
86+
});
87+
});
88+
89+
test.describe('should not redirect to 2FA setup page when both email and totp 2FA are disabled', () => {
90+
test.beforeAll(async ({ api }) => {
91+
await setSettingValueById(api, 'Accounts_TwoFactorAuthentication_By_Email_Enabled', false);
92+
await setSettingValueById(api, 'Accounts_TwoFactorAuthentication_By_TOTP_Enabled', false);
93+
});
94+
95+
test.afterAll(async ({ api }) => {
96+
await setSettingValueById(api, 'Accounts_TwoFactorAuthentication_By_Email_Enabled', true);
97+
await setSettingValueById(api, 'Accounts_TwoFactorAuthentication_By_TOTP_Enabled', true);
98+
});
99+
100+
test('should not redirect to 2FA setup page', async ({ page }) => {
101+
await page.goto('/home');
102+
await expect(poHomeChannel.sidenav.sidebarHomeAction).toBeVisible();
103+
await expect(poAccountProfile.securityHeader).not.toBeVisible();
104+
});
105+
});
65106
});

0 commit comments

Comments
 (0)