feat(auth): add trusted-device 30-day 2FA skip (frontend)
Adds a "Trust this device for 30 days" checkbox to the 2FA challenge step, and a "Trusted devices" section to the 2FA settings card: list devices with a "this device" badge, per-row revoke, and a confirm-gated "sign out all other trusted devices" action. Both flows are opt-in and additive -- default unchecked, so nothing changes for a user who never uses them.
This commit is contained in:
@@ -89,7 +89,7 @@ describe('LoginPage', () => {
|
||||
return Promise.resolve({ data: { requiresTwoFactor: true, pendingToken: 'pending-abc' } } as any);
|
||||
}
|
||||
if (url === '/auth/2fa/challenge') {
|
||||
expect(payload).toEqual({ pendingToken: 'pending-abc', code: '123456' });
|
||||
expect(payload).toEqual({ pendingToken: 'pending-abc', code: '123456', trustDevice: false });
|
||||
return Promise.resolve({ data: { authenticated: true, provider: 'local' } } as any);
|
||||
}
|
||||
return Promise.resolve({ data: {} } as any);
|
||||
@@ -109,7 +109,7 @@ describe('LoginPage', () => {
|
||||
await userEvent.type(screen.getByLabelText('Code'), '123456');
|
||||
await userEvent.click(screen.getByRole('button', { name: 'Verify' }));
|
||||
|
||||
await waitFor(() => expect(mockedApi.post).toHaveBeenCalledWith('/auth/2fa/challenge', { pendingToken: 'pending-abc', code: '123456' }));
|
||||
await waitFor(() => expect(mockedApi.post).toHaveBeenCalledWith('/auth/2fa/challenge', { pendingToken: 'pending-abc', code: '123456', trustDevice: false }));
|
||||
await waitFor(() => expect(mockedApi.get).toHaveBeenCalledWith('/auth/me'));
|
||||
await waitFor(() => expect(mockNavigate).toHaveBeenCalledWith('/dashboard', { replace: true }));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user