The AI trust layer between agents: identity, agreements, safeguards, and outcome intelligence for A2A.

Viewing files at commit 95b0e11125d2Commit detailsView latest

tests/hosted-auth.test.ts 64 lines · 2.7 KB · typescript
1
import { describe, expect, it } from 'vitest';
2
import { POST as mcpHandler } from '../api/mcp.js';
3
import { GET as metadataHandler } from '../api/oauth-protected-resource.js';
4
import { dashboardTokenFromCookie } from '../apps/api/src/auth0.js';
5
6
describe('hosted MCP authorization', () => {
7
  it('reads only the named dashboard session cookie', () => {
8
    expect(dashboardTokenFromCookie('other=x; openclasp_session=token%2Evalue; last=y')).toBe(
9
      'token.value',
10
    );
11
    expect(dashboardTokenFromCookie('other=x')).toBeUndefined();
12
  });
13
  it('challenges unauthenticated remote MCP requests', async () => {
14
    const response = await mcpHandler(
15
      new Request('https://openclasp.example/mcp', {
16
        method: 'POST',
17
        headers: { 'content-type': 'application/json' },
18
        body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'tools/list' }),
19
      }),
20
    );
21
    expect(response.status).toBe(401);
22
    expect(response.headers.get('www-authenticate')).toBe(
23
      'Bearer resource_metadata="https://openclasp.example/.well-known/oauth-protected-resource/mcp", scope="mcp:access profile:read interaction:write feedback:write agent:manage"',
24
    );
25
    expect(response.headers.get('www-authenticate')).not.toContain('invalid_token');
26
    expect(response.headers.get('cache-control')).toBe('no-store');
27
    expect(await response.text()).toBe('');
28
  });
29
30
  it('publishes Auth0 protected-resource metadata', async () => {
31
    const response = metadataHandler(
32
      new Request('https://openclasp.example/.well-known/oauth-protected-resource'),
33
    );
34
    expect(response.status).toBe(200);
35
    await expect(response.json()).resolves.toMatchObject({
36
      resource: 'https://openclasp.example/mcp',
37
      authorization_servers: ['https://openclasp.example'],
38
      scopes_supported: expect.arrayContaining([
39
        'mcp:access',
40
        'profile:read',
41
        'interaction:write',
42
        'feedback:write',
43
        'agent:manage',
44
      ]),
45
    });
46
  });
47
48
  it('keeps protected-resource metadata bound to the requested host during domain migration', async () => {
49
    const configuredUrl = process.env.OPENCLASP_MCP_URL;
50
    process.env.OPENCLASP_MCP_URL = 'https://openclasp.dev/mcp';
51
    try {
52
      const legacyResponse = metadataHandler(
53
        new Request('https://openclasp.vercel.app/.well-known/oauth-protected-resource/mcp'),
54
      );
55
      await expect(legacyResponse.json()).resolves.toMatchObject({
56
        resource: 'https://openclasp.vercel.app/mcp',
57
        authorization_servers: ['https://openclasp.vercel.app'],
58
      });
59
    } finally {
60
      if (configuredUrl === undefined) delete process.env.OPENCLASP_MCP_URL;
61
      else process.env.OPENCLASP_MCP_URL = configuredUrl;
62
    }
63
  });
64
});