@modelcontextprotocol/sdk 1.5.0 → 1.6.1
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/cjs/client/auth.d.ts +116 -0
- package/dist/cjs/client/auth.d.ts.map +1 -0
- package/dist/cjs/client/auth.js +251 -0
- package/dist/cjs/client/auth.js.map +1 -0
- package/dist/cjs/client/sse.d.ts +43 -4
- package/dist/cjs/client/sse.d.ts.map +1 -1
- package/dist/cjs/client/sse.js +72 -5
- package/dist/cjs/client/sse.js.map +1 -1
- package/dist/cjs/server/auth/clients.d.ts +19 -0
- package/dist/cjs/server/auth/clients.d.ts.map +1 -0
- package/dist/cjs/server/auth/clients.js +3 -0
- package/dist/cjs/server/auth/clients.js.map +1 -0
- package/dist/cjs/server/auth/errors.d.ts +126 -0
- package/dist/cjs/server/auth/errors.d.ts.map +1 -0
- package/dist/cjs/server/auth/errors.js +189 -0
- package/dist/cjs/server/auth/errors.js.map +1 -0
- package/dist/cjs/server/auth/handlers/authorize.d.ts +13 -0
- package/dist/cjs/server/auth/handlers/authorize.d.ts.map +1 -0
- package/dist/cjs/server/auth/handlers/authorize.js +149 -0
- package/dist/cjs/server/auth/handlers/authorize.js.map +1 -0
- package/dist/cjs/server/auth/handlers/metadata.d.ts +4 -0
- package/dist/cjs/server/auth/handlers/metadata.d.ts.map +1 -0
- package/dist/cjs/server/auth/handlers/metadata.js +21 -0
- package/dist/cjs/server/auth/handlers/metadata.js.map +1 -0
- package/dist/cjs/server/auth/handlers/register.d.ts +23 -0
- package/dist/cjs/server/auth/handlers/register.d.ts.map +1 -0
- package/dist/cjs/server/auth/handlers/register.js +79 -0
- package/dist/cjs/server/auth/handlers/register.js.map +1 -0
- package/dist/cjs/server/auth/handlers/revoke.d.ts +13 -0
- package/dist/cjs/server/auth/handlers/revoke.d.ts.map +1 -0
- package/dist/cjs/server/auth/handlers/revoke.js +67 -0
- package/dist/cjs/server/auth/handlers/revoke.js.map +1 -0
- package/dist/cjs/server/auth/handlers/token.d.ts +13 -0
- package/dist/cjs/server/auth/handlers/token.d.ts.map +1 -0
- package/dist/cjs/server/auth/handlers/token.js +107 -0
- package/dist/cjs/server/auth/handlers/token.js.map +1 -0
- package/dist/cjs/server/auth/middleware/allowedMethods.d.ts +9 -0
- package/dist/cjs/server/auth/middleware/allowedMethods.d.ts.map +1 -0
- package/dist/cjs/server/auth/middleware/allowedMethods.js +23 -0
- package/dist/cjs/server/auth/middleware/allowedMethods.js.map +1 -0
- package/dist/cjs/server/auth/middleware/bearerAuth.d.ts +28 -0
- package/dist/cjs/server/auth/middleware/bearerAuth.d.ts.map +1 -0
- package/dist/cjs/server/auth/middleware/bearerAuth.js +59 -0
- package/dist/cjs/server/auth/middleware/bearerAuth.js.map +1 -0
- package/dist/cjs/server/auth/middleware/clientAuth.d.ts +19 -0
- package/dist/cjs/server/auth/middleware/clientAuth.d.ts.map +1 -0
- package/dist/cjs/server/auth/middleware/clientAuth.js +53 -0
- package/dist/cjs/server/auth/middleware/clientAuth.js.map +1 -0
- package/dist/cjs/server/auth/provider.d.ts +50 -0
- package/dist/cjs/server/auth/provider.d.ts.map +1 -0
- package/dist/cjs/server/auth/provider.js +3 -0
- package/dist/cjs/server/auth/provider.js.map +1 -0
- package/dist/cjs/server/auth/router.d.ts +36 -0
- package/dist/cjs/server/auth/router.d.ts.map +1 -0
- package/dist/cjs/server/auth/router.js +68 -0
- package/dist/cjs/server/auth/router.js.map +1 -0
- package/dist/cjs/server/auth/types.d.ts +22 -0
- package/dist/cjs/server/auth/types.d.ts.map +1 -0
- package/dist/cjs/server/auth/types.js +3 -0
- package/dist/cjs/server/auth/types.js.map +1 -0
- package/dist/cjs/server/mcp.d.ts.map +1 -1
- package/dist/cjs/server/mcp.js +3 -1
- package/dist/cjs/server/mcp.js.map +1 -1
- package/dist/cjs/shared/auth.d.ts +271 -0
- package/dist/cjs/shared/auth.d.ts.map +1 -0
- package/dist/cjs/shared/auth.js +106 -0
- package/dist/cjs/shared/auth.js.map +1 -0
- package/dist/cjs/shared/protocol.d.ts +16 -0
- package/dist/cjs/shared/protocol.d.ts.map +1 -1
- package/dist/cjs/shared/protocol.js +66 -33
- package/dist/cjs/shared/protocol.js.map +1 -1
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/types.js +1 -0
- package/dist/cjs/types.js.map +1 -1
- package/dist/esm/client/auth.d.ts +116 -0
- package/dist/esm/client/auth.d.ts.map +1 -0
- package/dist/esm/client/auth.js +238 -0
- package/dist/esm/client/auth.js.map +1 -0
- package/dist/esm/client/sse.d.ts +43 -4
- package/dist/esm/client/sse.d.ts.map +1 -1
- package/dist/esm/client/sse.js +72 -5
- package/dist/esm/client/sse.js.map +1 -1
- package/dist/esm/server/auth/clients.d.ts +19 -0
- package/dist/esm/server/auth/clients.d.ts.map +1 -0
- package/dist/esm/server/auth/clients.js +2 -0
- package/dist/esm/server/auth/clients.js.map +1 -0
- package/dist/esm/server/auth/errors.d.ts +126 -0
- package/dist/esm/server/auth/errors.d.ts.map +1 -0
- package/dist/esm/server/auth/errors.js +169 -0
- package/dist/esm/server/auth/errors.js.map +1 -0
- package/dist/esm/server/auth/handlers/authorize.d.ts +13 -0
- package/dist/esm/server/auth/handlers/authorize.d.ts.map +1 -0
- package/dist/esm/server/auth/handlers/authorize.js +143 -0
- package/dist/esm/server/auth/handlers/authorize.js.map +1 -0
- package/dist/esm/server/auth/handlers/metadata.d.ts +4 -0
- package/dist/esm/server/auth/handlers/metadata.d.ts.map +1 -0
- package/dist/esm/server/auth/handlers/metadata.js +15 -0
- package/dist/esm/server/auth/handlers/metadata.js.map +1 -0
- package/dist/esm/server/auth/handlers/register.d.ts +23 -0
- package/dist/esm/server/auth/handlers/register.d.ts.map +1 -0
- package/dist/esm/server/auth/handlers/register.js +73 -0
- package/dist/esm/server/auth/handlers/register.js.map +1 -0
- package/dist/esm/server/auth/handlers/revoke.d.ts +13 -0
- package/dist/esm/server/auth/handlers/revoke.d.ts.map +1 -0
- package/dist/esm/server/auth/handlers/revoke.js +61 -0
- package/dist/esm/server/auth/handlers/revoke.js.map +1 -0
- package/dist/esm/server/auth/handlers/token.d.ts +13 -0
- package/dist/esm/server/auth/handlers/token.d.ts.map +1 -0
- package/dist/esm/server/auth/handlers/token.js +101 -0
- package/dist/esm/server/auth/handlers/token.js.map +1 -0
- package/dist/esm/server/auth/middleware/allowedMethods.d.ts +9 -0
- package/dist/esm/server/auth/middleware/allowedMethods.d.ts.map +1 -0
- package/dist/esm/server/auth/middleware/allowedMethods.js +20 -0
- package/dist/esm/server/auth/middleware/allowedMethods.js.map +1 -0
- package/dist/esm/server/auth/middleware/bearerAuth.d.ts +28 -0
- package/dist/esm/server/auth/middleware/bearerAuth.d.ts.map +1 -0
- package/dist/esm/server/auth/middleware/bearerAuth.js +56 -0
- package/dist/esm/server/auth/middleware/bearerAuth.js.map +1 -0
- package/dist/esm/server/auth/middleware/clientAuth.d.ts +19 -0
- package/dist/esm/server/auth/middleware/clientAuth.d.ts.map +1 -0
- package/dist/esm/server/auth/middleware/clientAuth.js +50 -0
- package/dist/esm/server/auth/middleware/clientAuth.js.map +1 -0
- package/dist/esm/server/auth/provider.d.ts +50 -0
- package/dist/esm/server/auth/provider.d.ts.map +1 -0
- package/dist/esm/server/auth/provider.js +2 -0
- package/dist/esm/server/auth/provider.js.map +1 -0
- package/dist/esm/server/auth/router.d.ts +36 -0
- package/dist/esm/server/auth/router.d.ts.map +1 -0
- package/dist/esm/server/auth/router.js +62 -0
- package/dist/esm/server/auth/router.js.map +1 -0
- package/dist/esm/server/auth/types.d.ts +22 -0
- package/dist/esm/server/auth/types.d.ts.map +1 -0
- package/dist/esm/server/auth/types.js +2 -0
- package/dist/esm/server/auth/types.js.map +1 -0
- package/dist/esm/server/mcp.d.ts.map +1 -1
- package/dist/esm/server/mcp.js +3 -1
- package/dist/esm/server/mcp.js.map +1 -1
- package/dist/esm/shared/auth.d.ts +271 -0
- package/dist/esm/shared/auth.d.ts.map +1 -0
- package/dist/esm/shared/auth.js +103 -0
- package/dist/esm/shared/auth.js.map +1 -0
- package/dist/esm/shared/protocol.d.ts +16 -0
- package/dist/esm/shared/protocol.d.ts.map +1 -1
- package/dist/esm/shared/protocol.js +66 -33
- package/dist/esm/shared/protocol.js.map +1 -1
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/types.js +1 -0
- package/dist/esm/types.js.map +1 -1
- package/package.json +10 -3
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import { OAuthClientMetadataSchema } from "../../../shared/auth.js";
|
|
3
|
+
import crypto from 'node:crypto';
|
|
4
|
+
import cors from 'cors';
|
|
5
|
+
import { rateLimit } from "express-rate-limit";
|
|
6
|
+
import { allowedMethods } from "../middleware/allowedMethods.js";
|
|
7
|
+
import { InvalidClientMetadataError, ServerError, TooManyRequestsError, OAuthError } from "../errors.js";
|
|
8
|
+
const DEFAULT_CLIENT_SECRET_EXPIRY_SECONDS = 30 * 24 * 60 * 60; // 30 days
|
|
9
|
+
export function clientRegistrationHandler({ clientsStore, clientSecretExpirySeconds = DEFAULT_CLIENT_SECRET_EXPIRY_SECONDS, rateLimit: rateLimitConfig }) {
|
|
10
|
+
if (!clientsStore.registerClient) {
|
|
11
|
+
throw new Error("Client registration store does not support registering clients");
|
|
12
|
+
}
|
|
13
|
+
// Nested router so we can configure middleware and restrict HTTP method
|
|
14
|
+
const router = express.Router();
|
|
15
|
+
// Configure CORS to allow any origin, to make accessible to web-based MCP clients
|
|
16
|
+
router.use(cors());
|
|
17
|
+
router.use(allowedMethods(["POST"]));
|
|
18
|
+
router.use(express.json());
|
|
19
|
+
// Apply rate limiting unless explicitly disabled - stricter limits for registration
|
|
20
|
+
if (rateLimitConfig !== false) {
|
|
21
|
+
router.use(rateLimit({
|
|
22
|
+
windowMs: 60 * 60 * 1000, // 1 hour
|
|
23
|
+
max: 20, // 20 requests per hour - stricter as registration is sensitive
|
|
24
|
+
standardHeaders: true,
|
|
25
|
+
legacyHeaders: false,
|
|
26
|
+
message: new TooManyRequestsError('You have exceeded the rate limit for client registration requests').toResponseObject(),
|
|
27
|
+
...rateLimitConfig
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
router.post("/", async (req, res) => {
|
|
31
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
32
|
+
try {
|
|
33
|
+
const parseResult = OAuthClientMetadataSchema.safeParse(req.body);
|
|
34
|
+
if (!parseResult.success) {
|
|
35
|
+
throw new InvalidClientMetadataError(parseResult.error.message);
|
|
36
|
+
}
|
|
37
|
+
const clientMetadata = parseResult.data;
|
|
38
|
+
const isPublicClient = clientMetadata.token_endpoint_auth_method === 'none';
|
|
39
|
+
// Generate client credentials
|
|
40
|
+
const clientId = crypto.randomUUID();
|
|
41
|
+
const clientSecret = isPublicClient
|
|
42
|
+
? undefined
|
|
43
|
+
: crypto.randomBytes(32).toString('hex');
|
|
44
|
+
const clientIdIssuedAt = Math.floor(Date.now() / 1000);
|
|
45
|
+
// Calculate client secret expiry time
|
|
46
|
+
const clientsDoExpire = clientSecretExpirySeconds > 0;
|
|
47
|
+
const secretExpiryTime = clientsDoExpire ? clientIdIssuedAt + clientSecretExpirySeconds : 0;
|
|
48
|
+
const clientSecretExpiresAt = isPublicClient ? undefined : secretExpiryTime;
|
|
49
|
+
let clientInfo = {
|
|
50
|
+
...clientMetadata,
|
|
51
|
+
client_id: clientId,
|
|
52
|
+
client_secret: clientSecret,
|
|
53
|
+
client_id_issued_at: clientIdIssuedAt,
|
|
54
|
+
client_secret_expires_at: clientSecretExpiresAt,
|
|
55
|
+
};
|
|
56
|
+
clientInfo = await clientsStore.registerClient(clientInfo);
|
|
57
|
+
res.status(201).json(clientInfo);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
if (error instanceof OAuthError) {
|
|
61
|
+
const status = error instanceof ServerError ? 500 : 400;
|
|
62
|
+
res.status(status).json(error.toResponseObject());
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.error("Unexpected error registering client:", error);
|
|
66
|
+
const serverError = new ServerError("Internal Server Error");
|
|
67
|
+
res.status(500).json(serverError.toResponseObject());
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return router;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../../../../../src/server/auth/handlers/register.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { OAuthServerProvider } from "../provider.js";
|
|
2
|
+
import { RequestHandler } from "express";
|
|
3
|
+
import { Options as RateLimitOptions } from "express-rate-limit";
|
|
4
|
+
export type RevocationHandlerOptions = {
|
|
5
|
+
provider: OAuthServerProvider;
|
|
6
|
+
/**
|
|
7
|
+
* Rate limiting configuration for the token revocation endpoint.
|
|
8
|
+
* Set to false to disable rate limiting for this endpoint.
|
|
9
|
+
*/
|
|
10
|
+
rateLimit?: Partial<RateLimitOptions> | false;
|
|
11
|
+
};
|
|
12
|
+
export declare function revocationHandler({ provider, rateLimit: rateLimitConfig }: RevocationHandlerOptions): RequestHandler;
|
|
13
|
+
//# sourceMappingURL=revoke.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revoke.d.ts","sourceRoot":"","sources":["../../../../../src/server/auth/handlers/revoke.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAIlD,OAAO,EAAa,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAS5E,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,mBAAmB,CAAC;IAC9B;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAAC;CAC/C,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,EAAE,EAAE,wBAAwB,GAAG,cAAc,CA4DpH"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import cors from "cors";
|
|
3
|
+
import { authenticateClient } from "../middleware/clientAuth.js";
|
|
4
|
+
import { OAuthTokenRevocationRequestSchema } from "../../../shared/auth.js";
|
|
5
|
+
import { rateLimit } from "express-rate-limit";
|
|
6
|
+
import { allowedMethods } from "../middleware/allowedMethods.js";
|
|
7
|
+
import { InvalidRequestError, ServerError, TooManyRequestsError, OAuthError } from "../errors.js";
|
|
8
|
+
export function revocationHandler({ provider, rateLimit: rateLimitConfig }) {
|
|
9
|
+
if (!provider.revokeToken) {
|
|
10
|
+
throw new Error("Auth provider does not support revoking tokens");
|
|
11
|
+
}
|
|
12
|
+
// Nested router so we can configure middleware and restrict HTTP method
|
|
13
|
+
const router = express.Router();
|
|
14
|
+
// Configure CORS to allow any origin, to make accessible to web-based MCP clients
|
|
15
|
+
router.use(cors());
|
|
16
|
+
router.use(allowedMethods(["POST"]));
|
|
17
|
+
router.use(express.urlencoded({ extended: false }));
|
|
18
|
+
// Apply rate limiting unless explicitly disabled
|
|
19
|
+
if (rateLimitConfig !== false) {
|
|
20
|
+
router.use(rateLimit({
|
|
21
|
+
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
22
|
+
max: 50, // 50 requests per windowMs
|
|
23
|
+
standardHeaders: true,
|
|
24
|
+
legacyHeaders: false,
|
|
25
|
+
message: new TooManyRequestsError('You have exceeded the rate limit for token revocation requests').toResponseObject(),
|
|
26
|
+
...rateLimitConfig
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
// Authenticate and extract client details
|
|
30
|
+
router.use(authenticateClient({ clientsStore: provider.clientsStore }));
|
|
31
|
+
router.post("/", async (req, res) => {
|
|
32
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
33
|
+
try {
|
|
34
|
+
const parseResult = OAuthTokenRevocationRequestSchema.safeParse(req.body);
|
|
35
|
+
if (!parseResult.success) {
|
|
36
|
+
throw new InvalidRequestError(parseResult.error.message);
|
|
37
|
+
}
|
|
38
|
+
const client = req.client;
|
|
39
|
+
if (!client) {
|
|
40
|
+
// This should never happen
|
|
41
|
+
console.error("Missing client information after authentication");
|
|
42
|
+
throw new ServerError("Internal Server Error");
|
|
43
|
+
}
|
|
44
|
+
await provider.revokeToken(client, parseResult.data);
|
|
45
|
+
res.status(200).json({});
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
if (error instanceof OAuthError) {
|
|
49
|
+
const status = error instanceof ServerError ? 500 : 400;
|
|
50
|
+
res.status(status).json(error.toResponseObject());
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
console.error("Unexpected error revoking token:", error);
|
|
54
|
+
const serverError = new ServerError("Internal Server Error");
|
|
55
|
+
res.status(500).json(serverError.toResponseObject());
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
return router;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=revoke.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revoke.js","sourceRoot":"","sources":["../../../../../src/server/auth/handlers/revoke.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { RequestHandler } from "express";
|
|
2
|
+
import { OAuthServerProvider } from "../provider.js";
|
|
3
|
+
import { Options as RateLimitOptions } from "express-rate-limit";
|
|
4
|
+
export type TokenHandlerOptions = {
|
|
5
|
+
provider: OAuthServerProvider;
|
|
6
|
+
/**
|
|
7
|
+
* Rate limiting configuration for the token endpoint.
|
|
8
|
+
* Set to false to disable rate limiting for this endpoint.
|
|
9
|
+
*/
|
|
10
|
+
rateLimit?: Partial<RateLimitOptions> | false;
|
|
11
|
+
};
|
|
12
|
+
export declare function tokenHandler({ provider, rateLimit: rateLimitConfig }: TokenHandlerOptions): RequestHandler;
|
|
13
|
+
//# sourceMappingURL=token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../../../../src/server/auth/handlers/token.ts"],"names":[],"mappings":"AACA,OAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAIrD,OAAO,EAAa,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAW5E,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,mBAAmB,CAAC;IAC9B;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAAC;CAC/C,CAAC;AAgBF,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,EAAE,EAAE,mBAAmB,GAAG,cAAc,CAkG1G"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import express from "express";
|
|
3
|
+
import cors from "cors";
|
|
4
|
+
import { verifyChallenge } from "pkce-challenge";
|
|
5
|
+
import { authenticateClient } from "../middleware/clientAuth.js";
|
|
6
|
+
import { rateLimit } from "express-rate-limit";
|
|
7
|
+
import { allowedMethods } from "../middleware/allowedMethods.js";
|
|
8
|
+
import { InvalidRequestError, InvalidGrantError, UnsupportedGrantTypeError, ServerError, TooManyRequestsError, OAuthError } from "../errors.js";
|
|
9
|
+
const TokenRequestSchema = z.object({
|
|
10
|
+
grant_type: z.string(),
|
|
11
|
+
});
|
|
12
|
+
const AuthorizationCodeGrantSchema = z.object({
|
|
13
|
+
code: z.string(),
|
|
14
|
+
code_verifier: z.string(),
|
|
15
|
+
});
|
|
16
|
+
const RefreshTokenGrantSchema = z.object({
|
|
17
|
+
refresh_token: z.string(),
|
|
18
|
+
scope: z.string().optional(),
|
|
19
|
+
});
|
|
20
|
+
export function tokenHandler({ provider, rateLimit: rateLimitConfig }) {
|
|
21
|
+
// Nested router so we can configure middleware and restrict HTTP method
|
|
22
|
+
const router = express.Router();
|
|
23
|
+
// Configure CORS to allow any origin, to make accessible to web-based MCP clients
|
|
24
|
+
router.use(cors());
|
|
25
|
+
router.use(allowedMethods(["POST"]));
|
|
26
|
+
router.use(express.urlencoded({ extended: false }));
|
|
27
|
+
// Apply rate limiting unless explicitly disabled
|
|
28
|
+
if (rateLimitConfig !== false) {
|
|
29
|
+
router.use(rateLimit({
|
|
30
|
+
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
31
|
+
max: 50, // 50 requests per windowMs
|
|
32
|
+
standardHeaders: true,
|
|
33
|
+
legacyHeaders: false,
|
|
34
|
+
message: new TooManyRequestsError('You have exceeded the rate limit for token requests').toResponseObject(),
|
|
35
|
+
...rateLimitConfig
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
// Authenticate and extract client details
|
|
39
|
+
router.use(authenticateClient({ clientsStore: provider.clientsStore }));
|
|
40
|
+
router.post("/", async (req, res) => {
|
|
41
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
42
|
+
try {
|
|
43
|
+
const parseResult = TokenRequestSchema.safeParse(req.body);
|
|
44
|
+
if (!parseResult.success) {
|
|
45
|
+
throw new InvalidRequestError(parseResult.error.message);
|
|
46
|
+
}
|
|
47
|
+
const { grant_type } = parseResult.data;
|
|
48
|
+
const client = req.client;
|
|
49
|
+
if (!client) {
|
|
50
|
+
// This should never happen
|
|
51
|
+
console.error("Missing client information after authentication");
|
|
52
|
+
throw new ServerError("Internal Server Error");
|
|
53
|
+
}
|
|
54
|
+
switch (grant_type) {
|
|
55
|
+
case "authorization_code": {
|
|
56
|
+
const parseResult = AuthorizationCodeGrantSchema.safeParse(req.body);
|
|
57
|
+
if (!parseResult.success) {
|
|
58
|
+
throw new InvalidRequestError(parseResult.error.message);
|
|
59
|
+
}
|
|
60
|
+
const { code, code_verifier } = parseResult.data;
|
|
61
|
+
// Verify PKCE challenge
|
|
62
|
+
const codeChallenge = await provider.challengeForAuthorizationCode(client, code);
|
|
63
|
+
if (!(await verifyChallenge(code_verifier, codeChallenge))) {
|
|
64
|
+
throw new InvalidGrantError("code_verifier does not match the challenge");
|
|
65
|
+
}
|
|
66
|
+
const tokens = await provider.exchangeAuthorizationCode(client, code);
|
|
67
|
+
res.status(200).json(tokens);
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
case "refresh_token": {
|
|
71
|
+
const parseResult = RefreshTokenGrantSchema.safeParse(req.body);
|
|
72
|
+
if (!parseResult.success) {
|
|
73
|
+
throw new InvalidRequestError(parseResult.error.message);
|
|
74
|
+
}
|
|
75
|
+
const { refresh_token, scope } = parseResult.data;
|
|
76
|
+
const scopes = scope === null || scope === void 0 ? void 0 : scope.split(" ");
|
|
77
|
+
const tokens = await provider.exchangeRefreshToken(client, refresh_token, scopes);
|
|
78
|
+
res.status(200).json(tokens);
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
// Not supported right now
|
|
82
|
+
//case "client_credentials":
|
|
83
|
+
default:
|
|
84
|
+
throw new UnsupportedGrantTypeError("The grant type is not supported by this authorization server.");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
if (error instanceof OAuthError) {
|
|
89
|
+
const status = error instanceof ServerError ? 500 : 400;
|
|
90
|
+
res.status(status).json(error.toResponseObject());
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
console.error("Unexpected error exchanging token:", error);
|
|
94
|
+
const serverError = new ServerError("Internal Server Error");
|
|
95
|
+
res.status(500).json(serverError.toResponseObject());
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
return router;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../../../../src/server/auth/handlers/token.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { RequestHandler } from "express";
|
|
2
|
+
/**
|
|
3
|
+
* Middleware to handle unsupported HTTP methods with a 405 Method Not Allowed response.
|
|
4
|
+
*
|
|
5
|
+
* @param allowedMethods Array of allowed HTTP methods for this endpoint (e.g., ['GET', 'POST'])
|
|
6
|
+
* @returns Express middleware that returns a 405 error if method not in allowed list
|
|
7
|
+
*/
|
|
8
|
+
export declare function allowedMethods(allowedMethods: string[]): RequestHandler;
|
|
9
|
+
//# sourceMappingURL=allowedMethods.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allowedMethods.d.ts","sourceRoot":"","sources":["../../../../../src/server/auth/middleware/allowedMethods.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGzC;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,cAAc,CAYvE"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { MethodNotAllowedError } from "../errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* Middleware to handle unsupported HTTP methods with a 405 Method Not Allowed response.
|
|
4
|
+
*
|
|
5
|
+
* @param allowedMethods Array of allowed HTTP methods for this endpoint (e.g., ['GET', 'POST'])
|
|
6
|
+
* @returns Express middleware that returns a 405 error if method not in allowed list
|
|
7
|
+
*/
|
|
8
|
+
export function allowedMethods(allowedMethods) {
|
|
9
|
+
return (req, res, next) => {
|
|
10
|
+
if (allowedMethods.includes(req.method)) {
|
|
11
|
+
next();
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const error = new MethodNotAllowedError(`The method ${req.method} is not allowed for this endpoint`);
|
|
15
|
+
res.status(405)
|
|
16
|
+
.set('Allow', allowedMethods.join(', '))
|
|
17
|
+
.json(error.toResponseObject());
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=allowedMethods.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allowedMethods.js","sourceRoot":"","sources":["../../../../../src/server/auth/middleware/allowedMethods.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAErD;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,cAAwB;IACrD,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACxB,IAAI,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACxC,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,qBAAqB,CAAC,cAAc,GAAG,CAAC,MAAM,mCAAmC,CAAC,CAAC;QACrG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;aACZ,GAAG,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aACvC,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { RequestHandler } from "express";
|
|
2
|
+
import { OAuthServerProvider } from "../provider.js";
|
|
3
|
+
import { AuthInfo } from "../types.js";
|
|
4
|
+
export type BearerAuthMiddlewareOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* A provider used to verify tokens.
|
|
7
|
+
*/
|
|
8
|
+
provider: OAuthServerProvider;
|
|
9
|
+
/**
|
|
10
|
+
* Optional scopes that the token must have.
|
|
11
|
+
*/
|
|
12
|
+
requiredScopes?: string[];
|
|
13
|
+
};
|
|
14
|
+
declare module "express-serve-static-core" {
|
|
15
|
+
interface Request {
|
|
16
|
+
/**
|
|
17
|
+
* Information about the validated access token, if the `requireBearerAuth` middleware was used.
|
|
18
|
+
*/
|
|
19
|
+
auth?: AuthInfo;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Middleware that requires a valid Bearer token in the Authorization header.
|
|
24
|
+
*
|
|
25
|
+
* This will validate the token with the auth provider and add the resulting auth info to the request object.
|
|
26
|
+
*/
|
|
27
|
+
export declare function requireBearerAuth({ provider, requiredScopes }: BearerAuthMiddlewareOptions): RequestHandler;
|
|
28
|
+
//# sourceMappingURL=bearerAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bearerAuth.d.ts","sourceRoot":"","sources":["../../../../../src/server/auth/middleware/bearerAuth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,MAAM,MAAM,2BAA2B,GAAG;IACxC;;OAEG;IACH,QAAQ,EAAE,mBAAmB,CAAC;IAE9B;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AAEF,OAAO,QAAQ,2BAA2B,CAAC;IACzC,UAAU,OAAO;QACf;;WAEG;QACH,IAAI,CAAC,EAAE,QAAQ,CAAC;KACjB;CACF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,QAAQ,EAAE,cAAmB,EAAE,EAAE,2BAA2B,GAAG,cAAc,CAmDhH"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { InsufficientScopeError, InvalidTokenError, OAuthError, ServerError } from "../errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* Middleware that requires a valid Bearer token in the Authorization header.
|
|
4
|
+
*
|
|
5
|
+
* This will validate the token with the auth provider and add the resulting auth info to the request object.
|
|
6
|
+
*/
|
|
7
|
+
export function requireBearerAuth({ provider, requiredScopes = [] }) {
|
|
8
|
+
return async (req, res, next) => {
|
|
9
|
+
try {
|
|
10
|
+
const authHeader = req.headers.authorization;
|
|
11
|
+
if (!authHeader) {
|
|
12
|
+
throw new InvalidTokenError("Missing Authorization header");
|
|
13
|
+
}
|
|
14
|
+
const [type, token] = authHeader.split(' ');
|
|
15
|
+
if (type.toLowerCase() !== 'bearer' || !token) {
|
|
16
|
+
throw new InvalidTokenError("Invalid Authorization header format, expected 'Bearer TOKEN'");
|
|
17
|
+
}
|
|
18
|
+
const authInfo = await provider.verifyAccessToken(token);
|
|
19
|
+
// Check if token has the required scopes (if any)
|
|
20
|
+
if (requiredScopes.length > 0) {
|
|
21
|
+
const hasAllScopes = requiredScopes.every(scope => authInfo.scopes.includes(scope));
|
|
22
|
+
if (!hasAllScopes) {
|
|
23
|
+
throw new InsufficientScopeError("Insufficient scope");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Check if the token is expired
|
|
27
|
+
if (!!authInfo.expiresAt && authInfo.expiresAt < Date.now() / 1000) {
|
|
28
|
+
throw new InvalidTokenError("Token has expired");
|
|
29
|
+
}
|
|
30
|
+
req.auth = authInfo;
|
|
31
|
+
next();
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (error instanceof InvalidTokenError) {
|
|
35
|
+
res.set("WWW-Authenticate", `Bearer error="${error.errorCode}", error_description="${error.message}"`);
|
|
36
|
+
res.status(401).json(error.toResponseObject());
|
|
37
|
+
}
|
|
38
|
+
else if (error instanceof InsufficientScopeError) {
|
|
39
|
+
res.set("WWW-Authenticate", `Bearer error="${error.errorCode}", error_description="${error.message}"`);
|
|
40
|
+
res.status(403).json(error.toResponseObject());
|
|
41
|
+
}
|
|
42
|
+
else if (error instanceof ServerError) {
|
|
43
|
+
res.status(500).json(error.toResponseObject());
|
|
44
|
+
}
|
|
45
|
+
else if (error instanceof OAuthError) {
|
|
46
|
+
res.status(400).json(error.toResponseObject());
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
console.error("Unexpected error authenticating bearer token:", error);
|
|
50
|
+
const serverError = new ServerError("Internal Server Error");
|
|
51
|
+
res.status(500).json(serverError.toResponseObject());
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=bearerAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bearerAuth.js","sourceRoot":"","sources":["../../../../../src/server/auth/middleware/bearerAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { RequestHandler } from "express";
|
|
2
|
+
import { OAuthRegisteredClientsStore } from "../clients.js";
|
|
3
|
+
import { OAuthClientInformationFull } from "../../../shared/auth.js";
|
|
4
|
+
export type ClientAuthenticationMiddlewareOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* A store used to read information about registered OAuth clients.
|
|
7
|
+
*/
|
|
8
|
+
clientsStore: OAuthRegisteredClientsStore;
|
|
9
|
+
};
|
|
10
|
+
declare module "express-serve-static-core" {
|
|
11
|
+
interface Request {
|
|
12
|
+
/**
|
|
13
|
+
* The authenticated client for this request, if the `authenticateClient` middleware was used.
|
|
14
|
+
*/
|
|
15
|
+
client?: OAuthClientInformationFull;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export declare function authenticateClient({ clientsStore }: ClientAuthenticationMiddlewareOptions): RequestHandler;
|
|
19
|
+
//# sourceMappingURL=clientAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clientAuth.d.ts","sourceRoot":"","sources":["../../../../../src/server/auth/middleware/clientAuth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAGrE,MAAM,MAAM,qCAAqC,GAAG;IAClD;;OAEG;IACH,YAAY,EAAE,2BAA2B,CAAC;CAC3C,CAAA;AAOD,OAAO,QAAQ,2BAA2B,CAAC;IACzC,UAAU,OAAO;QACf;;WAEG;QACH,MAAM,CAAC,EAAE,0BAA0B,CAAC;KACrC;CACF;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,EAAE,qCAAqC,GAAG,cAAc,CA6C1G"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { InvalidRequestError, InvalidClientError, ServerError, OAuthError } from "../errors.js";
|
|
3
|
+
const ClientAuthenticatedRequestSchema = z.object({
|
|
4
|
+
client_id: z.string(),
|
|
5
|
+
client_secret: z.string().optional(),
|
|
6
|
+
});
|
|
7
|
+
export function authenticateClient({ clientsStore }) {
|
|
8
|
+
return async (req, res, next) => {
|
|
9
|
+
try {
|
|
10
|
+
const result = ClientAuthenticatedRequestSchema.safeParse(req.body);
|
|
11
|
+
if (!result.success) {
|
|
12
|
+
throw new InvalidRequestError(String(result.error));
|
|
13
|
+
}
|
|
14
|
+
const { client_id, client_secret } = result.data;
|
|
15
|
+
const client = await clientsStore.getClient(client_id);
|
|
16
|
+
if (!client) {
|
|
17
|
+
throw new InvalidClientError("Invalid client_id");
|
|
18
|
+
}
|
|
19
|
+
// If client has a secret, validate it
|
|
20
|
+
if (client.client_secret) {
|
|
21
|
+
// Check if client_secret is required but not provided
|
|
22
|
+
if (!client_secret) {
|
|
23
|
+
throw new InvalidClientError("Client secret is required");
|
|
24
|
+
}
|
|
25
|
+
// Check if client_secret matches
|
|
26
|
+
if (client.client_secret !== client_secret) {
|
|
27
|
+
throw new InvalidClientError("Invalid client_secret");
|
|
28
|
+
}
|
|
29
|
+
// Check if client_secret has expired
|
|
30
|
+
if (client.client_secret_expires_at && client.client_secret_expires_at < Math.floor(Date.now() / 1000)) {
|
|
31
|
+
throw new InvalidClientError("Client secret has expired");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
req.client = client;
|
|
35
|
+
next();
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (error instanceof OAuthError) {
|
|
39
|
+
const status = error instanceof ServerError ? 500 : 400;
|
|
40
|
+
res.status(status).json(error.toResponseObject());
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
console.error("Unexpected error authenticating client:", error);
|
|
44
|
+
const serverError = new ServerError("Internal Server Error");
|
|
45
|
+
res.status(500).json(serverError.toResponseObject());
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=clientAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clientAuth.js","sourceRoot":"","sources":["../../../../../src/server/auth/middleware/clientAuth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAShG,MAAM,gCAAgC,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAC;AAWH,MAAM,UAAU,kBAAkB,CAAC,EAAE,YAAY,EAAyC;IACxF,OAAO,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC9B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,gCAAgC,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACpE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,MAAM,IAAI,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACtD,CAAC;YAED,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC;YACjD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;YACvD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,kBAAkB,CAAC,mBAAmB,CAAC,CAAC;YACpD,CAAC;YAED,sCAAsC;YACtC,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;gBACzB,sDAAsD;gBACtD,IAAI,CAAC,aAAa,EAAE,CAAC;oBACnB,MAAM,IAAI,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;gBAC5D,CAAC;gBAED,iCAAiC;gBACjC,IAAI,MAAM,CAAC,aAAa,KAAK,aAAa,EAAE,CAAC;oBAC3C,MAAM,IAAI,kBAAkB,CAAC,uBAAuB,CAAC,CAAC;gBACxD,CAAC;gBAED,qCAAqC;gBACrC,IAAI,MAAM,CAAC,wBAAwB,IAAI,MAAM,CAAC,wBAAwB,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;oBACvG,MAAM,IAAI,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;gBAC5D,CAAC;YACH,CAAC;YAED,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC;YACpB,IAAI,EAAE,CAAC;QACT,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;gBAChC,MAAM,MAAM,GAAG,KAAK,YAAY,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;gBACxD,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC;YACpD,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC,CAAC;gBAChE,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,uBAAuB,CAAC,CAAC;gBAC7D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,gBAAgB,EAAE,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;IACH,CAAC,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Response } from "express";
|
|
2
|
+
import { OAuthRegisteredClientsStore } from "./clients.js";
|
|
3
|
+
import { OAuthClientInformationFull, OAuthTokenRevocationRequest, OAuthTokens } from "../../shared/auth.js";
|
|
4
|
+
import { AuthInfo } from "./types.js";
|
|
5
|
+
export type AuthorizationParams = {
|
|
6
|
+
state?: string;
|
|
7
|
+
scopes?: string[];
|
|
8
|
+
codeChallenge: string;
|
|
9
|
+
redirectUri: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Implements an end-to-end OAuth server.
|
|
13
|
+
*/
|
|
14
|
+
export interface OAuthServerProvider {
|
|
15
|
+
/**
|
|
16
|
+
* A store used to read information about registered OAuth clients.
|
|
17
|
+
*/
|
|
18
|
+
get clientsStore(): OAuthRegisteredClientsStore;
|
|
19
|
+
/**
|
|
20
|
+
* Begins the authorization flow, which can either be implemented by this server itself or via redirection to a separate authorization server.
|
|
21
|
+
*
|
|
22
|
+
* This server must eventually issue a redirect with an authorization response or an error response to the given redirect URI. Per OAuth 2.1:
|
|
23
|
+
* - In the successful case, the redirect MUST include the `code` and `state` (if present) query parameters.
|
|
24
|
+
* - In the error case, the redirect MUST include the `error` query parameter, and MAY include an optional `error_description` query parameter.
|
|
25
|
+
*/
|
|
26
|
+
authorize(client: OAuthClientInformationFull, params: AuthorizationParams, res: Response): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Returns the `codeChallenge` that was used when the indicated authorization began.
|
|
29
|
+
*/
|
|
30
|
+
challengeForAuthorizationCode(client: OAuthClientInformationFull, authorizationCode: string): Promise<string>;
|
|
31
|
+
/**
|
|
32
|
+
* Exchanges an authorization code for an access token.
|
|
33
|
+
*/
|
|
34
|
+
exchangeAuthorizationCode(client: OAuthClientInformationFull, authorizationCode: string): Promise<OAuthTokens>;
|
|
35
|
+
/**
|
|
36
|
+
* Exchanges a refresh token for an access token.
|
|
37
|
+
*/
|
|
38
|
+
exchangeRefreshToken(client: OAuthClientInformationFull, refreshToken: string, scopes?: string[]): Promise<OAuthTokens>;
|
|
39
|
+
/**
|
|
40
|
+
* Verifies an access token and returns information about it.
|
|
41
|
+
*/
|
|
42
|
+
verifyAccessToken(token: string): Promise<AuthInfo>;
|
|
43
|
+
/**
|
|
44
|
+
* Revokes an access or refresh token. If unimplemented, token revocation is not supported (not recommended).
|
|
45
|
+
*
|
|
46
|
+
* If the given token is invalid or already revoked, this method should do nothing.
|
|
47
|
+
*/
|
|
48
|
+
revokeToken?(client: OAuthClientInformationFull, request: OAuthTokenRevocationRequest): Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../../src/server/auth/provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,2BAA2B,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC5G,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,IAAI,YAAY,IAAI,2BAA2B,CAAC;IAEhD;;;;;;OAMG;IACH,SAAS,CAAC,MAAM,EAAE,0BAA0B,EAAE,MAAM,EAAE,mBAAmB,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzG;;OAEG;IACH,6BAA6B,CAAC,MAAM,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE9G;;OAEG;IACH,yBAAyB,CAAC,MAAM,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAE/G;;OAEG;IACH,oBAAoB,CAAC,MAAM,EAAE,0BAA0B,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAExH;;OAEG;IACH,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEpD;;;;OAIG;IACH,WAAW,CAAC,CAAC,MAAM,EAAE,0BAA0B,EAAE,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../../src/server/auth/provider.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { RequestHandler } from "express";
|
|
2
|
+
import { ClientRegistrationHandlerOptions } from "./handlers/register.js";
|
|
3
|
+
import { TokenHandlerOptions } from "./handlers/token.js";
|
|
4
|
+
import { AuthorizationHandlerOptions } from "./handlers/authorize.js";
|
|
5
|
+
import { RevocationHandlerOptions } from "./handlers/revoke.js";
|
|
6
|
+
import { OAuthServerProvider } from "./provider.js";
|
|
7
|
+
export type AuthRouterOptions = {
|
|
8
|
+
/**
|
|
9
|
+
* A provider implementing the actual authorization logic for this router.
|
|
10
|
+
*/
|
|
11
|
+
provider: OAuthServerProvider;
|
|
12
|
+
/**
|
|
13
|
+
* The authorization server's issuer identifier, which is a URL that uses the "https" scheme and has no query or fragment components.
|
|
14
|
+
*/
|
|
15
|
+
issuerUrl: URL;
|
|
16
|
+
/**
|
|
17
|
+
* An optional URL of a page containing human-readable information that developers might want or need to know when using the authorization server.
|
|
18
|
+
*/
|
|
19
|
+
serviceDocumentationUrl?: URL;
|
|
20
|
+
authorizationOptions?: Omit<AuthorizationHandlerOptions, "provider">;
|
|
21
|
+
clientRegistrationOptions?: Omit<ClientRegistrationHandlerOptions, "clientsStore">;
|
|
22
|
+
revocationOptions?: Omit<RevocationHandlerOptions, "provider">;
|
|
23
|
+
tokenOptions?: Omit<TokenHandlerOptions, "provider">;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Installs standard MCP authorization endpoints, including dynamic client registration and token revocation (if supported). Also advertises standard authorization server metadata, for easier discovery of supported configurations by clients.
|
|
27
|
+
*
|
|
28
|
+
* By default, rate limiting is applied to all endpoints to prevent abuse.
|
|
29
|
+
*
|
|
30
|
+
* This router MUST be installed at the application root, like so:
|
|
31
|
+
*
|
|
32
|
+
* const app = express();
|
|
33
|
+
* app.use(mcpAuthRouter(...));
|
|
34
|
+
*/
|
|
35
|
+
export declare function mcpAuthRouter(options: AuthRouterOptions): RequestHandler;
|
|
36
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../../src/server/auth/router.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAA6B,gCAAgC,EAAE,MAAM,wBAAwB,CAAC;AACrG,OAAO,EAAgB,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAwB,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAC5F,OAAO,EAAqB,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAEnF,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEpD,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;OAEG;IACH,QAAQ,EAAE,mBAAmB,CAAC;IAE9B;;OAEG;IACH,SAAS,EAAE,GAAG,CAAC;IAEf;;OAEG;IACH,uBAAuB,CAAC,EAAE,GAAG,CAAC;IAG9B,oBAAoB,CAAC,EAAE,IAAI,CAAC,2BAA2B,EAAE,UAAU,CAAC,CAAC;IACrE,yBAAyB,CAAC,EAAE,IAAI,CAAC,gCAAgC,EAAE,cAAc,CAAC,CAAC;IACnF,iBAAiB,CAAC,EAAE,IAAI,CAAC,wBAAwB,EAAE,UAAU,CAAC,CAAC;IAC/D,YAAY,CAAC,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,CAAC;CACtD,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CAqExE"}
|