Skip to content

Commit a32ce5c

Browse files
authored
Merge pull request #18451 from mozilla/fxa-10418-v2
fix(bug): Ensure `unlink` route is called with correct assurance level
2 parents 9f1922a + 000a522 commit a32ce5c

2 files changed

Lines changed: 33 additions & 1 deletion

File tree

packages/fxa-auth-server/lib/routes/linked-accounts.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,21 @@ export class LinkedAccountHandler {
514514
if (!this.googleAuthClient) {
515515
throw error.thirdPartyAccountError();
516516
}
517-
const uid = request.auth.credentials.uid;
517+
const sessionToken = request.auth && request.auth.credentials;
518+
const uid = sessionToken.uid;
519+
520+
const hasTotpToken = await this.otpUtils.hasTotpToken({ uid });
521+
522+
// Ensure that the session has the correct assurance level before unlinking
523+
if (
524+
sessionToken &&
525+
hasTotpToken &&
526+
(sessionToken.tokenVerificationId ||
527+
(sessionToken.authenticatorAssuranceLevel as number) <= 1)
528+
) {
529+
throw error.unverifiedSession();
530+
}
531+
518532
const provider = (request.payload as any).provider.toLowerCase();
519533
// TODO: here we'll also delete any session tokens created via a google login
520534
await this.db.deleteLinkedAccount(uid, provider);

packages/fxa-auth-server/test/local/routes/linked-accounts.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,24 @@ describe('/linked_account', function () {
562562
assert.isTrue(mockDB.deleteLinkedAccount.calledOnceWith(UID));
563563
assert.isTrue(result.success);
564564
});
565+
566+
it('fails to unlink with incorrect assurance level', async () => {
567+
mockRequest.auth.credentials.authenticatorAssuranceLevel = 1;
568+
mockDB.totpToken = sinon.spy(() =>
569+
Promise.resolve({
570+
verified: true,
571+
enabled: true,
572+
})
573+
);
574+
575+
try {
576+
await runTest(route, mockRequest);
577+
assert.fail('should have failed');
578+
} catch(err) {
579+
assert.isTrue(mockDB.deleteLinkedAccount.notCalled);
580+
assert.equal(err.errno, 138, 'unconfirmed session');
581+
}
582+
});
565583
});
566584

567585
describe('/linked_account/webhook/google_event_receiver', () => {

0 commit comments

Comments
 (0)