Skip to content

Commit 1274d03

Browse files
committed
fix(auth): preserve desktop passkey enrollment
1 parent d9e1d9b commit 1274d03

2 files changed

Lines changed: 24 additions & 1 deletion

File tree

src/client/features/auth/FirstDeviceEnrollment.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
7474
if (mounted) feedback = 'Setup QR unavailable. Use the setup link below.';
7575
});
7676
const desktop = window.matchMedia?.('(min-width: 768px)').matches ?? false;
77-
if (desktop) pollTimer = setInterval(() => void pollStatus(), 15_000);
77+
if (!enrollmentTicket && desktop) pollTimer = setInterval(() => void pollStatus(), 15_000);
7878
});
7979
8080
onDestroy(() => {

src/client/features/auth/FirstDeviceEnrollment.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ function props(
3131
canonicalOrigin: string;
3232
onAuthenticated: ReturnType<typeof vi.fn>;
3333
onLocked: ReturnType<typeof vi.fn>;
34+
enrollmentTicket: string;
3435
}> = {},
3536
) {
3637
const client: TestClient = {
@@ -188,6 +189,28 @@ describe('FirstDeviceEnrollment', () => {
188189
expect(values.client.status).not.toHaveBeenCalled();
189190
});
190191

192+
it('does not cancel ticket enrollment when an existing relay is locked on desktop', async () => {
193+
vi.useFakeTimers();
194+
window.matchMedia = vi.fn(() => ({ matches: true })) as never;
195+
const values = props({
196+
enrollmentTicket: 'ticket',
197+
client: {
198+
...props().client,
199+
status: vi.fn(async () => ({ status: 'locked', publicOrigin: 'https://relay.example' })),
200+
},
201+
});
202+
mount(values);
203+
await fireEvent.input(screen.getByLabelText('Device nickname'), { target: { value: 'Omni' } });
204+
await fireEvent.click(screen.getByRole('button', { name: 'Authorize this device' }));
205+
await vi.advanceTimersByTimeAsync(15_000);
206+
await vi.waitFor(() =>
207+
expect(values.client.verifyRegistration).toHaveBeenCalledWith({ id: 'credential' }, 'Omni'),
208+
);
209+
expect(values.client.status).not.toHaveBeenCalled();
210+
expect(values.onLocked).not.toHaveBeenCalled();
211+
expect(values.onAuthenticated).toHaveBeenCalledOnce();
212+
});
213+
191214
it('does not continue an in-flight registration after another device wins polling', async () => {
192215
vi.useFakeTimers();
193216
window.matchMedia = vi.fn(() => ({ matches: true })) as never;

0 commit comments

Comments
 (0)