akanjs 3.0.0-alpha.69 → 3.0.0-alpha.70
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.
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
package/server/mcp/McpAuth.ts
CHANGED
|
@@ -21,8 +21,9 @@ interface McpAuthFailure {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* The OAuth 2.1 protected-resource half of the MCP authorization spec: the RFC 9728 metadata document
|
|
25
|
-
* `WWW-Authenticate` challenge that points at it, and the
|
|
24
|
+
* The OAuth 2.1 protected-resource half of the MCP authorization spec: the RFC 9728 metadata document (served
|
|
25
|
+
* only once an authorization server is named), the `WWW-Authenticate` challenge that points at it, and the
|
|
26
|
+
* token checks that can be made without an issuer.
|
|
26
27
|
*
|
|
27
28
|
* The authorization server itself is a separate project. What lives here is what a resource server owes a
|
|
28
29
|
* client regardless of who mints the tokens, so wiring one up later needs no change on this side.
|
|
@@ -39,8 +40,12 @@ export class McpAuth {
|
|
|
39
40
|
/**
|
|
40
41
|
* Both spellings of the metadata path. RFC 9728 inserts the resource's path into the well-known URL, and MCP
|
|
41
42
|
* clients try that form first and the bare one second; serving only one leaves half the clients at a 404.
|
|
43
|
+
*
|
|
44
|
+
* Absent until an issuer is named: an unprotected resource that still advertises `bearer_methods_supported`
|
|
45
|
+
* is treated by Cursor (and similar clients) as an OAuth mandate.
|
|
42
46
|
*/
|
|
43
47
|
createRoutes(): HttpRoutes {
|
|
48
|
+
if (!this.#hasIssuer()) return {};
|
|
44
49
|
const handler = { GET: (req: Request) => this.#metadata(req) };
|
|
45
50
|
return {
|
|
46
51
|
[McpAuth.wellKnownPath]: handler,
|
|
@@ -84,7 +89,7 @@ export class McpAuth {
|
|
|
84
89
|
(value): value is string => typeof value === "string",
|
|
85
90
|
);
|
|
86
91
|
|
|
87
|
-
if (this.#
|
|
92
|
+
if (this.#hasIssuer() && !audience.length)
|
|
88
93
|
return { status: 401, error: "invalid_token", description: "The access token names no resource." };
|
|
89
94
|
if (audience.length && !audience.includes(this.#resource(req)))
|
|
90
95
|
return { status: 401, error: "invalid_token", description: "The access token was issued for another resource." };
|
|
@@ -128,7 +133,9 @@ export class McpAuth {
|
|
|
128
133
|
return [
|
|
129
134
|
"Bearer",
|
|
130
135
|
[
|
|
131
|
-
|
|
136
|
+
...(this.#hasIssuer()
|
|
137
|
+
? [`resource_metadata="${new URL(McpAuth.wellKnownPath + this.#props.path, McpAuth.origin(req)).href}"`]
|
|
138
|
+
: []),
|
|
132
139
|
`error="${error}"`,
|
|
133
140
|
`error_description="${description}"`,
|
|
134
141
|
...(scopes.length ? [`scope="${scopes.join(" ")}"`] : []),
|
|
@@ -136,6 +143,10 @@ export class McpAuth {
|
|
|
136
143
|
].join(" ");
|
|
137
144
|
}
|
|
138
145
|
|
|
146
|
+
#hasIssuer() {
|
|
147
|
+
return Boolean(this.#props.authorizationServers?.length);
|
|
148
|
+
}
|
|
149
|
+
|
|
139
150
|
#resource(req: Request) {
|
|
140
151
|
return this.#props.resource ?? new URL(this.#props.path, McpAuth.origin(req)).href;
|
|
141
152
|
}
|
|
@@ -17,8 +17,9 @@ interface McpAuthFailure {
|
|
|
17
17
|
description: string;
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
|
-
* The OAuth 2.1 protected-resource half of the MCP authorization spec: the RFC 9728 metadata document
|
|
21
|
-
* `WWW-Authenticate` challenge that points at it, and the
|
|
20
|
+
* The OAuth 2.1 protected-resource half of the MCP authorization spec: the RFC 9728 metadata document (served
|
|
21
|
+
* only once an authorization server is named), the `WWW-Authenticate` challenge that points at it, and the
|
|
22
|
+
* token checks that can be made without an issuer.
|
|
22
23
|
*
|
|
23
24
|
* The authorization server itself is a separate project. What lives here is what a resource server owes a
|
|
24
25
|
* client regardless of who mints the tokens, so wiring one up later needs no change on this side.
|
|
@@ -30,6 +31,9 @@ export declare class McpAuth {
|
|
|
30
31
|
/**
|
|
31
32
|
* Both spellings of the metadata path. RFC 9728 inserts the resource's path into the well-known URL, and MCP
|
|
32
33
|
* clients try that form first and the bare one second; serving only one leaves half the clients at a 404.
|
|
34
|
+
*
|
|
35
|
+
* Absent until an issuer is named: an unprotected resource that still advertises `bearer_methods_supported`
|
|
36
|
+
* is treated by Cursor (and similar clients) as an OAuth mandate.
|
|
33
37
|
*/
|
|
34
38
|
createRoutes(): HttpRoutes;
|
|
35
39
|
unauthorized(req: Request, failure?: McpAuthFailure): Response;
|