Automerge backed Markdown editor for the Atmosphere
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970import { test } from 'node:test'import assert from 'node:assert/strict'import http from 'node:http'import { createAuthProxy } from '../src/server/auth-proxy.mjs'
const listen = async server => { await new Promise(resolve => server.listen(0, '127.0.0.1', resolve)); return server.address().port }async function close(server) { server.closeAllConnections(); await new Promise(resolve => server.close(resolve)) }function request(port, path, headers = {}, method = 'GET', body) { return new Promise((resolve, reject) => { const req = http.request({ hostname: '127.0.0.1', port, path, method, headers: { host: 'reams.example.test', ...headers } }, async res => { try { let text = ''; for await (const chunk of res) text += chunk; resolve({ status: res.statusCode, headers: res.headers, body: text }) } catch (error) { reject(error) } }) req.on('error', reject); req.setTimeout(3000, () => req.destroy(new Error('Test request timed out'))); req.end(body) })}
test('private auth proxy preserves identity/cookies/nonce, exact routes, and rejects Host/Connection spoofing', async () => { const received = [] const auth = http.createServer(async (req, res) => { let body = ''; for await (const chunk of req) body += chunk received.push({ path: req.url, headers: req.headers, body }) res.writeHead(400, { 'content-type': 'application/json', 'dpop-nonce': 'real-nonce-shape', 'set-cookie': ['__Host-session=a; Secure; HttpOnly; Path=/', '__Host-other=b; Secure; Path=/'] }).end(JSON.stringify({ error: 'use_dpop_nonce' })) }) const authPort = await listen(auth) const proxy = createAuthProxy({ upstream: `http://127.0.0.1:${authPort}`, publicOrigin: 'https://reams.example.test' }) const web = http.createServer(async (req, res) => { if (!await proxy(req, res)) res.writeHead(404).end() }) const port = await listen(web) try { const result = await request(port, '/oauth/broker/token', { origin: 'https://reams.example.test', cookie: '__Host-session=a', dpop: 'proof-bytes', 'x-oauth-csrf': 'csrf-bytes', 'content-type': 'application/x-www-form-urlencoded' }, 'POST', 'grant_type=authorization_code') assert.equal(result.status, 400) assert.equal(result.headers['dpop-nonce'], 'real-nonce-shape') assert.equal(result.headers['set-cookie'].length, 2) assert.equal(result.headers['cache-control'], 'no-store') assert.equal(received[0].headers.host, 'reams.example.test') assert.equal(received[0].headers.dpop, 'proof-bytes') assert.equal(received[0].headers.cookie, '__Host-session=a') assert.equal(received[0].body, 'grant_type=authorization_code') for (const args of [ ['/oauth/broker/session', { host: 'wrong.test', 'x-forwarded-host': 'reams.example.test' }], ['https://wrong.test/oauth/broker/session', {}], ['/oauth/broker/not-a-route', {}], ]) assert.equal((await request(port, ...args)).status, 404) assert.equal((await request(port, '/oauth/broker/session', { connection: 'dpop', dpop: 'proof' })).status, 400) assert.equal(received.length, 1) } finally { await close(web); await close(auth) }})
test('proxy has no redirect/retry and terminates oversized responses and stalled requests', async () => { let mode = 'redirect', calls = 0 const auth = http.createServer((_req, res) => { calls++ if (mode === 'redirect') res.writeHead(302, { location: 'https://elsewhere.test' }).end() else if (mode === 'large') res.end('x'.repeat(129 * 1024)) else setTimeout(() => res.end('{}'), 200) }) const authPort = await listen(auth) const proxy = createAuthProxy({ upstream: `http://127.0.0.1:${authPort}`, publicOrigin: 'https://reams.example.test', timeoutMs: 40 }) const web = http.createServer(async (req, res) => { await proxy(req, res) }) const port = await listen(web) try { assert.equal((await request(port, '/oauth/broker/session')).status, 502) assert.equal(calls, 1) mode = 'large' await assert.rejects(request(port, '/oauth/broker/session')) mode = 'slow' assert.equal((await request(port, '/oauth/broker/session')).status, 502) assert.equal(calls, 3) } finally { await close(web); await close(auth) }})