durable-mcp-oauth-security-stress.test.mjs
51 lines 1.6 KB
Raw
sha256:b5f647cb9c409f563d4671fe3fc05ddea01fabfed9b41fc11cb923588e1c1baf mirror: GitHub Phase A durable MCP OAuth (#270) Human minor ⚠ breaking 10 days ago
1 /**
2 * Phase A — durable MCP OAuth: security-stress tier.
3 * Refresh storm / family churn must not degrade reuse detection or leak secrets.
4 */
5
6 import { describe, it, afterEach } from 'node:test';
7 import assert from 'node:assert/strict';
8 import {
9 createDurableMcpProvider,
10 mintMcpTokens,
11 } from './helpers/durable-mcp-oauth-harness.mjs';
12
13 const cleanups = [];
14 afterEach(async () => {
15 while (cleanups.length) await cleanups.pop()();
16 });
17
18 describe('Phase A security-stress — refresh storm', () => {
19 it('50 families × 5 rotations: reuse of first token always fails; no secret in errors', async () => {
20 const { provider, cleanup } = await createDurableMcpProvider();
21 cleanups.push(cleanup);
22
23 const families = [];
24 for (let i = 0; i < 50; i++) {
25 const { client, tokens } = await mintMcpTokens(provider, {
26 userId: `google:storm-${i}`,
27 clientName: `agent-${i}`,
28 scopes: ['vault:read'],
29 });
30 families.push({ client, first: tokens.refresh_token, current: tokens.refresh_token });
31 }
32
33 for (const fam of families) {
34 for (let r = 0; r < 5; r++) {
35 const next = await provider.exchangeRefreshToken(fam.client, fam.current);
36 fam.current = next.refresh_token;
37 }
38 }
39
40 for (const fam of families) {
41 try {
42 await provider.exchangeRefreshToken(fam.client, fam.first);
43 assert.fail('reuse of first token must fail');
44 } catch (e) {
45 const msg = String(e.message || e);
46 assert.ok(/reuse|revoked|Unknown/i.test(msg), msg);
47 assert.ok(!msg.includes(fam.first.split('.')[1] || '___'));
48 }
49 }
50 });
51 });
File History 1 commit
sha256:b5f647cb9c409f563d4671fe3fc05ddea01fabfed9b41fc11cb923588e1c1baf mirror: GitHub Phase A durable MCP OAuth (#270) Human minor 10 days ago