Skip to content

Commit 3aced3c

Browse files
committed
add 3rd variation of metadata
1 parent e9f657b commit 3aced3c

File tree

4 files changed

+17
-19
lines changed

4 files changed

+17
-19
lines changed

examples/clients/typescript/helpers/withOAuthRetry.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ export const handle401 = async (
1414
serverUrl: string | URL
1515
): Promise<void> => {
1616
const resourceMetadataUrl = extractResourceMetadataUrl(response);
17-
1817
let result = await auth(provider, {
1918
serverUrl,
2019
resourceMetadataUrl,

src/scenarios/client/auth/basic-metadata.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,6 @@ export class AuthBasicMetadataVar1Scenario implements Scenario {
2626
this.server.getUrl,
2727
this.authServer.getUrl,
2828
{
29-
// TODO: this will put this path in the WWW-Authenticate header
30-
// but RFC 9728 states that in that case, the resource in the PRM
31-
// must match the URL used to make the request to the resource server.
32-
// We'll need to establish an opinion on whether that means the
33-
// URL for the metadata fetch, or the URL for the MCP endpoint,
34-
// or more generally what are the valid scenarios / combos.
3529
prmPath: '/.well-known/oauth-protected-resource'
3630
}
3731
);
@@ -172,11 +166,14 @@ export class AuthBasicMetadataVar3Scenario implements Scenario {
172166
const app = createServer(
173167
this.checks,
174168
this.server.getUrl,
175-
this.authServer.getUrl,
169+
() => {
170+
return `${this.authServer.getUrl()}/tenant1`;
171+
},
176172
{
177173
// This is a custom path, so unable to get via probing, it's only available
178174
// via following the `resource_metadata_url` in the WWW-Authenticate header.
179-
prmPath: '/.well-known/oauth-protected-resource'
175+
// The resource must match the original request URL per RFC 9728.
176+
prmPath: '/custom/metadata/location.json'
180177
}
181178
);
182179
await this.server.start(app);

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,15 @@ export function createServer(
6767
}
6868
});
6969

70+
// Resource is usually $baseUrl/mcp, but if PRM is at the root,
71+
// the resource identifier is the root.
72+
const resource =
73+
prmPath === '/.well-known/oauth-protected-resource'
74+
? getBaseUrl()
75+
: `${getBaseUrl()}/mcp`;
76+
7077
res.json({
71-
resource: getBaseUrl(),
78+
resource,
7279
authorization_servers: [getAuthServerUrl()]
7380
});
7481
});

src/scenarios/client/auth/index.test.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,21 @@
1+
import { authScenariosList } from './index.js';
12
import {
23
runClientAgainstScenario,
34
SpawnedClientRunner
45
} from './test_helpers/testClient.js';
56
import path from 'path';
6-
import { listScenarios } from '../../index.js';
77

88
describe('Client Auth Scenarios', () => {
99
const clientPath = path.join(
1010
process.cwd(),
1111
'examples/clients/typescript/auth-test.ts'
1212
);
1313

14-
// Get all scenarios that start with 'auth/'
15-
const authScenarios = listScenarios().filter((name) =>
16-
name.startsWith('auth/')
17-
);
18-
1914
// Generate individual test for each auth scenario
20-
for (const scenarioName of authScenarios) {
21-
test(`${scenarioName} passes`, async () => {
15+
for (const scenario of authScenariosList) {
16+
test(`${scenario.name} passes`, async () => {
2217
const runner = new SpawnedClientRunner(clientPath);
23-
await runClientAgainstScenario(runner, scenarioName);
18+
await runClientAgainstScenario(runner, scenario.name);
2419
});
2520
}
2621
});

0 commit comments

Comments
 (0)