// The forge auth wiring: the client metadata document, the login redirect // against a stubbed authorization server, the session cookie the callback // sets, and the owner-only procedure refusing a stranger's session. import { mkdtempSync, rmSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { createAppViewStore } from '@pdsjs/appview/store'; import Database from 'better-sqlite3'; import { afterEach, describe, expect, it } from 'vitest'; import { createForgeAuth } from '../src/auth.js'; import { createRemoteAccount } from '../src/remote.js'; import { createGitHostServer } from '../src/server.js'; const PDS_PORT = 2522; const PDS_BASE = `http://127.0.0.1:${PDS_PORT}`; const HOST_PORT = 2523; const ORIGIN = `http://127.0.0.1:${HOST_PORT}`; const DID = 'did:plc:forgeowner'; /** @type {Array<{close: () => Promise}>} */ const closers = []; /** @type {string[]} */ const dirs = []; afterEach(async () => { for (const closer of closers.splice(0)) { await closer.close().catch(() => {}); } for (const dir of dirs.splice(0)) rmSync(dir, { recursive: true, force: true }); }); describe('forge auth', () => { it('serves the client metadata document the client_id names', async () => { const dir = mkdtempSync(join(tmpdir(), 'git-host-auth-')); dirs.push(dir); const auth = createForgeAuth({ origin: ORIGIN, accountDid: DID }); const server = createGitHostServer({ account: createRemoteAccount({ service: PDS_BASE, account: DID, fetch: async () => Response.json({ did: DID, handle: 'forge.test' }), }), store: createAppViewStore(new Database(':memory:')), auth, origin: ORIGIN, }); closers.push(server); await server.listen(HOST_PORT); const doc = await fetch(`${ORIGIN}/oauth/client-metadata.json`).then( (r) => /** @type {any} */ (r.json()), ); expect(doc.client_id).toBe(`${ORIGIN}/oauth/client-metadata.json`); expect(doc.redirect_uris).toEqual([`${ORIGIN}/oauth/callback`]); expect(doc.dpop_bound_access_tokens).toBe(true); }); it('refuses an owner procedure without a session, and serves reads', async () => { const dir = mkdtempSync(join(tmpdir(), 'git-host-auth-')); dirs.push(dir); const server = createGitHostServer({ account: createRemoteAccount({ service: PDS_BASE, account: DID, fetch: async () => Response.json({ did: DID, handle: 'forge.test' }), }), store: createAppViewStore(new Database(':memory:')), origin: ORIGIN, }); closers.push(server); await server.listen(HOST_PORT); const refusal = await fetch(`${ORIGIN}/xrpc/dev.pdsjs.git.createRepo`, { method: 'POST', headers: { 'content-type': 'application/json', origin: ORIGIN }, body: JSON.stringify({ name: 'proj' }), }); expect(refusal.status).toBe(401); }); });