Skip to content

Commit a811e09

Browse files
committed
polish(settings): Clear MFA cache on sign out
1 parent cabad89 commit a811e09

3 files changed

Lines changed: 52 additions & 0 deletions

File tree

packages/fxa-settings/src/components/Settings/DropDownAvatarMenu/index.test.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,24 @@ import { Account, AppContext } from '../../../models';
1616
import { SettingsContext } from '../../../models/contexts/SettingsContext';
1717
import firefox from '../../../lib/channels/firefox';
1818
import { PLACEHOLDER_IMAGE_URL } from '../../../pages/mocks';
19+
import { JwtTokenCache, MfaOtpRequestCache } from '../../../lib/cache';
1920

2021
jest.mock('../../../models/AlertBarInfo');
2122
jest.mock('fxa-settings/src/lib/metrics', () => ({
2223
logViewEvent: jest.fn(),
2324
settingsViewName: 'quuz',
2425
}));
2526

27+
jest.mock('../../../lib/cache', () => ({
28+
...jest.requireActual('../../../lib/cache'),
29+
JwtTokenCache: {
30+
clearTokens: jest.fn(),
31+
},
32+
MfaOtpRequestCache: {
33+
clear: jest.fn(),
34+
},
35+
}));
36+
2637
const account = {
2738
avatar: {
2839
id: 'abc1234',
@@ -38,6 +49,10 @@ const account = {
3849
describe('DropDownAvatarMenu', () => {
3950
const dropDownId = 'drop-down-avatar-menu';
4051

52+
beforeEach(() => {
53+
jest.resetAllMocks();
54+
});
55+
4156
it('renders and toggles as expected with default values', () => {
4257
const account = {
4358
avatar: { url: null, id: null },
@@ -142,6 +157,12 @@ describe('DropDownAvatarMenu', () => {
142157
expect(window.location.assign).toHaveBeenCalledWith(
143158
window.location.origin
144159
);
160+
expect(JwtTokenCache.clearTokens).toHaveBeenCalledWith(
161+
mockSession().token
162+
);
163+
expect(MfaOtpRequestCache.clear).toHaveBeenCalledWith(
164+
mockSession().token
165+
);
145166
});
146167

147168
it('displays an error in the AlertBar', async () => {

packages/fxa-settings/src/components/Settings/DropDownAvatarMenu/index.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { logViewEvent, settingsViewName } from '../../../lib/metrics';
1212
import { Localized, useLocalization } from '@fluent/react';
1313
import firefox from '../../../lib/channels/firefox';
1414
import { FtlMsg } from 'fxa-react/lib/utils';
15+
import { JwtTokenCache, MfaOtpRequestCache } from '../../../lib/cache';
1516

1617
export const DropDownAvatarMenu = () => {
1718
const { displayName, primaryEmail, avatar, uid } = useAccount();
@@ -33,6 +34,12 @@ export const DropDownAvatarMenu = () => {
3334
const signOut = async () => {
3435
if (session.destroy) {
3536
try {
37+
// Clear JWTs associated with the current session and clear any
38+
// record of cached OTP requests.
39+
JwtTokenCache.clearTokens(session.token);
40+
MfaOtpRequestCache.clear(session.token);
41+
42+
// Destroy the current session
3643
await session.destroy();
3744

3845
// Send a logout event to Firefox even if the user is in a non-Sync flow.

packages/fxa-settings/src/lib/cache.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,20 @@ export class JwtTokenCache {
391391
this.state = { ...this.state };
392392
JwtTokenCache.listeners.forEach((l) => l());
393393
}
394+
395+
/**
396+
* Remove all cached tokens associated with the provided session.
397+
* @param sessionToken
398+
*/
399+
static clearTokens(sessionToken: string) {
400+
for (const key of Object.keys(this.state)) {
401+
if (key.startsWith(sessionToken)) {
402+
delete this.state[key];
403+
}
404+
}
405+
this.state = { ...this.state };
406+
JwtTokenCache.listeners.forEach((l) => l());
407+
}
394408
}
395409

396410
/**
@@ -460,4 +474,14 @@ export class MfaOtpRequestCache {
460474
static get(sessionToken: string, requiredScope: MfaScope) {
461475
return this.state[this.getKey(sessionToken, requiredScope)];
462476
}
477+
478+
static clear(sessionToken: string) {
479+
for (const key of Object.keys(this.state)) {
480+
console.log('!!! checking', key);
481+
if (key.startsWith(sessionToken)) {
482+
console.log('!!! deleting', key);
483+
delete this.state[key];
484+
}
485+
}
486+
}
463487
}

0 commit comments

Comments
 (0)