import { test } from 'node:test'; import assert from 'node:assert/strict'; const store = new Map(); (globalThis as { localStorage?: unknown }).localStorage = { getItem: (k: string) => store.get(k) ?? null, setItem: (k: string, v: string) => { store.set(k, v); }, removeItem: (k: string) => { store.delete(k); }, }; const sessions = await import('../app/state/sessions'); const { guardRefreshFetch, refreshGrantToken } = await import('./oidcTokenRefresher'); const id = { userId: '@a:hs.example', deviceId: 'DEV1', baseUrl: 'https://hs.example', oidc: { issuer: 'https://auth.example/', clientId: 'c1', redirectUri: 'https://app/cb' }, }; const grant = (refresh: string): RequestInit => { const body = new URLSearchParams(); body.append('grant_type', 'refresh_token'); body.append('client_id', 'c1'); body.append('refresh_token', refresh); return { method: 'POST', body }; }; const persist = (access: string, refresh: string) => sessions.setFallbackSession(access, id.deviceId, id.userId, id.baseUrl, { refreshToken: refresh, oidc: id.oidc, expiresInMs: 300_000, }); test('[#16] recognises only refresh-token grants', () => { assert.equal(refreshGrantToken(grant('r1')), 'r1'); assert.equal( refreshGrantToken({ method: 'POST', body: 'grant_type=refresh_token&refresh_token=r2' }), 'r2', ); assert.equal( refreshGrantToken({ method: 'POST', body: 'grant_type=authorization_code&code=x' }), undefined, ); assert.equal(refreshGrantToken({ method: 'GET' }), undefined); assert.equal(refreshGrantToken(undefined), undefined); }); test('[#16] a real refresh is persisted before the lock is released', async () => { store.clear(); persist('at1', 'r1'); let calls = 0; const inner: typeof fetch = async () => { calls += 1; return new Response( JSON.stringify({ token_type: 'Bearer', access_token: 'at2', refresh_token: 'r2', expires_in: 300, }), { status: 200 }, ); }; const res = await guardRefreshFetch(inner, id)('https://auth.example/token', grant('r1')); assert.equal(calls, 1); assert.equal((await res.json()).access_token, 'at2', 'the SDK still reads the body'); const s = sessions.getFallbackSession(); assert.equal(s?.accessToken, 'at2'); assert.equal(s?.refreshToken, 'r2'); assert.ok((s?.expiresInMs ?? 0) > 290_000); }); test('[#16] the losing tab adopts the winner instead of spending a used token', async () => { store.clear(); persist('at-winner', 'r-winner'); // a sibling tab already rotated r-old let calls = 0; const inner: typeof fetch = async () => { calls += 1; return new Response('{"error":"invalid_grant"}', { status: 400 }); }; const res = await guardRefreshFetch(inner, id)('https://auth.example/token', grant('r-old')); assert.equal(calls, 0, 'never hits the issuer'); const body = await res.json(); assert.equal(res.status, 200); assert.equal(body.token_type, 'Bearer'); assert.equal(body.access_token, 'at-winner'); assert.equal(body.refresh_token, 'r-winner'); }); test('[#16] another account in storage is never adopted', async () => { store.clear(); sessions.setFallbackSession('at-other', 'DEV9', '@b:hs.example', id.baseUrl, { refreshToken: 'r-other', }); let calls = 0; const inner: typeof fetch = async () => { calls += 1; return new Response(JSON.stringify({ token_type: 'Bearer', access_token: 'at2' }), { status: 200, }); }; await guardRefreshFetch(inner, id)('https://auth.example/token', grant('r1')); assert.equal(calls, 1); }); test('[#16] other requests pass straight through', async () => { let seen = ''; const inner: typeof fetch = async (input) => { seen = String(input); return new Response('{}'); }; await guardRefreshFetch(inner, id)('https://hs.example/_matrix/client/v3/sync'); assert.equal(seen, 'https://hs.example/_matrix/client/v3/sync'); });