Skip to content

Commit c1d5281

Browse files
committed
add back compat test
1 parent 3cb3c72 commit c1d5281

File tree

3 files changed

+114
-4
lines changed

3 files changed

+114
-4
lines changed

src/scenarios/client/auth/helpers/serverLifecycle.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ export class ServerLifecycle {
55
private httpServer: any = null;
66
private baseUrl: string = '';
77

8+
// Arrow function to avoid needing lots of .bind(this)
9+
getUrl = (): string => {
10+
return this.baseUrl;
11+
};
12+
813
async start(app: express.Application): Promise<string> {
914
this.app = app;
1015
this.httpServer = this.app.listen(0);
@@ -23,8 +28,4 @@ export class ServerLifecycle {
2328
}
2429
this.app = null;
2530
}
26-
27-
getUrl(): string {
28-
return this.baseUrl;
29-
}
3031
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import type { Scenario, ConformanceCheck } from '../../../types.js';
2+
import { ScenarioUrls } from '../../../types.js';
3+
import { createAuthServer } from './helpers/createAuthServer.js';
4+
import { createServer } from './helpers/createServer.js';
5+
import { ServerLifecycle } from './helpers/serverLifecycle.js';
6+
import { Request, Response } from 'express';
7+
8+
export class AuthMarchSpecBackcompatScenario implements Scenario {
9+
name = 'auth/march-spec-backcompat';
10+
description =
11+
'Tests March 2024 spec OAuth flow: no PRM (Protected Resource Metadata), OAuth metadata at root location';
12+
private server = new ServerLifecycle();
13+
private checks: ConformanceCheck[] = [];
14+
15+
async start(): Promise<ScenarioUrls> {
16+
this.checks = [];
17+
18+
// Legacy server, so we create the auth server endpoints on the
19+
// same URL as the main server (rather than separating AS / RS).
20+
const authApp = createAuthServer(this.checks, this.server.getUrl);
21+
const app = createServer(
22+
this.checks,
23+
this.server.getUrl,
24+
this.server.getUrl
25+
);
26+
app.use(authApp);
27+
28+
app.get(
29+
'/.well-known/oauth-protected-resource',
30+
(req: Request, res: Response) => {
31+
this.checks.push({
32+
id: 'no-prm-root',
33+
name: 'No PRM at Root',
34+
description:
35+
'Client attempted to fetch PRM at root location, but March spec does not have PRM',
36+
status: 'SUCCESS',
37+
timestamp: new Date().toISOString(),
38+
details: {
39+
url: req.url,
40+
path: req.path,
41+
note: 'March spec behavior: no PRM available'
42+
}
43+
});
44+
45+
res.status(404).json({
46+
error: 'not_found',
47+
error_description: 'PRM not available (March spec behavior)'
48+
});
49+
}
50+
);
51+
52+
app.get(
53+
'/.well-known/oauth-protected-resource/mcp',
54+
(req: Request, res: Response) => {
55+
this.checks.push({
56+
id: 'no-prm-path',
57+
name: 'No PRM at Path',
58+
description:
59+
'Client attempted to fetch PRM at path-based location, but March spec behavior does not have PRM',
60+
status: 'SUCCESS',
61+
timestamp: new Date().toISOString(),
62+
details: {
63+
url: req.url,
64+
path: req.path,
65+
note: 'March spec behavior: no PRM available'
66+
}
67+
});
68+
69+
res.status(404).json({
70+
error: 'not_found',
71+
error_description: 'PRM not available (March spec behavior)'
72+
});
73+
}
74+
);
75+
76+
await this.server.start(app);
77+
78+
return { serverUrl: `${this.server.getUrl()}/mcp` };
79+
}
80+
81+
async stop() {
82+
await this.server.stop();
83+
}
84+
85+
getChecks(): ConformanceCheck[] {
86+
const expectedSlugs = [
87+
'authorization-server-metadata',
88+
'client-registration',
89+
'authorization-request',
90+
'token-request'
91+
];
92+
93+
for (const slug of expectedSlugs) {
94+
if (!this.checks.find((c) => c.id === slug)) {
95+
this.checks.push({
96+
id: slug,
97+
name: `Expected Check Missing: ${slug}`,
98+
description: `Expected Check Missing: ${slug}`,
99+
status: 'FAILURE',
100+
timestamp: new Date().toISOString()
101+
});
102+
}
103+
}
104+
105+
return this.checks;
106+
}
107+
}

src/scenarios/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { InitializeScenario } from './client/initialize.js';
33
import { ToolsCallScenario } from './client/tools_call.js';
44
import { AuthBasicDCRScenario } from './client/auth/basic-dcr.js';
55
import { AuthBasicMetadataVar1Scenario } from './client/auth/basic-metadata-var1.js';
6+
import { AuthMarchSpecBackcompatScenario } from './client/auth/march-spec-backcompat.js';
67
import { ElicitationClientDefaultsScenario } from './client/elicitation-defaults.js';
78

89
// Import all new server test scenarios
@@ -117,6 +118,7 @@ const scenariosList: Scenario[] = [
117118
new ToolsCallScenario(),
118119
new AuthBasicDCRScenario(),
119120
new AuthBasicMetadataVar1Scenario(),
121+
new AuthMarchSpecBackcompatScenario(),
120122
new ElicitationClientDefaultsScenario()
121123
];
122124

0 commit comments

Comments
 (0)