fix(auth): require a hashed poll secret for desktop handoff (#2357)

This commit is contained in:
Hampus authored and GitHub committed 2026-09-02 17:25:54 +02:00
1 parent b82681b77a
commit f703969e80
45 files changed
+382 -188

No files matched your search

@@ -12,6 +12,7 @@ import {createAuthHarness, createTestAccount, fetchMe, loginAccount} from './Aut
interface HandoffInitiateResponse {
code: string;
expires_at: string;
poll_secret: string;
}
interface HandoffInfoResponse {
@@ -93,7 +94,8 @@ describe('Auth desktop handoff flow', () => {
.expect(204)
.execute();
const completed = await createBuilderWithoutAuth<HandoffStatusResponse>(harness)
.get(`/auth/handoff/${initResp.code}/status`)
.post(`/auth/handoff/${initResp.code}/status`)
.body({poll_secret: initResp.poll_secret})
.execute();
const sessions = await createBuilder<Array<AuthSessionsResponseItem>>(harness, completed.token!)
.get('/auth/sessions')
@@ -116,13 +118,15 @@ describe('Auth desktop handoff flow', () => {
expect(initResp.code).toBeTruthy();
expect(validateHandoffCodeFormat(initResp.code)).toBe(true);
expect(initResp.expires_at).toBeTruthy();
expect(initResp.poll_secret).toBeTruthy();
const info = await createBuilderWithoutAuth<HandoffInfoResponse>(harness)
.get(`/auth/handoff/${initResp.code}/info`)
.execute();
expect(info.status).toBe('pending');
expect(info.client_info).toBeTruthy();
const pending = await createBuilderWithoutAuth<HandoffStatusResponse>(harness)
.get(`/auth/handoff/${initResp.code}/status`)
.post(`/auth/handoff/${initResp.code}/status`)
.body({poll_secret: initResp.poll_secret})
.execute();
expect(pending.status).toBe('pending');
await createBuilderWithoutAuth(harness)
@@ -135,7 +139,8 @@ describe('Auth desktop handoff flow', () => {
.expect(204)
.execute();
const completed = await createBuilderWithoutAuth<HandoffStatusResponse>(harness)
.get(`/auth/handoff/${initResp.code}/status`)
.post(`/auth/handoff/${initResp.code}/status`)
.body({poll_secret: initResp.poll_secret})
.execute();
expect(completed.status).toBe('completed');
expect(completed.token).toBeTruthy();
@@ -150,7 +155,8 @@ describe('Auth desktop handoff flow', () => {
const handoffUser = handoffSession.json as UserMeResponse;
expect(handoffUser.id).toBe(login.userId);
const retrieved = await createBuilderWithoutAuth<HandoffStatusResponse>(harness)
.get(`/auth/handoff/${initResp.code}/status`)
.post(`/auth/handoff/${initResp.code}/status`)
.body({poll_secret: initResp.poll_secret})
.execute();
expect(retrieved.status).toBe('expired');
});
@@ -159,7 +165,11 @@ describe('Auth desktop handoff flow', () => {
.post('/auth/handoff/initiate')
.body(null)
.execute();
await createBuilderWithoutAuth(harness).delete(`/auth/handoff/${initResp.code}`).expect(204).execute();
await createBuilderWithoutAuth(harness)
.delete(`/auth/handoff/${initResp.code}`)
.body({poll_secret: initResp.poll_secret})
.expect(204)
.execute();
const cancelled = await createBuilderWithoutAuth<HandoffStatusResponse>(harness)
.get(`/auth/handoff/${initResp.code}/status`)
.execute();
@@ -184,7 +194,8 @@ describe('Auth desktop handoff flow', () => {
.expect(204)
.execute();
const completed = await createBuilderWithoutAuth<HandoffStatusResponse>(harness)
.get(`/auth/handoff/${initResp.code}/status`)
.post(`/auth/handoff/${initResp.code}/status`)
.body({poll_secret: initResp.poll_secret})
.execute();
expect(completed.status).toBe('completed');
expect(completed.token).toBeTruthy();
@@ -233,8 +244,9 @@ describe('Auth desktop handoff flow', () => {
.expect(204)
.execute();
const completed = await createBuilderWithoutAuth<HandoffStatusResponse>(harness)
.get(`/auth/handoff/${initResp.code}/status`)
.post(`/auth/handoff/${initResp.code}/status`)
.header('x-forwarded-for', pollerIp)
.body({poll_secret: initResp.poll_secret})
.execute();
expect(completed.status).toBe('completed');
expect(completed.user_id).toBe(login.userId);
@@ -267,8 +279,9 @@ describe('Auth desktop handoff flow', () => {
.expect(204)
.execute();
const completed = await createBuilderWithoutAuth<HandoffStatusResponse>(harness)
.get(`/auth/handoff/${initResp.code}/status`)
.post(`/auth/handoff/${initResp.code}/status`)
.header('x-forwarded-for', pollerIp)
.body({poll_secret: initResp.poll_secret})
.execute();
expect(completed.status).toBe('completed');
expect(completed.user_id).toBe(login.userId);