skybridge 2.0.0-beta.36d7fef → 2.0.0-beta.3a8ddf2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/app.d.ts +80 -51
- package/dist/server/app.js +57 -70
- package/dist/server/app.js.map +1 -1
- package/dist/server/app.test.js +97 -0
- package/dist/server/app.test.js.map +1 -0
- package/dist/server/auth/index.d.ts +1 -1
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/auth/setup.test.js +56 -54
- package/dist/server/auth/setup.test.js.map +1 -1
- package/dist/server/auth-extra.test-d.js +91 -35
- package/dist/server/auth-extra.test-d.js.map +1 -1
- package/dist/server/auth.d.ts +1 -1
- package/dist/server/auth.js +1 -1
- package/dist/server/auth.js.map +1 -1
- package/dist/server/build-manifest.test.js +1 -1
- package/dist/server/build-manifest.test.js.map +1 -1
- package/dist/server/express.d.ts +6 -6
- package/dist/server/express.js +16 -22
- package/dist/server/express.js.map +1 -1
- package/dist/server/express.test.js +120 -31
- package/dist/server/express.test.js.map +1 -1
- package/dist/server/index.d.ts +3 -2
- package/dist/server/index.js +2 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp-errors.test.js +5 -1
- package/dist/server/mcp-errors.test.js.map +1 -1
- package/dist/server/middleware.test.js +184 -135
- package/dist/server/middleware.test.js.map +1 -1
- package/dist/server/register-tool.test.js +8 -4
- package/dist/server/register-tool.test.js.map +1 -1
- package/dist/server/server.d.ts +19 -44
- package/dist/server/server.js +17 -62
- package/dist/server/server.js.map +1 -1
- package/dist/server/skills-integration.test.js +7 -2
- package/dist/server/skills-integration.test.js.map +1 -1
- package/dist/server/tool-extra.test.js +30 -14
- package/dist/server/tool-extra.test.js.map +1 -1
- package/dist/server/view-resource-resolution.test.js +7 -3
- package/dist/server/view-resource-resolution.test.js.map +1 -1
- package/dist/test/utils.d.ts +3 -3
- package/dist/test/utils.js +211 -197
- package/dist/test/utils.js.map +1 -1
- package/dist/test/view.test.js +19 -15
- package/dist/test/view.test.js.map +1 -1
- package/dist/web/generate-helpers.d.ts +15 -12
- package/dist/web/generate-helpers.js +15 -12
- package/dist/web/generate-helpers.js.map +1 -1
- package/package.json +1 -2
- package/dist/server/factory-loader.test.js +0 -81
- package/dist/server/factory-loader.test.js.map +0 -1
- /package/dist/server/{factory-loader.test.d.ts → app.test.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.test.js","sourceRoot":"","sources":["../../src/server/app.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { Client, InMemoryTransport } from \"@modelcontextprotocol/client\";\nimport { describe, expect, it } from \"vitest\";\nimport { Skybridge } from \"./app.js\";\n\nconst oauthConfig = {\n oauthMetadata: {\n issuer: \"https://issuer.example.com\",\n authorization_endpoint: \"https://issuer.example.com/authorize\",\n token_endpoint: \"https://issuer.example.com/token\",\n response_types_supported: [\"code\"],\n },\n verifier: {\n verifyAccessToken: async () => ({\n token: \"t\",\n clientId: \"c\",\n scopes: [],\n extra: {},\n }),\n },\n};\n\ndescribe(\"Skybridge setup and handler\", () => {\n it(\"resolves setup once and passes the context to the per-request handler\", async () => {\n let loads = 0;\n const app = new Skybridge({\n name: \"test\",\n version: \"1.0.0\",\n setup: async () => {\n loads++;\n return { greeting: await Promise.resolve(\"hello\") };\n },\n handler: (server, { greeting }) =>\n server.registerTool(\n { name: \"greet\", description: \"greet\" },\n async () => ({ content: [{ type: \"text\", text: greeting }] }),\n ),\n });\n\n expect(loads).toBe(0);\n\n const call = async () => {\n const client = new Client({ name: \"client\", version: \"1.0.0\" });\n const [clientTransport, serverTransport] =\n InMemoryTransport.createLinkedPair();\n await app.connect(serverTransport);\n await client.connect(clientTransport);\n const result = await client.callTool({ name: \"greet\" });\n await client.close();\n return result;\n };\n\n expect(await call()).toMatchObject({\n content: [{ type: \"text\", text: \"hello\" }],\n });\n expect(await call()).toMatchObject({\n content: [{ type: \"text\", text: \"hello\" }],\n });\n expect(loads).toBe(1);\n });\n\n it(\"retries setup after a failed first resolution\", async () => {\n let attempts = 0;\n const app = new Skybridge({\n name: \"test\",\n version: \"1.0.0\",\n setup: async () => {\n attempts++;\n if (attempts === 1) {\n throw new Error(\"transient\");\n }\n },\n handler: (server) => server,\n });\n\n const [, first] = InMemoryTransport.createLinkedPair();\n await expect(app.connect(first)).rejects.toThrow(\"transient\");\n\n const [, second] = InMemoryTransport.createLinkedPair();\n await expect(app.connect(second)).resolves.toBeUndefined();\n expect(attempts).toBe(2);\n });\n\n it(\"rejects a handler that returns a promise\", async () => {\n const app = new Skybridge({\n name: \"test\",\n version: \"1.0.0\",\n // @ts-expect-error the handler runs per request and must stay synchronous\n handler: async (server) => server,\n });\n const [, serverTransport] = InMemoryTransport.createLinkedPair();\n await expect(app.connect(serverTransport)).rejects.toThrow(\n /must be synchronous/,\n );\n });\n\n it(\"resolves an oauth function with the setup config before wiring the routes\", async () => {\n let seen: unknown;\n const app = new Skybridge({\n name: \"test\",\n version: \"1.0.0\",\n setup: () => ({ issuer: \"https://issuer.example.com\" }),\n oauth: (config) => {\n seen = config;\n return oauthConfig;\n },\n handler: (server) => server,\n });\n\n expect(seen).toBeUndefined();\n const [, serverTransport] = InMemoryTransport.createLinkedPair();\n await app.connect(serverTransport);\n expect(seen).toEqual({ issuer: \"https://issuer.example.com\" });\n });\n});\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { OAuthMetadata } from "@modelcontextprotocol/server";
|
|
2
2
|
import type { ExtraClaims, TokenVerifier } from "../auth.js";
|
|
3
3
|
/**
|
|
4
|
-
* Resource-server OAuth config for `
|
|
4
|
+
* Resource-server OAuth config for the `oauth` field of `SkybridgeConfig`.
|
|
5
5
|
*
|
|
6
6
|
* `TExtra` comes from the `verifier` and flows on to tool handlers and
|
|
7
7
|
* `mcpMiddleware`, so the claim shape is declared once by whoever checks the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/auth/index.ts"],"names":[],"mappings":"","sourcesContent":["import type { OAuthMetadata } from \"@modelcontextprotocol/server\";\nimport type { ExtraClaims, TokenVerifier } from \"../auth.js\";\n\n/**\n * Resource-server OAuth config for `
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/auth/index.ts"],"names":[],"mappings":"","sourcesContent":["import type { OAuthMetadata } from \"@modelcontextprotocol/server\";\nimport type { ExtraClaims, TokenVerifier } from \"../auth.js\";\n\n/**\n * Resource-server OAuth config for the `oauth` field of `SkybridgeConfig`.\n *\n * `TExtra` comes from the `verifier` and flows on to tool handlers and\n * `mcpMiddleware`, so the claim shape is declared once by whoever checks the\n * token. The branded providers set it from the claims their IdP documents.\n *\n * @typeParam TExtra - Claims the verifier populates in `AuthInfo[\"extra\"]`.\n */\nexport type OAuthConfig<TExtra extends ExtraClaims = ExtraClaims> = {\n /**\n * Public URL of this server; sets `resourceServerUrl` and the\n * `resource_metadata` URL. When omitted, it is inferred per request from\n * `x-forwarded-host`/`origin`/`host` headers.\n */\n baseUrl?: string;\n /** AS metadata served at `/.well-known/oauth-authorization-server`. */\n oauthMetadata: OAuthMetadata;\n /** Scopes advertised in protected-resource metadata. */\n scopesSupported?: string[];\n /** Server-wide required-scope floor. */\n requiredScopes?: string[];\n /**\n * Checks each bearer token. Build one with `createJwksVerifier` for a\n * JWT-issuing IdP, or supply your own for opaque tokens.\n */\n verifier: TokenVerifier<TExtra>;\n};\n"]}
|
|
@@ -54,7 +54,6 @@ async function bootServer(jwksUri, { baseUrl = "https://app.example.test" } = {}
|
|
|
54
54
|
const app = new Skybridge({
|
|
55
55
|
name: "auth-test",
|
|
56
56
|
version: "0.0.0",
|
|
57
|
-
capabilities: {},
|
|
58
57
|
oauth: {
|
|
59
58
|
...(baseUrl === null ? {} : { baseUrl }),
|
|
60
59
|
oauthMetadata: {
|
|
@@ -71,18 +70,19 @@ async function bootServer(jwksUri, { baseUrl = "https://app.example.test" } = {}
|
|
|
71
70
|
scopesSupported: ["openid", "email"],
|
|
72
71
|
requiredScopes: ["openid"],
|
|
73
72
|
},
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
73
|
+
handler: (server) => server.registerTool({
|
|
74
|
+
name: "whoami",
|
|
75
|
+
description: "Returns the caller identity.",
|
|
76
|
+
inputSchema: {},
|
|
77
|
+
}, (_args, extra) => ({
|
|
78
|
+
structuredContent: {
|
|
79
|
+
clientId: extra.http?.authInfo?.clientId ?? null,
|
|
80
|
+
},
|
|
81
|
+
content: [
|
|
82
|
+
{ type: "text", text: extra.http?.authInfo?.clientId ?? "anon" },
|
|
83
|
+
],
|
|
84
|
+
})),
|
|
85
|
+
});
|
|
86
86
|
const httpServer = http.createServer();
|
|
87
87
|
await createApp({ app, httpServer });
|
|
88
88
|
const listening = http.createServer(app.express);
|
|
@@ -182,7 +182,6 @@ async function bootMixedServer(jwksUri) {
|
|
|
182
182
|
const app = new Skybridge({
|
|
183
183
|
name: "mixed-auth-test",
|
|
184
184
|
version: "0.0.0",
|
|
185
|
-
capabilities: {},
|
|
186
185
|
oauth: {
|
|
187
186
|
baseUrl: "https://app.example.test",
|
|
188
187
|
oauthMetadata: {
|
|
@@ -197,36 +196,37 @@ async function bootMixedServer(jwksUri) {
|
|
|
197
196
|
jwksUri,
|
|
198
197
|
}),
|
|
199
198
|
},
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
199
|
+
handler: (server) => server
|
|
200
|
+
.registerTool({
|
|
201
|
+
name: "public-whoami",
|
|
202
|
+
description: "Public.",
|
|
203
|
+
inputSchema: {},
|
|
204
|
+
auth: { allowsAnonymous: true },
|
|
205
|
+
}, (_args, extra) => ({
|
|
206
|
+
content: [
|
|
207
|
+
{ type: "text", text: extra.http?.authInfo?.clientId ?? "anon" },
|
|
208
|
+
],
|
|
209
|
+
}))
|
|
210
|
+
.registerTool({
|
|
211
|
+
name: "private-whoami",
|
|
212
|
+
description: "Private.",
|
|
213
|
+
inputSchema: {},
|
|
214
|
+
auth: {},
|
|
215
|
+
}, (_args, extra) => ({
|
|
216
|
+
content: [
|
|
217
|
+
{ type: "text", text: extra.http?.authInfo?.clientId ?? "anon" },
|
|
218
|
+
],
|
|
219
|
+
}))
|
|
220
|
+
.registerTool({
|
|
221
|
+
name: "undeclared-whoami",
|
|
222
|
+
description: "Registered without auth or securitySchemes.",
|
|
223
|
+
inputSchema: {},
|
|
224
|
+
}, (_args, extra) => ({
|
|
225
|
+
content: [
|
|
226
|
+
{ type: "text", text: extra.http?.authInfo?.clientId ?? "anon" },
|
|
227
|
+
],
|
|
228
|
+
})),
|
|
229
|
+
});
|
|
230
230
|
const httpServer = http.createServer();
|
|
231
231
|
await createApp({ app, httpServer });
|
|
232
232
|
const listening = http.createServer(app.express);
|
|
@@ -399,7 +399,6 @@ async function bootScopedServer(jwksUri) {
|
|
|
399
399
|
const app = new Skybridge({
|
|
400
400
|
name: "scoped-auth-test",
|
|
401
401
|
version: "0.0.0",
|
|
402
|
-
capabilities: {},
|
|
403
402
|
oauth: {
|
|
404
403
|
baseUrl: "https://app.example.test",
|
|
405
404
|
oauthMetadata: {
|
|
@@ -414,12 +413,13 @@ async function bootScopedServer(jwksUri) {
|
|
|
414
413
|
jwksUri,
|
|
415
414
|
}),
|
|
416
415
|
},
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
416
|
+
handler: (server) => server.registerTool({
|
|
417
|
+
name: "checkout",
|
|
418
|
+
description: "Needs the checkout scope.",
|
|
419
|
+
inputSchema: {},
|
|
420
|
+
auth: { scopes: ["checkout"] },
|
|
421
|
+
}, () => ({ content: [{ type: "text", text: "ok" }] })),
|
|
422
|
+
});
|
|
423
423
|
const httpServer = http.createServer();
|
|
424
424
|
await createApp({ app, httpServer });
|
|
425
425
|
const listening = http.createServer(app.express);
|
|
@@ -494,8 +494,8 @@ describe("oauth config validation", () => {
|
|
|
494
494
|
token_endpoint: `${ISSUER}/token`,
|
|
495
495
|
response_types_supported: ["code"],
|
|
496
496
|
};
|
|
497
|
-
it("
|
|
498
|
-
|
|
497
|
+
it("rejects a non-absolute baseUrl when the app is first used", async () => {
|
|
498
|
+
const app = new Skybridge({
|
|
499
499
|
name: "t",
|
|
500
500
|
version: "0",
|
|
501
501
|
oauth: {
|
|
@@ -506,7 +506,9 @@ describe("oauth config validation", () => {
|
|
|
506
506
|
audience: AUDIENCE,
|
|
507
507
|
}),
|
|
508
508
|
},
|
|
509
|
-
|
|
509
|
+
handler: (server) => server,
|
|
510
|
+
});
|
|
511
|
+
await expect(app.createServerInstance()).rejects.toThrow(/baseUrl must be a valid absolute URL/);
|
|
510
512
|
});
|
|
511
513
|
});
|
|
512
514
|
//# sourceMappingURL=setup.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.test.js","sourceRoot":"","sources":["../../../src/server/auth/setup.test.ts"],"names":[],"mappings":"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","sourcesContent":["// @vitest-environment node\nimport http from \"node:http\";\nimport {\n Client,\n StreamableHTTPClientTransport,\n} from \"@modelcontextprotocol/client\";\nimport type { RequestHandler } from \"express\";\nimport * as jose from \"jose\";\nimport { afterEach, describe, expect, it, vi } from \"vitest\";\nimport { Skybridge } from \"../app.js\";\nimport { McpServer } from \"../server.js\";\nimport { createJwksVerifier } from \"./verify.js\";\n\nvi.mock(\"@skybridge/devtools\", () => ({\n devtoolsStaticServer: () =>\n ((_req: unknown, _res: unknown, next: () => void) =>\n next()) as RequestHandler,\n}));\nvi.mock(\"../viewsDevServer.js\", () => ({\n viewsDevServer: (_httpServer: unknown) =>\n ((_req: unknown, _res: unknown, next: () => void) =>\n next()) as RequestHandler,\n}));\n\nconst ISSUER = \"https://issuer.test\";\nconst AUDIENCE = \"api://default\";\n\nlet jwksServer: http.Server | undefined;\nlet appServer: http.Server | undefined;\nafterEach(() => {\n jwksServer?.close();\n appServer?.close();\n});\n\nasync function startJwks() {\n const { publicKey, privateKey } = await jose.generateKeyPair(\"RS256\");\n const jwk = {\n ...(await jose.exportJWK(publicKey)),\n kid: \"test-key\",\n alg: \"RS256\",\n use: \"sig\",\n };\n const server = http.createServer((_req, res) => {\n res.setHeader(\"content-type\", \"application/json\");\n res.end(JSON.stringify({ keys: [jwk] }));\n });\n await new Promise<void>((resolve) => server.listen(0, resolve));\n jwksServer = server;\n const port = (server.address() as { port: number }).port;\n return { privateKey, jwksUri: `http://localhost:${port}/jwks` };\n}\n\nfunction signToken(key: CryptoKey, scope = \"openid email\") {\n return new jose.SignJWT({\n client_id: \"client-1\",\n scope,\n sub: \"user-1\",\n })\n .setProtectedHeader({ alg: \"RS256\", kid: \"test-key\" })\n .setIssuer(ISSUER)\n .setAudience(AUDIENCE)\n .setExpirationTime(\"1h\")\n .sign(key);\n}\n\nasync function bootServer(\n jwksUri: string,\n { baseUrl = \"https://app.example.test\" }: { baseUrl?: string | null } = {},\n) {\n const { createApp } = await import(\"../express.js\");\n const app = new Skybridge(\n {\n name: \"auth-test\",\n version: \"0.0.0\",\n capabilities: {},\n oauth: {\n ...(baseUrl === null ? {} : { baseUrl }),\n oauthMetadata: {\n issuer: ISSUER,\n authorization_endpoint: `${ISSUER}/authorize`,\n token_endpoint: `${ISSUER}/token`,\n response_types_supported: [\"code\"],\n },\n verifier: createJwksVerifier({\n issuer: ISSUER,\n audience: AUDIENCE,\n jwksUri,\n }),\n scopesSupported: [\"openid\", \"email\"],\n requiredScopes: [\"openid\"],\n },\n },\n (server) =>\n server.registerTool(\n {\n name: \"whoami\",\n description: \"Returns the caller identity.\",\n inputSchema: {},\n },\n (_args, extra) => ({\n structuredContent: {\n clientId: extra.http?.authInfo?.clientId ?? null,\n },\n content: [\n { type: \"text\", text: extra.http?.authInfo?.clientId ?? \"anon\" },\n ],\n }),\n ),\n );\n\n const httpServer = http.createServer();\n await createApp({ app, httpServer });\n const listening = http.createServer(app.express);\n await new Promise<void>((resolve) => listening.listen(0, resolve));\n appServer = listening;\n const port = (listening.address() as { port: number }).port;\n return `http://localhost:${port}`;\n}\n\ndescribe(\"setupOAuth wiring\", () => {\n it(\"serves protected-resource metadata\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootServer(jwksUri);\n\n const res = await fetch(`${base}/.well-known/oauth-protected-resource`);\n expect(res.status).toBe(200);\n const body = (await res.json()) as {\n resource: string;\n authorization_servers: string[];\n scopes_supported: string[];\n };\n expect(body.resource).toBe(\"https://app.example.test/\");\n expect(body.authorization_servers).toContain(ISSUER);\n expect(body.scopes_supported).toEqual([\"openid\", \"email\"]);\n });\n\n it(\"rejects /mcp without a token (401 + WWW-Authenticate)\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootServer(jwksUri);\n\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ jsonrpc: \"2.0\", method: \"initialize\", id: 1 }),\n });\n expect(res.status).toBe(401);\n expect(res.headers.get(\"www-authenticate\")).toMatch(/resource_metadata=/);\n });\n\n it(\"threads authInfo into the tool handler for a valid token\", async () => {\n const { privateKey, jwksUri } = await startJwks();\n const base = await bootServer(jwksUri);\n const token = await signToken(privateKey);\n\n const client = new Client({ name: \"test-client\", version: \"0.0.0\" });\n const transport = new StreamableHTTPClientTransport(\n new URL(`${base}/mcp`),\n { requestInit: { headers: { Authorization: `Bearer ${token}` } } },\n );\n await client.connect(transport);\n\n const result = (await client.callTool({\n name: \"whoami\",\n arguments: {},\n })) as unknown as {\n content: { type: string; text: string }[];\n };\n expect(result.content[0]?.text).toBe(\"client-1\");\n\n await client.close();\n });\n});\n\ndescribe(\"baseUrl inferred from headers\", () => {\n it(\"derives the resource origin from x-forwarded-host\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootServer(jwksUri, { baseUrl: null });\n\n const res = await fetch(`${base}/.well-known/oauth-protected-resource`, {\n headers: { \"x-forwarded-host\": \"infer.example.test\" },\n });\n expect(res.status).toBe(200);\n const body = (await res.json()) as { resource: string };\n expect(body.resource).toBe(\"https://infer.example.test/\");\n });\n\n it(\"uses the first hop of a forwarded-host chain\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootServer(jwksUri, { baseUrl: null });\n\n const res = await fetch(`${base}/.well-known/oauth-protected-resource`, {\n headers: {\n \"x-forwarded-host\": \"public.example, internal.local\",\n \"x-forwarded-proto\": \"https, http\",\n },\n });\n expect(res.status).toBe(200);\n const body = (await res.json()) as { resource: string };\n expect(body.resource).toBe(\"https://public.example/\");\n });\n\n it(\"ignores the client Origin header, using Host instead\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootServer(jwksUri, { baseUrl: null });\n\n const res = await fetch(`${base}/.well-known/oauth-protected-resource`, {\n headers: { origin: \"https://chatgpt.com\" },\n });\n expect(res.status).toBe(200);\n const body = (await res.json()) as { resource: string };\n expect(body.resource).toMatch(/^http:\\/\\/(localhost|127\\.0\\.0\\.1):/);\n });\n\n it(\"points the 401 WWW-Authenticate at the inferred host\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootServer(jwksUri, { baseUrl: null });\n\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-forwarded-host\": \"infer.example.test\",\n },\n body: JSON.stringify({ jsonrpc: \"2.0\", method: \"initialize\", id: 1 }),\n });\n expect(res.status).toBe(401);\n expect(res.headers.get(\"www-authenticate\")).toMatch(\n /resource_metadata=\"https:\\/\\/infer\\.example\\.test\\//,\n );\n });\n});\n\nasync function bootMixedServer(jwksUri: string) {\n const { createApp } = await import(\"../express.js\");\n const app = new Skybridge(\n {\n name: \"mixed-auth-test\",\n version: \"0.0.0\",\n capabilities: {},\n oauth: {\n baseUrl: \"https://app.example.test\",\n oauthMetadata: {\n issuer: ISSUER,\n authorization_endpoint: `${ISSUER}/authorize`,\n token_endpoint: `${ISSUER}/token`,\n response_types_supported: [\"code\"],\n },\n verifier: createJwksVerifier({\n issuer: ISSUER,\n audience: AUDIENCE,\n jwksUri,\n }),\n },\n },\n (server) =>\n server\n .registerTool(\n {\n name: \"public-whoami\",\n description: \"Public.\",\n inputSchema: {},\n auth: { allowsAnonymous: true },\n },\n (_args, extra) => ({\n content: [\n { type: \"text\", text: extra.http?.authInfo?.clientId ?? \"anon\" },\n ],\n }),\n )\n .registerTool(\n {\n name: \"private-whoami\",\n description: \"Private.\",\n inputSchema: {},\n auth: {},\n },\n (_args, extra) => ({\n content: [\n { type: \"text\", text: extra.http?.authInfo?.clientId ?? \"anon\" },\n ],\n }),\n )\n .registerTool(\n {\n name: \"undeclared-whoami\",\n description: \"Registered without auth or securitySchemes.\",\n inputSchema: {},\n },\n (_args, extra) => ({\n content: [\n { type: \"text\", text: extra.http?.authInfo?.clientId ?? \"anon\" },\n ],\n }),\n ),\n );\n\n const httpServer = http.createServer();\n await createApp({ app, httpServer });\n const listening = http.createServer(app.express);\n await new Promise<void>((resolve) => listening.listen(0, resolve));\n appServer = listening;\n const port = (listening.address() as { port: number }).port;\n return `http://localhost:${port}`;\n}\n\ndescribe(\"mixed-auth door\", () => {\n it(\"lets an anonymous caller initialize and run a noauth tool\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootMixedServer(jwksUri);\n\n const client = new Client({ name: \"test-client\", version: \"0.0.0\" });\n await client.connect(\n new StreamableHTTPClientTransport(new URL(`${base}/mcp`)),\n );\n\n const result = (await client.callTool({\n name: \"public-whoami\",\n arguments: {},\n })) as unknown as { content: { text: string }[] };\n expect(result.content[0]?.text).toBe(\"anon\");\n\n await client.close();\n });\n\n it(\"exposes securitySchemes at the top level of tools/list (not only _meta)\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootMixedServer(jwksUri);\n const headers = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n };\n await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"initialize\",\n params: {\n protocolVersion: \"2025-06-18\",\n capabilities: {},\n clientInfo: { name: \"c\", version: \"0\" },\n },\n }),\n });\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ jsonrpc: \"2.0\", id: 2, method: \"tools/list\" }),\n });\n const text = await res.text();\n const json = JSON.parse((text.match(/\\{[\\s\\S]*\\}/) ?? [\"{}\"])[0]) as {\n result: { tools: Array<{ name: string; securitySchemes?: unknown }> };\n };\n const whoami = json.result.tools.find((t) => t.name === \"private-whoami\");\n expect(whoami?.securitySchemes).toEqual([{ type: \"oauth2\" }]);\n });\n\n it(\"denies a protected tool inside an anonymous JSON-RPC batch\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootMixedServer(jwksUri);\n\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n },\n body: JSON.stringify([\n {\n jsonrpc: \"2.0\",\n id: 1,\n method: \"tools/call\",\n params: { name: \"private-whoami\", arguments: {} },\n },\n ]),\n });\n expect(res.status).toBe(401);\n const wwwAuthenticate = res.headers.get(\"www-authenticate\") ?? \"\";\n expect(wwwAuthenticate).toMatch(/^Bearer /);\n expect(wwwAuthenticate).toContain(\"resource_metadata=\");\n const text = await res.text();\n expect(text).not.toContain(\"client-1\");\n });\n\n it(\"gates a tool with no declared schemes (secure default)\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootMixedServer(jwksUri);\n\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"tools/call\",\n params: { name: \"undeclared-whoami\", arguments: {} },\n }),\n });\n expect(res.status).toBe(401);\n });\n\n it(\"returns 401 + WWW-Authenticate for a protected tool while anonymous\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootMixedServer(jwksUri);\n\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"tools/call\",\n params: { name: \"private-whoami\", arguments: {} },\n }),\n });\n expect(res.status).toBe(401);\n expect(res.headers.get(\"www-authenticate\")).toMatch(\n /error=\"invalid_token\"/,\n );\n expect(res.headers.get(\"www-authenticate\")).toMatch(/resource_metadata=/);\n });\n\n it(\"returns an in-band mcp/www_authenticate array to ChatGPT (not a transport 401)\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootMixedServer(jwksUri);\n\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n \"User-Agent\": \"openai-mcp/1.0\",\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 7,\n method: \"tools/call\",\n params: { name: \"private-whoami\", arguments: {} },\n }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"www-authenticate\")).toBeNull();\n const body = (await res.json()) as {\n id: number;\n result: {\n isError: boolean;\n _meta: { \"mcp/www_authenticate\": string[] };\n };\n };\n expect(body.id).toBe(7);\n expect(body.result.isError).toBe(true);\n const challenge = body.result._meta[\"mcp/www_authenticate\"];\n expect(Array.isArray(challenge)).toBe(true);\n expect(challenge[0]).toMatch(/error=\"invalid_token\"/);\n expect(challenge[0]).toMatch(/resource_metadata=/);\n });\n\n it(\"fails closed on a ChatGPT batch (transport 401, no in-band challenge)\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootMixedServer(jwksUri);\n\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n \"User-Agent\": \"openai-mcp/1.0\",\n },\n body: JSON.stringify([\n {\n jsonrpc: \"2.0\",\n id: 1,\n method: \"tools/call\",\n params: { name: \"private-whoami\", arguments: {} },\n },\n ]),\n });\n expect(res.status).toBe(401);\n expect(res.headers.get(\"www-authenticate\")).toMatch(/^Bearer /);\n const text = await res.text();\n expect(text).not.toContain(\"client-1\");\n });\n});\n\nasync function bootScopedServer(jwksUri: string) {\n const { createApp } = await import(\"../express.js\");\n const app = new Skybridge(\n {\n name: \"scoped-auth-test\",\n version: \"0.0.0\",\n capabilities: {},\n oauth: {\n baseUrl: \"https://app.example.test\",\n oauthMetadata: {\n issuer: ISSUER,\n authorization_endpoint: `${ISSUER}/authorize`,\n token_endpoint: `${ISSUER}/token`,\n response_types_supported: [\"code\"],\n },\n verifier: createJwksVerifier({\n issuer: ISSUER,\n audience: AUDIENCE,\n jwksUri,\n }),\n },\n },\n (server) =>\n server.registerTool(\n {\n name: \"checkout\",\n description: \"Needs the checkout scope.\",\n inputSchema: {},\n auth: { scopes: [\"checkout\"] },\n },\n () => ({ content: [{ type: \"text\", text: \"ok\" }] }),\n ),\n );\n\n const httpServer = http.createServer();\n await createApp({ app, httpServer });\n const listening = http.createServer(app.express);\n await new Promise<void>((resolve) => listening.listen(0, resolve));\n appServer = listening;\n const port = (listening.address() as { port: number }).port;\n return `http://localhost:${port}`;\n}\n\ndescribe(\"per-tool scope enforcement in fully-authenticated mode\", () => {\n it(\"returns 403 for a valid token missing the tool's scope\", async () => {\n const { privateKey, jwksUri } = await startJwks();\n const base = await bootScopedServer(jwksUri);\n const token = await signToken(privateKey, \"openid\");\n\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"tools/call\",\n params: { name: \"checkout\", arguments: {} },\n }),\n });\n expect(res.status).toBe(403);\n const header = res.headers.get(\"www-authenticate\");\n expect(header).toMatch(/error=\"insufficient_scope\"/);\n expect(header).toMatch(/scope=\"checkout\"/);\n });\n\n it(\"allows a token carrying the tool's scope\", async () => {\n const { privateKey, jwksUri } = await startJwks();\n const base = await bootScopedServer(jwksUri);\n const token = await signToken(privateKey, \"openid checkout\");\n\n const client = new Client({ name: \"test-client\", version: \"0.0.0\" });\n await client.connect(\n new StreamableHTTPClientTransport(new URL(`${base}/mcp`), {\n requestInit: { headers: { Authorization: `Bearer ${token}` } },\n }),\n );\n\n const result = (await client.callTool({\n name: \"checkout\",\n arguments: {},\n })) as unknown as { isError?: boolean; content: { text: string }[] };\n expect(result.content[0]?.text).toBe(\"ok\");\n\n await client.close();\n });\n});\n\ndescribe(\"auth shorthand validation\", () => {\n it(\"throws when `auth` requires sign-in but no oauth provider is configured\", () => {\n expect(() =>\n new McpServer({ name: \"t\", version: \"0\" }).registerTool(\n { name: \"x\", inputSchema: {}, auth: {} },\n () => ({ content: [{ type: \"text\", text: \"\" }] }),\n ),\n ).toThrow(/no `oauth` provider/);\n });\n\n it(\"throws when `auth` sets scopes but no oauth provider is configured\", () => {\n expect(() =>\n new McpServer({ name: \"t\", version: \"0\" }).registerTool(\n { name: \"x\", inputSchema: {}, auth: { scopes: [\"checkout\"] } },\n () => ({ content: [{ type: \"text\", text: \"\" }] }),\n ),\n ).toThrow(/no `oauth` provider/);\n });\n\n it(\"allows `auth: { allowsAnonymous: true }` without an oauth provider\", () => {\n expect(() =>\n new McpServer({ name: \"t\", version: \"0\" }).registerTool(\n { name: \"x\", inputSchema: {}, auth: { allowsAnonymous: true } },\n () => ({ content: [{ type: \"text\", text: \"\" }] }),\n ),\n ).not.toThrow();\n });\n\n it(\"prefers `securitySchemes` over `auth` when both are set (untyped path)\", () => {\n expect(() =>\n (\n new McpServer({ name: \"t\", version: \"0\" }).registerTool as (\n ...a: unknown[]\n ) => unknown\n )(\n {\n name: \"x\",\n inputSchema: {},\n auth: {},\n securitySchemes: [{ type: \"oauth2\" }],\n },\n () => ({ content: [{ type: \"text\", text: \"\" }] }),\n ),\n ).not.toThrow();\n });\n});\n\ndescribe(\"oauth config validation\", () => {\n const validMetadata = {\n issuer: ISSUER,\n authorization_endpoint: `${ISSUER}/authorize`,\n token_endpoint: `${ISSUER}/token`,\n response_types_supported: [\"code\"],\n };\n\n it(\"throws on a non-absolute baseUrl\", () => {\n expect(\n () =>\n new Skybridge(\n {\n name: \"t\",\n version: \"0\",\n oauth: {\n baseUrl: \"not-a-url\",\n oauthMetadata: validMetadata,\n verifier: createJwksVerifier({\n issuer: ISSUER,\n audience: AUDIENCE,\n }),\n },\n },\n (server) => server,\n ),\n ).toThrow(/baseUrl must be a valid absolute URL/);\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"setup.test.js","sourceRoot":"","sources":["../../../src/server/auth/setup.test.ts"],"names":[],"mappings":"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","sourcesContent":["// @vitest-environment node\nimport http from \"node:http\";\nimport {\n Client,\n StreamableHTTPClientTransport,\n} from \"@modelcontextprotocol/client\";\nimport type { RequestHandler } from \"express\";\nimport * as jose from \"jose\";\nimport { afterEach, describe, expect, it, vi } from \"vitest\";\nimport { Skybridge } from \"../app.js\";\nimport { McpServer } from \"../server.js\";\nimport { createJwksVerifier } from \"./verify.js\";\n\nvi.mock(\"@skybridge/devtools\", () => ({\n devtoolsStaticServer: () =>\n ((_req: unknown, _res: unknown, next: () => void) =>\n next()) as RequestHandler,\n}));\nvi.mock(\"../viewsDevServer.js\", () => ({\n viewsDevServer: (_httpServer: unknown) =>\n ((_req: unknown, _res: unknown, next: () => void) =>\n next()) as RequestHandler,\n}));\n\nconst ISSUER = \"https://issuer.test\";\nconst AUDIENCE = \"api://default\";\n\nlet jwksServer: http.Server | undefined;\nlet appServer: http.Server | undefined;\nafterEach(() => {\n jwksServer?.close();\n appServer?.close();\n});\n\nasync function startJwks() {\n const { publicKey, privateKey } = await jose.generateKeyPair(\"RS256\");\n const jwk = {\n ...(await jose.exportJWK(publicKey)),\n kid: \"test-key\",\n alg: \"RS256\",\n use: \"sig\",\n };\n const server = http.createServer((_req, res) => {\n res.setHeader(\"content-type\", \"application/json\");\n res.end(JSON.stringify({ keys: [jwk] }));\n });\n await new Promise<void>((resolve) => server.listen(0, resolve));\n jwksServer = server;\n const port = (server.address() as { port: number }).port;\n return { privateKey, jwksUri: `http://localhost:${port}/jwks` };\n}\n\nfunction signToken(key: CryptoKey, scope = \"openid email\") {\n return new jose.SignJWT({\n client_id: \"client-1\",\n scope,\n sub: \"user-1\",\n })\n .setProtectedHeader({ alg: \"RS256\", kid: \"test-key\" })\n .setIssuer(ISSUER)\n .setAudience(AUDIENCE)\n .setExpirationTime(\"1h\")\n .sign(key);\n}\n\nasync function bootServer(\n jwksUri: string,\n { baseUrl = \"https://app.example.test\" }: { baseUrl?: string | null } = {},\n) {\n const { createApp } = await import(\"../express.js\");\n const app = new Skybridge({\n name: \"auth-test\",\n version: \"0.0.0\",\n oauth: {\n ...(baseUrl === null ? {} : { baseUrl }),\n oauthMetadata: {\n issuer: ISSUER,\n authorization_endpoint: `${ISSUER}/authorize`,\n token_endpoint: `${ISSUER}/token`,\n response_types_supported: [\"code\"],\n },\n verifier: createJwksVerifier({\n issuer: ISSUER,\n audience: AUDIENCE,\n jwksUri,\n }),\n scopesSupported: [\"openid\", \"email\"],\n requiredScopes: [\"openid\"],\n },\n handler: (server) =>\n server.registerTool(\n {\n name: \"whoami\",\n description: \"Returns the caller identity.\",\n inputSchema: {},\n },\n (_args, extra) => ({\n structuredContent: {\n clientId: extra.http?.authInfo?.clientId ?? null,\n },\n content: [\n { type: \"text\", text: extra.http?.authInfo?.clientId ?? \"anon\" },\n ],\n }),\n ),\n });\n\n const httpServer = http.createServer();\n await createApp({ app, httpServer });\n const listening = http.createServer(app.express);\n await new Promise<void>((resolve) => listening.listen(0, resolve));\n appServer = listening;\n const port = (listening.address() as { port: number }).port;\n return `http://localhost:${port}`;\n}\n\ndescribe(\"setupOAuth wiring\", () => {\n it(\"serves protected-resource metadata\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootServer(jwksUri);\n\n const res = await fetch(`${base}/.well-known/oauth-protected-resource`);\n expect(res.status).toBe(200);\n const body = (await res.json()) as {\n resource: string;\n authorization_servers: string[];\n scopes_supported: string[];\n };\n expect(body.resource).toBe(\"https://app.example.test/\");\n expect(body.authorization_servers).toContain(ISSUER);\n expect(body.scopes_supported).toEqual([\"openid\", \"email\"]);\n });\n\n it(\"rejects /mcp without a token (401 + WWW-Authenticate)\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootServer(jwksUri);\n\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ jsonrpc: \"2.0\", method: \"initialize\", id: 1 }),\n });\n expect(res.status).toBe(401);\n expect(res.headers.get(\"www-authenticate\")).toMatch(/resource_metadata=/);\n });\n\n it(\"threads authInfo into the tool handler for a valid token\", async () => {\n const { privateKey, jwksUri } = await startJwks();\n const base = await bootServer(jwksUri);\n const token = await signToken(privateKey);\n\n const client = new Client({ name: \"test-client\", version: \"0.0.0\" });\n const transport = new StreamableHTTPClientTransport(\n new URL(`${base}/mcp`),\n { requestInit: { headers: { Authorization: `Bearer ${token}` } } },\n );\n await client.connect(transport);\n\n const result = (await client.callTool({\n name: \"whoami\",\n arguments: {},\n })) as unknown as {\n content: { type: string; text: string }[];\n };\n expect(result.content[0]?.text).toBe(\"client-1\");\n\n await client.close();\n });\n});\n\ndescribe(\"baseUrl inferred from headers\", () => {\n it(\"derives the resource origin from x-forwarded-host\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootServer(jwksUri, { baseUrl: null });\n\n const res = await fetch(`${base}/.well-known/oauth-protected-resource`, {\n headers: { \"x-forwarded-host\": \"infer.example.test\" },\n });\n expect(res.status).toBe(200);\n const body = (await res.json()) as { resource: string };\n expect(body.resource).toBe(\"https://infer.example.test/\");\n });\n\n it(\"uses the first hop of a forwarded-host chain\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootServer(jwksUri, { baseUrl: null });\n\n const res = await fetch(`${base}/.well-known/oauth-protected-resource`, {\n headers: {\n \"x-forwarded-host\": \"public.example, internal.local\",\n \"x-forwarded-proto\": \"https, http\",\n },\n });\n expect(res.status).toBe(200);\n const body = (await res.json()) as { resource: string };\n expect(body.resource).toBe(\"https://public.example/\");\n });\n\n it(\"ignores the client Origin header, using Host instead\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootServer(jwksUri, { baseUrl: null });\n\n const res = await fetch(`${base}/.well-known/oauth-protected-resource`, {\n headers: { origin: \"https://chatgpt.com\" },\n });\n expect(res.status).toBe(200);\n const body = (await res.json()) as { resource: string };\n expect(body.resource).toMatch(/^http:\\/\\/(localhost|127\\.0\\.0\\.1):/);\n });\n\n it(\"points the 401 WWW-Authenticate at the inferred host\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootServer(jwksUri, { baseUrl: null });\n\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-forwarded-host\": \"infer.example.test\",\n },\n body: JSON.stringify({ jsonrpc: \"2.0\", method: \"initialize\", id: 1 }),\n });\n expect(res.status).toBe(401);\n expect(res.headers.get(\"www-authenticate\")).toMatch(\n /resource_metadata=\"https:\\/\\/infer\\.example\\.test\\//,\n );\n });\n});\n\nasync function bootMixedServer(jwksUri: string) {\n const { createApp } = await import(\"../express.js\");\n const app = new Skybridge({\n name: \"mixed-auth-test\",\n version: \"0.0.0\",\n oauth: {\n baseUrl: \"https://app.example.test\",\n oauthMetadata: {\n issuer: ISSUER,\n authorization_endpoint: `${ISSUER}/authorize`,\n token_endpoint: `${ISSUER}/token`,\n response_types_supported: [\"code\"],\n },\n verifier: createJwksVerifier({\n issuer: ISSUER,\n audience: AUDIENCE,\n jwksUri,\n }),\n },\n handler: (server) =>\n server\n .registerTool(\n {\n name: \"public-whoami\",\n description: \"Public.\",\n inputSchema: {},\n auth: { allowsAnonymous: true },\n },\n (_args, extra) => ({\n content: [\n { type: \"text\", text: extra.http?.authInfo?.clientId ?? \"anon\" },\n ],\n }),\n )\n .registerTool(\n {\n name: \"private-whoami\",\n description: \"Private.\",\n inputSchema: {},\n auth: {},\n },\n (_args, extra) => ({\n content: [\n { type: \"text\", text: extra.http?.authInfo?.clientId ?? \"anon\" },\n ],\n }),\n )\n .registerTool(\n {\n name: \"undeclared-whoami\",\n description: \"Registered without auth or securitySchemes.\",\n inputSchema: {},\n },\n (_args, extra) => ({\n content: [\n { type: \"text\", text: extra.http?.authInfo?.clientId ?? \"anon\" },\n ],\n }),\n ),\n });\n\n const httpServer = http.createServer();\n await createApp({ app, httpServer });\n const listening = http.createServer(app.express);\n await new Promise<void>((resolve) => listening.listen(0, resolve));\n appServer = listening;\n const port = (listening.address() as { port: number }).port;\n return `http://localhost:${port}`;\n}\n\ndescribe(\"mixed-auth door\", () => {\n it(\"lets an anonymous caller initialize and run a noauth tool\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootMixedServer(jwksUri);\n\n const client = new Client({ name: \"test-client\", version: \"0.0.0\" });\n await client.connect(\n new StreamableHTTPClientTransport(new URL(`${base}/mcp`)),\n );\n\n const result = (await client.callTool({\n name: \"public-whoami\",\n arguments: {},\n })) as unknown as { content: { text: string }[] };\n expect(result.content[0]?.text).toBe(\"anon\");\n\n await client.close();\n });\n\n it(\"exposes securitySchemes at the top level of tools/list (not only _meta)\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootMixedServer(jwksUri);\n const headers = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n };\n await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"initialize\",\n params: {\n protocolVersion: \"2025-06-18\",\n capabilities: {},\n clientInfo: { name: \"c\", version: \"0\" },\n },\n }),\n });\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ jsonrpc: \"2.0\", id: 2, method: \"tools/list\" }),\n });\n const text = await res.text();\n const json = JSON.parse((text.match(/\\{[\\s\\S]*\\}/) ?? [\"{}\"])[0]) as {\n result: { tools: Array<{ name: string; securitySchemes?: unknown }> };\n };\n const whoami = json.result.tools.find((t) => t.name === \"private-whoami\");\n expect(whoami?.securitySchemes).toEqual([{ type: \"oauth2\" }]);\n });\n\n it(\"denies a protected tool inside an anonymous JSON-RPC batch\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootMixedServer(jwksUri);\n\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n },\n body: JSON.stringify([\n {\n jsonrpc: \"2.0\",\n id: 1,\n method: \"tools/call\",\n params: { name: \"private-whoami\", arguments: {} },\n },\n ]),\n });\n expect(res.status).toBe(401);\n const wwwAuthenticate = res.headers.get(\"www-authenticate\") ?? \"\";\n expect(wwwAuthenticate).toMatch(/^Bearer /);\n expect(wwwAuthenticate).toContain(\"resource_metadata=\");\n const text = await res.text();\n expect(text).not.toContain(\"client-1\");\n });\n\n it(\"gates a tool with no declared schemes (secure default)\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootMixedServer(jwksUri);\n\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"tools/call\",\n params: { name: \"undeclared-whoami\", arguments: {} },\n }),\n });\n expect(res.status).toBe(401);\n });\n\n it(\"returns 401 + WWW-Authenticate for a protected tool while anonymous\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootMixedServer(jwksUri);\n\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"tools/call\",\n params: { name: \"private-whoami\", arguments: {} },\n }),\n });\n expect(res.status).toBe(401);\n expect(res.headers.get(\"www-authenticate\")).toMatch(\n /error=\"invalid_token\"/,\n );\n expect(res.headers.get(\"www-authenticate\")).toMatch(/resource_metadata=/);\n });\n\n it(\"returns an in-band mcp/www_authenticate array to ChatGPT (not a transport 401)\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootMixedServer(jwksUri);\n\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n \"User-Agent\": \"openai-mcp/1.0\",\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 7,\n method: \"tools/call\",\n params: { name: \"private-whoami\", arguments: {} },\n }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"www-authenticate\")).toBeNull();\n const body = (await res.json()) as {\n id: number;\n result: {\n isError: boolean;\n _meta: { \"mcp/www_authenticate\": string[] };\n };\n };\n expect(body.id).toBe(7);\n expect(body.result.isError).toBe(true);\n const challenge = body.result._meta[\"mcp/www_authenticate\"];\n expect(Array.isArray(challenge)).toBe(true);\n expect(challenge[0]).toMatch(/error=\"invalid_token\"/);\n expect(challenge[0]).toMatch(/resource_metadata=/);\n });\n\n it(\"fails closed on a ChatGPT batch (transport 401, no in-band challenge)\", async () => {\n const { jwksUri } = await startJwks();\n const base = await bootMixedServer(jwksUri);\n\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n \"User-Agent\": \"openai-mcp/1.0\",\n },\n body: JSON.stringify([\n {\n jsonrpc: \"2.0\",\n id: 1,\n method: \"tools/call\",\n params: { name: \"private-whoami\", arguments: {} },\n },\n ]),\n });\n expect(res.status).toBe(401);\n expect(res.headers.get(\"www-authenticate\")).toMatch(/^Bearer /);\n const text = await res.text();\n expect(text).not.toContain(\"client-1\");\n });\n});\n\nasync function bootScopedServer(jwksUri: string) {\n const { createApp } = await import(\"../express.js\");\n const app = new Skybridge({\n name: \"scoped-auth-test\",\n version: \"0.0.0\",\n oauth: {\n baseUrl: \"https://app.example.test\",\n oauthMetadata: {\n issuer: ISSUER,\n authorization_endpoint: `${ISSUER}/authorize`,\n token_endpoint: `${ISSUER}/token`,\n response_types_supported: [\"code\"],\n },\n verifier: createJwksVerifier({\n issuer: ISSUER,\n audience: AUDIENCE,\n jwksUri,\n }),\n },\n handler: (server) =>\n server.registerTool(\n {\n name: \"checkout\",\n description: \"Needs the checkout scope.\",\n inputSchema: {},\n auth: { scopes: [\"checkout\"] },\n },\n () => ({ content: [{ type: \"text\", text: \"ok\" }] }),\n ),\n });\n\n const httpServer = http.createServer();\n await createApp({ app, httpServer });\n const listening = http.createServer(app.express);\n await new Promise<void>((resolve) => listening.listen(0, resolve));\n appServer = listening;\n const port = (listening.address() as { port: number }).port;\n return `http://localhost:${port}`;\n}\n\ndescribe(\"per-tool scope enforcement in fully-authenticated mode\", () => {\n it(\"returns 403 for a valid token missing the tool's scope\", async () => {\n const { privateKey, jwksUri } = await startJwks();\n const base = await bootScopedServer(jwksUri);\n const token = await signToken(privateKey, \"openid\");\n\n const res = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"tools/call\",\n params: { name: \"checkout\", arguments: {} },\n }),\n });\n expect(res.status).toBe(403);\n const header = res.headers.get(\"www-authenticate\");\n expect(header).toMatch(/error=\"insufficient_scope\"/);\n expect(header).toMatch(/scope=\"checkout\"/);\n });\n\n it(\"allows a token carrying the tool's scope\", async () => {\n const { privateKey, jwksUri } = await startJwks();\n const base = await bootScopedServer(jwksUri);\n const token = await signToken(privateKey, \"openid checkout\");\n\n const client = new Client({ name: \"test-client\", version: \"0.0.0\" });\n await client.connect(\n new StreamableHTTPClientTransport(new URL(`${base}/mcp`), {\n requestInit: { headers: { Authorization: `Bearer ${token}` } },\n }),\n );\n\n const result = (await client.callTool({\n name: \"checkout\",\n arguments: {},\n })) as unknown as { isError?: boolean; content: { text: string }[] };\n expect(result.content[0]?.text).toBe(\"ok\");\n\n await client.close();\n });\n});\n\ndescribe(\"auth shorthand validation\", () => {\n it(\"throws when `auth` requires sign-in but no oauth provider is configured\", () => {\n expect(() =>\n new McpServer({ name: \"t\", version: \"0\" }).registerTool(\n { name: \"x\", inputSchema: {}, auth: {} },\n () => ({ content: [{ type: \"text\", text: \"\" }] }),\n ),\n ).toThrow(/no `oauth` provider/);\n });\n\n it(\"throws when `auth` sets scopes but no oauth provider is configured\", () => {\n expect(() =>\n new McpServer({ name: \"t\", version: \"0\" }).registerTool(\n { name: \"x\", inputSchema: {}, auth: { scopes: [\"checkout\"] } },\n () => ({ content: [{ type: \"text\", text: \"\" }] }),\n ),\n ).toThrow(/no `oauth` provider/);\n });\n\n it(\"allows `auth: { allowsAnonymous: true }` without an oauth provider\", () => {\n expect(() =>\n new McpServer({ name: \"t\", version: \"0\" }).registerTool(\n { name: \"x\", inputSchema: {}, auth: { allowsAnonymous: true } },\n () => ({ content: [{ type: \"text\", text: \"\" }] }),\n ),\n ).not.toThrow();\n });\n\n it(\"prefers `securitySchemes` over `auth` when both are set (untyped path)\", () => {\n expect(() =>\n (\n new McpServer({ name: \"t\", version: \"0\" }).registerTool as (\n ...a: unknown[]\n ) => unknown\n )(\n {\n name: \"x\",\n inputSchema: {},\n auth: {},\n securitySchemes: [{ type: \"oauth2\" }],\n },\n () => ({ content: [{ type: \"text\", text: \"\" }] }),\n ),\n ).not.toThrow();\n });\n});\n\ndescribe(\"oauth config validation\", () => {\n const validMetadata = {\n issuer: ISSUER,\n authorization_endpoint: `${ISSUER}/authorize`,\n token_endpoint: `${ISSUER}/token`,\n response_types_supported: [\"code\"],\n };\n\n it(\"rejects a non-absolute baseUrl when the app is first used\", async () => {\n const app = new Skybridge({\n name: \"t\",\n version: \"0\",\n oauth: {\n baseUrl: \"not-a-url\",\n oauthMetadata: validMetadata,\n verifier: createJwksVerifier({\n issuer: ISSUER,\n audience: AUDIENCE,\n }),\n },\n handler: (server) => server,\n });\n await expect(app.createServerInstance()).rejects.toThrow(\n /baseUrl must be a valid absolute URL/,\n );\n });\n});\n"]}
|
|
@@ -9,31 +9,45 @@ const customOAuth = await workosProvider({
|
|
|
9
9
|
audience: "a",
|
|
10
10
|
});
|
|
11
11
|
test("a server with no oauth keeps the untyped claim bag", () => {
|
|
12
|
-
new Skybridge({
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
new Skybridge({
|
|
13
|
+
name: "t",
|
|
14
|
+
version: "0",
|
|
15
|
+
handler: (server) => server.registerTool({ name: "plain", inputSchema: { q: z.string() } }, (_args, extra) => {
|
|
16
|
+
expectTypeOf(extra.http?.authInfo?.extra).toEqualTypeOf();
|
|
17
|
+
return { content: "ok" };
|
|
18
|
+
}),
|
|
19
|
+
});
|
|
16
20
|
});
|
|
17
21
|
test("provider claims reach tool handlers", () => {
|
|
18
|
-
new Skybridge({
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
new Skybridge({
|
|
23
|
+
name: "t",
|
|
24
|
+
version: "0",
|
|
25
|
+
oauth: workosOAuth,
|
|
26
|
+
handler: (server) => server
|
|
27
|
+
.registerTool({ name: "a", inputSchema: {} }, (_args, extra) => {
|
|
28
|
+
expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf();
|
|
29
|
+
expectTypeOf(extra.http?.authInfo?.extra?.permissions).toEqualTypeOf();
|
|
30
|
+
// @ts-expect-error not a WorkOS claim
|
|
31
|
+
extra.http?.authInfo?.extra?.nope;
|
|
32
|
+
return { content: "a" };
|
|
33
|
+
})
|
|
34
|
+
.registerTool({ name: "b", inputSchema: {} }, (_args, extra) => {
|
|
35
|
+
expectTypeOf(extra.http?.authInfo?.extra?.sid).toEqualTypeOf();
|
|
36
|
+
return { content: "b" };
|
|
37
|
+
}),
|
|
38
|
+
});
|
|
30
39
|
});
|
|
31
40
|
test("registered claims survive the mapping into extra", () => {
|
|
32
|
-
new Skybridge({
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
new Skybridge({
|
|
42
|
+
name: "t",
|
|
43
|
+
version: "0",
|
|
44
|
+
oauth: workosOAuth,
|
|
45
|
+
handler: (server) => server.registerTool({ name: "a", inputSchema: {} }, (_args, extra) => {
|
|
46
|
+
expectTypeOf(extra.http?.authInfo?.extra?.iss).toEqualTypeOf();
|
|
47
|
+
expectTypeOf(extra.http?.authInfo?.extra?.iat).toEqualTypeOf();
|
|
48
|
+
return { content: "a" };
|
|
49
|
+
}),
|
|
50
|
+
});
|
|
37
51
|
});
|
|
38
52
|
test("a hand-written verifier carries its own claims", async () => {
|
|
39
53
|
const verifier = {
|
|
@@ -44,10 +58,15 @@ test("a hand-written verifier carries its own claims", async () => {
|
|
|
44
58
|
const { oauthMetadata } = await customProvider({
|
|
45
59
|
issuer: "https://idp.example.com",
|
|
46
60
|
});
|
|
47
|
-
new Skybridge({
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
61
|
+
new Skybridge({
|
|
62
|
+
name: "t",
|
|
63
|
+
version: "0",
|
|
64
|
+
oauth: { oauthMetadata, verifier },
|
|
65
|
+
handler: (server) => server.registerTool({ name: "a", inputSchema: {} }, (_args, extra) => {
|
|
66
|
+
expectTypeOf(extra.http?.authInfo?.extra?.email).toEqualTypeOf();
|
|
67
|
+
return { content: "a" };
|
|
68
|
+
}),
|
|
69
|
+
});
|
|
51
70
|
});
|
|
52
71
|
test("a config must carry a verifier", () => {
|
|
53
72
|
// @ts-expect-error a verifier is required
|
|
@@ -57,15 +76,52 @@ test("a config must carry a verifier", () => {
|
|
|
57
76
|
void missing;
|
|
58
77
|
});
|
|
59
78
|
test("a provider override adds claims without dropping the provider's", () => {
|
|
60
|
-
new Skybridge({
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
79
|
+
new Skybridge({
|
|
80
|
+
name: "t",
|
|
81
|
+
version: "0",
|
|
82
|
+
oauth: customOAuth,
|
|
83
|
+
handler: (server) => server
|
|
84
|
+
.registerTool({ name: "a", inputSchema: {} }, (_args, extra) => {
|
|
85
|
+
expectTypeOf(extra.http?.authInfo?.extra?.tenant).toEqualTypeOf();
|
|
86
|
+
expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf();
|
|
87
|
+
return { content: "a" };
|
|
88
|
+
})
|
|
89
|
+
.mcpMiddleware("tools/call", (_request, extra, next) => {
|
|
90
|
+
expectTypeOf(extra.http?.authInfo?.extra?.tenant).toEqualTypeOf();
|
|
91
|
+
return next();
|
|
92
|
+
}),
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
test("bag oauth claims reach tool handlers, promise form included", () => {
|
|
96
|
+
new Skybridge({
|
|
97
|
+
name: "t",
|
|
98
|
+
version: "0",
|
|
99
|
+
oauth: workosProvider({ domain: "d", audience: "a" }),
|
|
100
|
+
handler: (server) => server.registerTool({ name: "a", inputSchema: {} }, (_args, extra) => {
|
|
101
|
+
expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf();
|
|
102
|
+
// @ts-expect-error not a WorkOS claim
|
|
103
|
+
extra.http?.authInfo?.extra?.nope;
|
|
104
|
+
return { content: "a" };
|
|
105
|
+
}),
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
test("the setup config flows into oauth and handler, and the app carries the registry", () => {
|
|
109
|
+
const app = new Skybridge({
|
|
110
|
+
name: "t",
|
|
111
|
+
version: "0",
|
|
112
|
+
setup: async () => ({ apiKey: "k" }),
|
|
113
|
+
oauth: (config) => {
|
|
114
|
+
expectTypeOf(config).toEqualTypeOf();
|
|
115
|
+
return workosOAuth;
|
|
116
|
+
},
|
|
117
|
+
handler: (server, config) => {
|
|
118
|
+
expectTypeOf(config).toEqualTypeOf();
|
|
119
|
+
return server.registerTool({ name: "a", inputSchema: {} }, (_args, extra) => {
|
|
120
|
+
expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf();
|
|
121
|
+
return { content: "a" };
|
|
122
|
+
});
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
expectTypeOf().toEqualTypeOf();
|
|
70
126
|
});
|
|
71
127
|
//# sourceMappingURL=auth-extra.test-d.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-extra.test-d.js","sourceRoot":"","sources":["../../src/server/auth-extra.test-d.ts"],"names":[],"mappings":"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","sourcesContent":["import { expectTypeOf, test } from \"vitest\";\nimport { z } from \"zod\";\nimport { Skybridge } from \"./app.js\";\nimport type { OAuthConfig } from \"./auth/index.js\";\nimport { customProvider } from \"./auth/providers/custom.js\";\nimport { workosProvider } from \"./auth/providers/workos.js\";\nimport type { TokenVerifier } from \"./auth.js\";\n\nconst workosOAuth = await workosProvider({ domain: \"d\", audience: \"a\" });\nconst customOAuth = await workosProvider<{ tenant: string }>({\n domain: \"d\",\n audience: \"a\",\n});\n\ntest(\"a server with no oauth keeps the untyped claim bag\", () => {\n new Skybridge({ name: \"t\", version: \"0\" }, (server) =>\n server.registerTool(\n { name: \"plain\", inputSchema: { q: z.string() } },\n (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra).toEqualTypeOf<\n Record<string, unknown> | undefined\n >();\n return { content: \"ok\" };\n },\n ),\n );\n});\n\ntest(\"provider claims reach tool handlers\", () => {\n new Skybridge({ name: \"t\", version: \"0\", oauth: workosOAuth }, (server) =>\n server\n .registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf<\n string | undefined\n >();\n expectTypeOf(extra.http?.authInfo?.extra?.permissions).toEqualTypeOf<\n string[] | undefined\n >();\n // @ts-expect-error not a WorkOS claim\n extra.http?.authInfo?.extra?.nope;\n return { content: \"a\" };\n })\n .registerTool({ name: \"b\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.sid).toEqualTypeOf<\n string | undefined\n >();\n return { content: \"b\" };\n }),\n );\n});\n\ntest(\"registered claims survive the mapping into extra\", () => {\n new Skybridge({ name: \"t\", version: \"0\", oauth: workosOAuth }, (server) =>\n server.registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.iss).toEqualTypeOf<\n string | undefined\n >();\n expectTypeOf(extra.http?.authInfo?.extra?.iat).toEqualTypeOf<\n number | undefined\n >();\n return { content: \"a\" };\n }),\n );\n});\n\ntest(\"a hand-written verifier carries its own claims\", async () => {\n type Claims = { subject?: string; email?: string };\n const verifier: TokenVerifier<Claims> = {\n async verifyAccessToken(token) {\n return { token, clientId: \"c\", scopes: [], expiresAt: 1, extra: {} };\n },\n };\n const { oauthMetadata } = await customProvider({\n issuer: \"https://idp.example.com\",\n });\n new Skybridge(\n { name: \"t\", version: \"0\", oauth: { oauthMetadata, verifier } },\n (server) =>\n server.registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.email).toEqualTypeOf<\n string | undefined\n >();\n return { content: \"a\" };\n }),\n );\n});\n\ntest(\"a config must carry a verifier\", () => {\n // @ts-expect-error a verifier is required\n const missing: OAuthConfig = {\n oauthMetadata: workosOAuth.oauthMetadata,\n };\n void missing;\n});\n\ntest(\"a provider override adds claims without dropping the provider's\", () => {\n new Skybridge({ name: \"t\", version: \"0\", oauth: customOAuth }, (server) =>\n server\n .registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.tenant).toEqualTypeOf<\n string | undefined\n >();\n expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf<\n string | undefined\n >();\n return { content: \"a\" };\n })\n .mcpMiddleware(\"tools/call\", (_request, extra, next) => {\n expectTypeOf(extra.http?.authInfo?.extra?.tenant).toEqualTypeOf<\n string | undefined\n >();\n return next();\n }),\n );\n});\n"]}
|
|
1
|
+
{"version":3,"file":"auth-extra.test-d.js","sourceRoot":"","sources":["../../src/server/auth-extra.test-d.ts"],"names":[],"mappings":"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","sourcesContent":["import { expectTypeOf, test } from \"vitest\";\nimport { z } from \"zod\";\nimport { Skybridge } from \"./app.js\";\nimport type { OAuthConfig } from \"./auth/index.js\";\nimport { customProvider } from \"./auth/providers/custom.js\";\nimport { workosProvider } from \"./auth/providers/workos.js\";\nimport type { TokenVerifier } from \"./auth.js\";\nimport type { ToolNames } from \"./inferUtilityTypes.js\";\n\nconst workosOAuth = await workosProvider({ domain: \"d\", audience: \"a\" });\nconst customOAuth = await workosProvider<{ tenant: string }>({\n domain: \"d\",\n audience: \"a\",\n});\n\ntest(\"a server with no oauth keeps the untyped claim bag\", () => {\n new Skybridge({\n name: \"t\",\n version: \"0\",\n handler: (server) =>\n server.registerTool(\n { name: \"plain\", inputSchema: { q: z.string() } },\n (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra).toEqualTypeOf<\n Record<string, unknown> | undefined\n >();\n return { content: \"ok\" };\n },\n ),\n });\n});\n\ntest(\"provider claims reach tool handlers\", () => {\n new Skybridge({\n name: \"t\",\n version: \"0\",\n oauth: workosOAuth,\n handler: (server) =>\n server\n .registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf<\n string | undefined\n >();\n expectTypeOf(extra.http?.authInfo?.extra?.permissions).toEqualTypeOf<\n string[] | undefined\n >();\n // @ts-expect-error not a WorkOS claim\n extra.http?.authInfo?.extra?.nope;\n return { content: \"a\" };\n })\n .registerTool({ name: \"b\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.sid).toEqualTypeOf<\n string | undefined\n >();\n return { content: \"b\" };\n }),\n });\n});\n\ntest(\"registered claims survive the mapping into extra\", () => {\n new Skybridge({\n name: \"t\",\n version: \"0\",\n oauth: workosOAuth,\n handler: (server) =>\n server.registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.iss).toEqualTypeOf<\n string | undefined\n >();\n expectTypeOf(extra.http?.authInfo?.extra?.iat).toEqualTypeOf<\n number | undefined\n >();\n return { content: \"a\" };\n }),\n });\n});\n\ntest(\"a hand-written verifier carries its own claims\", async () => {\n type Claims = { subject?: string; email?: string };\n const verifier: TokenVerifier<Claims> = {\n async verifyAccessToken(token) {\n return { token, clientId: \"c\", scopes: [], expiresAt: 1, extra: {} };\n },\n };\n const { oauthMetadata } = await customProvider({\n issuer: \"https://idp.example.com\",\n });\n new Skybridge({\n name: \"t\",\n version: \"0\",\n oauth: { oauthMetadata, verifier },\n handler: (server) =>\n server.registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.email).toEqualTypeOf<\n string | undefined\n >();\n return { content: \"a\" };\n }),\n });\n});\n\ntest(\"a config must carry a verifier\", () => {\n // @ts-expect-error a verifier is required\n const missing: OAuthConfig = {\n oauthMetadata: workosOAuth.oauthMetadata,\n };\n void missing;\n});\n\ntest(\"a provider override adds claims without dropping the provider's\", () => {\n new Skybridge({\n name: \"t\",\n version: \"0\",\n oauth: customOAuth,\n handler: (server) =>\n server\n .registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.tenant).toEqualTypeOf<\n string | undefined\n >();\n expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf<\n string | undefined\n >();\n return { content: \"a\" };\n })\n .mcpMiddleware(\"tools/call\", (_request, extra, next) => {\n expectTypeOf(extra.http?.authInfo?.extra?.tenant).toEqualTypeOf<\n string | undefined\n >();\n return next();\n }),\n });\n});\n\ntest(\"bag oauth claims reach tool handlers, promise form included\", () => {\n new Skybridge({\n name: \"t\",\n version: \"0\",\n oauth: workosProvider({ domain: \"d\", audience: \"a\" }),\n handler: (server) =>\n server.registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf<\n string | undefined\n >();\n // @ts-expect-error not a WorkOS claim\n extra.http?.authInfo?.extra?.nope;\n return { content: \"a\" };\n }),\n });\n});\n\ntest(\"the setup config flows into oauth and handler, and the app carries the registry\", () => {\n const app = new Skybridge({\n name: \"t\",\n version: \"0\",\n setup: async () => ({ apiKey: \"k\" }),\n oauth: (config) => {\n expectTypeOf(config).toEqualTypeOf<{ apiKey: string }>();\n return workosOAuth;\n },\n handler: (server, config) => {\n expectTypeOf(config).toEqualTypeOf<{ apiKey: string }>();\n return server.registerTool(\n { name: \"a\", inputSchema: {} },\n (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf<\n string | undefined\n >();\n return { content: \"a\" };\n },\n );\n },\n });\n expectTypeOf<ToolNames<typeof app>>().toEqualTypeOf<\"a\">();\n});\n"]}
|