Skip to content

Commit 70c6ae1

Browse files
authored
Merge pull request #18317 from mozilla/fxa-11060
feat(keys): Update key stretching to optionally use session token on password change
2 parents ce4985f + 586866b commit 70c6ae1

17 files changed

Lines changed: 305 additions & 190 deletions

File tree

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ test.describe('severity-2 #smoke', () => {
2020
password: string
2121
) {
2222
const client = target.createAuthClient(version);
23-
const response = await client.signIn(email, password, { keys: true });
23+
const response = await client.signIn(email, password, {
24+
keys: true,
25+
skipPasswordUpgrade: true,
26+
});
2427
expect(response.keyFetchToken).toBeDefined();
2528
expect(response.unwrapBKey).toBeDefined();
2629

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

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,14 @@ test.describe('severity-2 #smoke', () => {
2121
password: string
2222
) {
2323
const client = target.createAuthClient(version);
24-
const response = await client.signIn(email, password, { keys: true });
24+
const response = await client.signIn(email, password, {
25+
keys: true,
26+
skipPasswordUpgrade: true,
27+
});
2528
expect(response.keyFetchToken).toBeDefined();
2629
expect(response.unwrapBKey).toBeDefined();
2730

28-
const keys = client.accountKeys(
31+
const keys = await client.accountKeys(
2932
response.keyFetchToken as string,
3033
response.unwrapBKey as string
3134
);
@@ -62,18 +65,25 @@ test.describe('severity-2 #smoke', () => {
6265
recoveryKey,
6366
resetPassword,
6467
confirmSignupCode,
68+
deleteAccount,
6569
},
6670
testAccountTracker,
6771
}) => {
68-
const { email, password } = testAccountTracker.generateAccountDetails();
72+
const accountDetails = {
73+
email: testAccountTracker.generateEmail(),
74+
password: testAccountTracker.generatePassword(),
75+
};
76+
const newPassword = testAccountTracker.generatePassword();
6977
await page.goto(
7078
`${target.contentServerUrl}/?forceExperiment=generalizedReactApp&forceExperimentGroup=react&${signupVersion.query}`
7179
);
7280
await page.waitForURL(/\//);
73-
await signup.fillOutEmailForm(email);
74-
await signup.fillOutSignupForm(password, AGE_21);
81+
await signup.fillOutEmailForm(accountDetails.email);
82+
await signup.fillOutSignupForm(accountDetails.password, AGE_21);
7583
await expect(page).toHaveURL(/confirm_signup_code/);
76-
const code = await target.emailClient.getVerifyShortCode(email);
84+
const code = await target.emailClient.getVerifyShortCode(
85+
accountDetails.email
86+
);
7787
await confirmSignupCode.fillOutCodeForm(code);
7888

7989
await page.waitForURL(/settings/);
@@ -84,57 +94,72 @@ test.describe('severity-2 #smoke', () => {
8494
const keys = await _getKeys(
8595
signupVersion.version,
8696
target,
87-
email,
88-
password
97+
accountDetails.email,
98+
accountDetails.password
8999
);
90100
await page.goto(
91101
`${target.contentServerUrl}/?forceExperiment=generalizedReactApp&forceExperimentGroup=react&${resetVersion.query}`
92102
);
93103
await page.waitForURL(/\//);
94-
await signin.fillOutEmailFirstForm(email);
95-
await signin.fillOutPasswordForm(password);
104+
await signin.fillOutEmailFirstForm(accountDetails.email);
105+
await signin.fillOutPasswordForm(accountDetails.password);
96106
await page.waitForURL(/settings/);
97107
await expect(page).toHaveURL(/settings/);
98108

99-
await settings.goto(`${resetVersion.version}`);
109+
await settings.goto(`${resetVersion.query}`);
100110
await page.waitForURL(/settings/);
101111
await settings.recoveryKey.createButton.click();
102-
const key = await recoveryKey.createRecoveryKey(password, HINT);
112+
const key = await recoveryKey.createRecoveryKey(
113+
accountDetails.password,
114+
HINT
115+
);
103116
await settings.signOut();
104117
await page.goto(
105118
`${target.contentServerUrl}/reset_password?${resetVersion.query}`
106119
);
107120
await page.waitForURL(/reset_password/);
108-
await resetPassword.fillOutEmailForm(email);
109-
const resetCode = await target.emailClient.getResetPasswordCode(email);
121+
await resetPassword.fillOutEmailForm(accountDetails.email);
122+
const resetCode = await target.emailClient.getResetPasswordCode(
123+
accountDetails.email
124+
);
110125
await resetPassword.fillOutResetPasswordCodeForm(resetCode);
111126
await resetPassword.fillOutRecoveryKeyForm(key);
112127

113128
await expect(page).toHaveURL(
114129
new RegExp(`account_recovery_reset_password.*${resetVersion.query}`)
115130
);
116131

117-
await resetPassword.fillOutNewPasswordForm(password);
132+
await resetPassword.fillOutNewPasswordForm(newPassword);
133+
accountDetails.password = newPassword;
118134

119135
await expect(page).toHaveURL(/reset_password_with_recovery_key_verified/);
120136

137+
await resetPassword.continueWithoutDownloadingRecoveryKey();
138+
await resetPassword.recoveryKeyFinishButton.click();
139+
140+
// a successful password reset means that the user is signed in
141+
await page.waitForURL(/settings/);
142+
await settings.signOut();
143+
144+
// Attempt to signin
121145
await page.goto(
122146
`${target.contentServerUrl}/?forceExperiment=generalizedReactApp&forceExperimentGroup=react&${signinVersion.query}`
123147
);
124148
await page.waitForURL(/\//);
125-
// a successful password reset means that the user is signed in
126-
await expect(signin.cachedSigninHeading).toBeVisible();
127-
await signin.signInButton.click();
128-
149+
await signin.fillOutEmailFirstForm(accountDetails.email);
150+
await signin.fillOutPasswordForm(accountDetails.password);
129151
await page.waitForURL(/settings/);
130-
await expect(page).toHaveURL(/settings/);
152+
131153
const keys2 = await _getKeys(
132154
signinVersion.version,
133155
target,
134-
email,
135-
password
156+
accountDetails.email,
157+
accountDetails.password
136158
);
137159
expect(keys2.kB).toEqual(keys.kB);
160+
161+
await settings.deleteAccountButton.click();
162+
await deleteAccount.deleteAccount(accountDetails.password);
138163
});
139164
}
140165
});

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ test.describe('severity-2 #smoke', () => {
2020
password: string
2121
) {
2222
const client = target.createAuthClient(version);
23-
const response = await client.signIn(email, password, { keys: true });
23+
const response = await client.signIn(email, password, {
24+
keys: true,
25+
skipPasswordUpgrade: true,
26+
});
2427
expect(response.keyFetchToken).toBeDefined();
2528
expect(response.unwrapBKey).toBeDefined();
2629

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

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ test.describe('auth-client-tests', () => {
120120
const { email, password } = testAccountTracker.generateAccountDetails();
121121

122122
await signUp(client, email, password);
123+
123124
const signInResult = await client.signIn(email, password, { keys: true });
124125
expect(signInResult.keyFetchToken).toBeDefined();
125126
expect(signInResult.unwrapBKey).toBeDefined();
@@ -129,6 +130,7 @@ test.describe('auth-client-tests', () => {
129130
signInResult.keyFetchToken as string,
130131
signInResult.unwrapBKey as string
131132
);
133+
132134
expect(keys1).toBeDefined();
133135
expect(keys1.kA).toBeDefined();
134136
expect(keys1.kB).toBeDefined();
@@ -143,13 +145,26 @@ test.describe('auth-client-tests', () => {
143145
expect(statusBefore.clientSalt).toBeUndefined();
144146
expect(statusBefore.currentVersion).toBe('v1');
145147

146-
// The sign in should automatically reset the password
148+
// The sign in should automatically upgrade the password, but return V1 creds
147149
const signInResult2 = await client2.signIn(email, password, {
148150
keys: true,
149151
});
150152
expect(signInResult2).toBeDefined();
151153
expect(signInResult2.keyFetchToken).toBeDefined();
152154
expect(signInResult2.unwrapBKey).toBeDefined();
155+
expect(signInResult2.unwrapBKey).toEqual(signInResult.unwrapBKey);
156+
157+
// Grab keys, so we can compare kA and kB
158+
const keys2 = await client.accountKeys(
159+
signInResult2.keyFetchToken as string,
160+
signInResult2.unwrapBKey as string
161+
);
162+
163+
expect(keys2).toBeDefined();
164+
expect(keys2.kA).toBeDefined();
165+
expect(keys2.kB).toBeDefined();
166+
expect(keys2.kA).toEqual(keys1.kA);
167+
expect(keys2.kB).toEqual(keys1.kB);
153168

154169
// Check the status after the signin
155170
const statusAfter = await client2.getCredentialStatusV2(email);
@@ -159,7 +174,12 @@ test.describe('auth-client-tests', () => {
159174
expect(statusAfter.clientSalt).toMatch('quickStretchV2:');
160175
expect(statusAfter.currentVersion).toBe('v2');
161176

162-
// Check unwrapKB. It should match our V2 credential unwrapBKey.
177+
// Do another signin to get V2 credentials
178+
const signInResult3 = await client2.signIn(email, password, {
179+
keys: true,
180+
});
181+
182+
// Check unwrapKB. It should match our V1 credential unwrapBKey.
163183
const status = await client.getCredentialStatusV2(email);
164184
expect(status.clientSalt).toBeDefined();
165185
expect(status.clientSalt).toBeDefined();
@@ -168,22 +188,23 @@ test.describe('auth-client-tests', () => {
168188
password,
169189
clientSalt: status.clientSalt as string,
170190
});
171-
expect(credentialsV2.unwrapBKey).toEqual(signInResult2.unwrapBKey);
191+
expect(credentialsV2.unwrapBKey).toEqual(signInResult3.unwrapBKey);
172192

173193
const credentialsV1 = await getCredentials(email, password);
174-
expect(credentialsV1.unwrapBKey).not.toEqual(signInResult2.unwrapBKey);
175-
expect(signInResult2.keyFetchToken).toBeDefined();
176-
expect(signInResult2.unwrapBKey).toBeDefined();
194+
expect(credentialsV1.unwrapBKey).not.toEqual(signInResult3.unwrapBKey);
195+
expect(signInResult3.keyFetchToken).toBeDefined();
196+
expect(signInResult3.unwrapBKey).toBeDefined();
177197

178198
// Check that keys didn't drift
179-
const keys2 = await client2.accountKeys(
180-
signInResult2.keyFetchToken as string,
181-
signInResult2.unwrapBKey as string
199+
const keys3 = await client2.accountKeys(
200+
signInResult3.keyFetchToken as string,
201+
signInResult3.unwrapBKey as string
182202
);
183-
expect(keys2).toBeDefined();
184-
expect(keys2.kA).toBeDefined();
185-
expect(keys2.kB).toBeDefined();
186-
expect(keys2.kA).toEqual(keys1.kA);
187-
expect(keys2.kB).toEqual(keys1.kB);
203+
204+
expect(keys3).toBeDefined();
205+
expect(keys3.kA).toBeDefined();
206+
expect(keys3.kB).toBeDefined();
207+
expect(keys3.kA).toEqual(keys1.kA);
208+
expect(keys3.kB).toEqual(keys1.kB);
188209
});
189210
});

0 commit comments

Comments
 (0)