chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
// 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<void>}>} */
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);
});
});