Skip to content

Commit e8fc8ef

Browse files
committed
task(settings): Wrap create account recovery keys with MFA guard
1 parent bae1e9c commit e8fc8ef

21 files changed

Lines changed: 206 additions & 23 deletions

File tree

packages/functional-tests/tests/key-stretching-v2/recoveryKey.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ test.describe('severity-2 #smoke', () => {
114114
await settings.goto(`${resetVersion.query}`);
115115
await page.waitForURL(/settings/);
116116
await settings.recoveryKey.createButton.click();
117+
118+
await settings.confirmMfaGuard(accountDetails.email);
119+
117120
const key = await recoveryKey.createRecoveryKey(
118121
accountDetails.password,
119122
HINT

packages/functional-tests/tests/key-stretching-v2/recoveryKeyUpgrade.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ test.describe('severity-2 #smoke', () => {
2929
await expect(settings.recoveryKey.status).toHaveText('Not Set');
3030

3131
await settings.recoveryKey.createButton.click();
32+
33+
await settings.confirmMfaGuard(email);
34+
3235
await recoveryKey.createRecoveryKey(password, HINT);
3336

3437
await expect(settings.recoveryKey.status).toHaveText('Enabled');

packages/functional-tests/tests/misc/recoveryKeyPromoInline.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ test.describe('recovery key promo', () => {
6464
await signin.fillOutPasswordForm(credentials.password);
6565
await page.waitForURL(/settings/);
6666
await settings.recoveryKey.createButton.click();
67+
await settings.confirmMfaGuard(credentials.email);
6768
await recoveryKey.acknowledgeInfoForm();
6869
await recoveryKey.fillOutConfirmPasswordForm(credentials.password);
6970
await recoveryKey.clickDownload();

packages/functional-tests/tests/misc/recoveryKeyPromoSettingsBanner.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ test.describe('recovery key promo', () => {
2727

2828
await inlineRecoveryKey.getBannerCreateLink().click();
2929

30+
await settings.confirmMfaGuard(credentials.email);
31+
3032
await recoveryKey.acknowledgeInfoForm();
3133
await recoveryKey.fillOutConfirmPasswordForm(credentials.password);
3234

@@ -57,6 +59,8 @@ test.describe('recovery key promo', () => {
5759

5860
await inlineRecoveryKey.getBannerCreateLink().click();
5961

62+
await settings.confirmMfaGuard(credentials.email);
63+
6064
await recoveryKey.acknowledgeInfoForm();
6165
await recoveryKey.fillOutConfirmPasswordForm(credentials.password);
6266

packages/functional-tests/tests/resetPassword/oauthResetPasswordRecoveryKey.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ test.describe('severity-1 #smoke', () => {
2222

2323
// Goes to settings and enables the account recovery key on user's account.
2424
await settings.recoveryKey.createButton.click();
25+
26+
await settings.confirmMfaGuard(credentials.email);
27+
2528
const accountRecoveryKey = await recoveryKey.createRecoveryKey(
2629
credentials.password,
2730
'hint'

packages/functional-tests/tests/resetPassword/resetPassword2FA.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ test.describe('severity-1 #smoke', () => {
143143

144144
// Create recovery key
145145
await settings.recoveryKey.createButton.click();
146+
147+
await settings.confirmMfaGuard(credentials.email);
148+
146149
const key = await recoveryKey.createRecoveryKey(
147150
credentials.password,
148151
'hint'
@@ -218,6 +221,9 @@ test.describe('severity-1 #smoke', () => {
218221

219222
// Create recovery key
220223
await settings.recoveryKey.createButton.click();
224+
225+
await settings.confirmMfaGuard(credentials.email);
226+
221227
const key = await recoveryKey.createRecoveryKey(
222228
credentials.password,
223229
'hint'
@@ -287,6 +293,9 @@ test.describe('severity-1 #smoke', () => {
287293

288294
// Create recovery key
289295
await settings.recoveryKey.createButton.click();
296+
297+
await settings.confirmMfaGuard(credentials.email);
298+
290299
await recoveryKey.createRecoveryKey(credentials.password, 'hint');
291300

292301
// Verify status as 'enabled'
@@ -357,6 +366,9 @@ test.describe('severity-1 #smoke', () => {
357366

358367
// Create recovery key
359368
await settings.recoveryKey.createButton.click();
369+
370+
await settings.confirmMfaGuard(credentials.email);
371+
360372
await recoveryKey.createRecoveryKey(credentials.password, 'hint');
361373

362374
// Verify status as 'enabled'

packages/functional-tests/tests/resetPassword/resetPasswordRecoveryKey.spec.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5+
import { emit } from 'node:process';
56
import { expect, test } from '../../lib/fixtures/standard';
67
import { SettingsPage } from '../../pages/settings';
78
import { RecoveryKeyPage } from '../../pages/settings/recoveryKey';
@@ -26,6 +27,7 @@ test.describe('severity-1 #smoke', () => {
2627
);
2728

2829
const key = await enableRecoveryKey(
30+
credentials.email,
2931
credentials.password,
3032
recoveryKey,
3133
settings
@@ -127,7 +129,12 @@ test.describe('severity-1 #smoke', () => {
127129
signin
128130
);
129131

130-
await enableRecoveryKey(credentials.password, recoveryKey, settings);
132+
await enableRecoveryKey(
133+
credentials.email,
134+
credentials.password,
135+
recoveryKey,
136+
settings
137+
);
131138

132139
await settings.signOut();
133140

@@ -170,6 +177,7 @@ test.describe('severity-1 #smoke', () => {
170177
);
171178

172179
const key = await enableRecoveryKey(
180+
credentials.email,
173181
credentials.password,
174182
recoveryKey,
175183
settings
@@ -223,13 +231,17 @@ test.describe('severity-1 #smoke', () => {
223231
}
224232

225233
async function enableRecoveryKey(
234+
email: string,
226235
password: string,
227236
recoveryKey: RecoveryKeyPage,
228237
settings: SettingsPage
229238
): Promise<string> {
230239
await expect(settings.recoveryKey.status).toHaveText('Not Set');
231240

232241
await settings.recoveryKey.createButton.click();
242+
243+
await settings.confirmMfaGuard(email);
244+
233245
const key = await recoveryKey.createRecoveryKey(password, 'hint');
234246

235247
await expect(settings.settingsHeading).toBeVisible();

packages/functional-tests/tests/settings/recoveryKey.spec.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ test.describe('severity-1 #smoke', () => {
1919
pages: { page, recoveryKey, settings, signin },
2020
testAccountTracker,
2121
}) => {
22-
const { password } = await signInAccount(
22+
const { email, password } = await signInAccount(
2323
target,
2424
page,
2525
settings,
@@ -33,6 +33,9 @@ test.describe('severity-1 #smoke', () => {
3333
await expect(settings.recoveryKey.status).toHaveText('Not Set');
3434

3535
await settings.recoveryKey.createButton.click();
36+
37+
await settings.confirmMfaGuard(email);
38+
3639
await recoveryKey.acknowledgeInfoForm();
3740
await recoveryKey.fillOutConfirmPasswordForm(password);
3841

@@ -61,6 +64,9 @@ test.describe('severity-1 #smoke', () => {
6164
await expect(settings.recoveryKey.status).toHaveText('Not Set');
6265

6366
await settings.recoveryKey.createButton.click();
67+
68+
await settings.confirmMfaGuard(credentials.email);
69+
6470
await recoveryKey.acknowledgeInfoForm();
6571
await recoveryKey.fillOutConfirmPasswordForm(credentials.password);
6672

@@ -118,6 +124,9 @@ test.describe('severity-1 #smoke', () => {
118124
await expect(settings.recoveryKey.status).toHaveText('Not Set');
119125

120126
await settings.recoveryKey.createButton.click();
127+
128+
await settings.confirmMfaGuard(credentials.email);
129+
121130
await recoveryKey.createRecoveryKey(credentials.password, HINT);
122131
await expect(page.getByRole('alert')).toHaveText(
123132
'Account recovery key created'

packages/fxa-auth-client/lib/client.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2099,6 +2099,16 @@ export default class AuthClient {
20992099
);
21002100
}
21012101

2102+
/**
2103+
* Creates an account recovery key that can be used to restore account data in the password is lost.
2104+
* @param sessionToken
2105+
* @param recoveryKeyId
2106+
* @param recoveryData
2107+
* @param enabled
2108+
* @param replaceKey
2109+
* @param headers
2110+
* @returns
2111+
*/
21022112
async createRecoveryKey(
21032113
sessionToken: hexstring,
21042114
recoveryKeyId: string,
@@ -2120,6 +2130,37 @@ export default class AuthClient {
21202130
);
21212131
}
21222132

2133+
/**
2134+
* Creates an account recovery key that can be used to restore account data in the password is lost.
2135+
* @param sessionToken
2136+
* @param recoveryKeyId
2137+
* @param recoveryData
2138+
* @param enabled
2139+
* @param replaceKey
2140+
* @param headers
2141+
* @returns
2142+
*/
2143+
async createRecoveryKeyWithJwt(
2144+
jwt: string,
2145+
recoveryKeyId: string,
2146+
recoveryData: any,
2147+
enabled: boolean = true,
2148+
replaceKey: boolean = false,
2149+
headers?: Headers
2150+
): Promise<{}> {
2151+
return this.jwtPost(
2152+
'/mfa/recoveryKey',
2153+
jwt,
2154+
{
2155+
recoveryKeyId,
2156+
recoveryData,
2157+
enabled,
2158+
replaceKey,
2159+
},
2160+
headers
2161+
);
2162+
}
2163+
21232164
async getRecoveryKey(
21242165
accountResetToken: hexstring,
21252166
recoveryKeyId: string,

packages/fxa-auth-server/config/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2476,7 +2476,7 @@ const convictConf = convict({
24762476
env: 'MFA__ENABLED',
24772477
},
24782478
actions: {
2479-
default: ['test', '2fa', 'email'],
2479+
default: ['test', '2fa', 'email', 'recovery_key'],
24802480
doc: 'Actions protected by MFA',
24812481
format: Array,
24822482
env: 'MFA__ACTIONS',

0 commit comments

Comments
 (0)