File size: 3,219 Bytes
ec8acdf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';

import handler from '../api/agent-auth.ts';

const __dirname = dirname(fileURLToPath(import.meta.url));
const vercelConfig = JSON.parse(readFileSync(resolve(__dirname, '../vercel.json'), 'utf-8'));

const call = (host, init) =>
  handler(new Request('https://' + host + '/agent/auth', { headers: { host }, ...init }));

describe('agent-auth WWW-Authenticate challenge (/agent/auth)', () => {
  it('answers a plain GET with 401 + RFC 9728 WWW-Authenticate pointing at the PRM', async () => {
    const res = await call('worldmonitor.app', { method: 'GET' });
    assert.equal(res.status, 401);
    assert.equal(
      res.headers.get('www-authenticate'),
      'Bearer realm="worldmonitor", resource_metadata="https://worldmonitor.app/.well-known/oauth-protected-resource"',
    );
    assert.equal(res.headers.get('cache-control'), 'no-store');
    assert.equal(res.headers.get('access-control-allow-origin'), '*');
  });

  it('returns a machine-readable body with the auth discovery pointers', async () => {
    const body = await (await call('worldmonitor.app', { method: 'GET' })).json();
    assert.equal(body.error, 'unauthorized');
    assert.equal(
      body.resource_metadata,
      'https://worldmonitor.app/.well-known/oauth-protected-resource',
    );
    assert.equal(
      body.authorization_server,
      'https://worldmonitor.app/.well-known/oauth-authorization-server',
    );
    assert.equal(body.skill, 'https://worldmonitor.app/auth.md');
  });

  it('derives resource_metadata from the request Host (www stays self-consistent)', async () => {
    const res = await call('www.worldmonitor.app', { method: 'GET' });
    assert.equal(
      res.headers.get('www-authenticate'),
      'Bearer realm="worldmonitor", resource_metadata="https://www.worldmonitor.app/.well-known/oauth-protected-resource"',
    );
  });

  it('never reflects a spoofed Host — falls back to the apex origin', async () => {
    const res = await call('evil.example', { method: 'GET' });
    assert.match(
      res.headers.get('www-authenticate'),
      /resource_metadata="https:\/\/worldmonitor\.app\/\.well-known\/oauth-protected-resource"/,
    );
  });

  it('answers CORS preflight', async () => {
    const res = await call('worldmonitor.app', { method: 'OPTIONS' });
    assert.equal(res.status, 204);
    assert.equal(res.headers.get('access-control-allow-methods'), 'GET, HEAD, POST, OPTIONS');
  });

  it('is wired in vercel.json ahead of the SPA catch-all', () => {
    const rewrite = vercelConfig.rewrites.find((r) => r.source === '/agent/auth');
    assert.ok(rewrite, 'expected a rewrite for /agent/auth');
    assert.equal(rewrite.destination, '/api/agent-auth');

    const catchAllIndex = vercelConfig.rewrites.findIndex(
      (r) => r.destination === '/dashboard.html' && r.source.startsWith('/((?!'),
    );
    assert.ok(
      vercelConfig.rewrites.indexOf(rewrite) < catchAllIndex,
      '/agent/auth rewrite must precede the SPA catch-all so it is not swallowed',
    );
  });
});