Skip to content

Commit 365b387

Browse files
authored
Merge pull request #20331 from mozilla/FXA-13355
fix(auth): Provide sessionVerified on passwordChange handler
2 parents 0cee199 + e39d9fc commit 365b387

3 files changed

Lines changed: 101 additions & 3 deletions

File tree

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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,4 +147,52 @@ test.describe('severity-1 #smoke', () => {
147147

148148
await expect(resetPassword.confirmResetPasswordHeading).toBeVisible();
149149
});
150+
151+
test('can reset password then add ARK', async ({
152+
target,
153+
pages: { resetPassword, settings, recoveryKey, page },
154+
testAccountTracker,
155+
}) => {
156+
const credentials = await testAccountTracker.signUp();
157+
const newPassword = testAccountTracker.generatePassword();
158+
159+
await resetPassword.goto();
160+
161+
await resetPassword.page.waitForURL(/reset_password/);
162+
163+
await resetPassword.fillOutEmailForm(credentials.email);
164+
165+
const code = await target.emailClient.getResetPasswordCode(
166+
credentials.email
167+
);
168+
169+
await resetPassword.fillOutResetPasswordCodeForm(code);
170+
171+
// Create and submit new password
172+
await resetPassword.fillOutNewPasswordForm(newPassword);
173+
174+
await expect(settings.settingsHeading).toBeVisible();
175+
176+
// Cleanup requires setting this value to correct password
177+
credentials.password = newPassword;
178+
179+
// now add an ARK to make sure the browser has the correct verified state
180+
await expect(settings.recoveryKey.status).toHaveText('Not set');
181+
182+
await settings.recoveryKey.createButton.click();
183+
184+
await settings.confirmMfaGuard(credentials.email);
185+
186+
await recoveryKey.createRecoveryKey(
187+
credentials.password,
188+
'secret key location'
189+
);
190+
await expect(page.getByRole('alert')).toHaveText(
191+
'Account recovery key created'
192+
);
193+
194+
await expect(settings.settingsHeading).toBeVisible();
195+
await expect(settings.recoveryKey.status).toHaveText('Enabled');
196+
await expect(settings.recoveryKey.deleteButton).toBeVisible();
197+
});
150198
});

packages/fxa-auth-server/lib/routes/password.spec.ts

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,9 +448,7 @@ describe('/password', () => {
448448
mockRequest
449449
).then((response: any) => {
450450
expect(Object.keys(response)).toEqual(['accountResetToken']);
451-
expect(response.accountResetToken).toBe(
452-
accountResetToken.data
453-
);
451+
expect(response.accountResetToken).toBe(accountResetToken.data);
454452

455453
expect(mockCustoms.check.callCount).toBe(1);
456454

@@ -1230,5 +1228,56 @@ describe('/password', () => {
12301228
expect(response.sessionToken).toBeTruthy();
12311229
expect(response.keyFetchToken).toBeFalsy();
12321230
});
1231+
1232+
it('should include sessionVerified in the response reflecting token verification status', async () => {
1233+
const oldAuthPW = crypto.randomBytes(32).toString('hex');
1234+
const authPW = crypto.randomBytes(32).toString('hex');
1235+
const wrapKb = crypto.randomBytes(32).toString('hex');
1236+
1237+
const mockRequest = mocks.mockRequest({
1238+
log: mockLog,
1239+
auth: {
1240+
credentials: {
1241+
uid,
1242+
email: TEST_EMAIL,
1243+
emailVerified: true,
1244+
tokenVerified: true,
1245+
deviceId: crypto.randomBytes(16).toString('hex'),
1246+
authenticatorAssuranceLevel: 2,
1247+
lastAuthAt: () => Date.now(),
1248+
data: crypto.randomBytes(32).toString('hex'),
1249+
},
1250+
},
1251+
payload: {
1252+
email: TEST_EMAIL,
1253+
oldAuthPW,
1254+
authPW,
1255+
wrapKb,
1256+
},
1257+
query: {},
1258+
});
1259+
1260+
const passwordRoutes = makeRoutes({
1261+
db: mockDB,
1262+
mailer: mockMailer,
1263+
push: mockPush,
1264+
log: mockLog,
1265+
statsd: mockStatsd,
1266+
customs: mockCustoms,
1267+
});
1268+
1269+
const response = await runRoute(
1270+
passwordRoutes,
1271+
'/mfa/password/change',
1272+
mockRequest
1273+
);
1274+
1275+
// sessionVerified must be present so that client-side storage correctly
1276+
// reflects the verified session after a password change.
1277+
expect(response.sessionVerified).toBe(true);
1278+
1279+
// verified (deprecated compat field) should remain present and consistent
1280+
expect(response.verified).toBe(true);
1281+
});
12331282
});
12341283
});

packages/fxa-auth-server/lib/routes/password.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,7 @@ module.exports = function (
976976
const response: any = {
977977
uid: newSessionToken.uid,
978978
sessionToken: newSessionToken.data,
979+
sessionVerified: newSessionToken.tokenVerified,
979980
verified:
980981
newSessionToken.emailVerified && newSessionToken.tokenVerified,
981982
authAt: newSessionToken.lastAuthAt(),

0 commit comments

Comments
 (0)