@modelcontextprotocol/sdk 1.5.0 → 1.6.0
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 +239 -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 +74 -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 +55 -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/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 +226 -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 +68 -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 +52 -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/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,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,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.revocationHandler = revocationHandler;
|
|
7
|
+
const express_1 = __importDefault(require("express"));
|
|
8
|
+
const cors_1 = __importDefault(require("cors"));
|
|
9
|
+
const clientAuth_js_1 = require("../middleware/clientAuth.js");
|
|
10
|
+
const auth_js_1 = require("../../../shared/auth.js");
|
|
11
|
+
const express_rate_limit_1 = require("express-rate-limit");
|
|
12
|
+
const allowedMethods_js_1 = require("../middleware/allowedMethods.js");
|
|
13
|
+
const errors_js_1 = require("../errors.js");
|
|
14
|
+
function revocationHandler({ provider, rateLimit: rateLimitConfig }) {
|
|
15
|
+
if (!provider.revokeToken) {
|
|
16
|
+
throw new Error("Auth provider does not support revoking tokens");
|
|
17
|
+
}
|
|
18
|
+
// Nested router so we can configure middleware and restrict HTTP method
|
|
19
|
+
const router = express_1.default.Router();
|
|
20
|
+
// Configure CORS to allow any origin, to make accessible to web-based MCP clients
|
|
21
|
+
router.use((0, cors_1.default)());
|
|
22
|
+
router.use((0, allowedMethods_js_1.allowedMethods)(["POST"]));
|
|
23
|
+
router.use(express_1.default.urlencoded({ extended: false }));
|
|
24
|
+
// Apply rate limiting unless explicitly disabled
|
|
25
|
+
if (rateLimitConfig !== false) {
|
|
26
|
+
router.use((0, express_rate_limit_1.rateLimit)({
|
|
27
|
+
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
28
|
+
max: 50, // 50 requests per windowMs
|
|
29
|
+
standardHeaders: true,
|
|
30
|
+
legacyHeaders: false,
|
|
31
|
+
message: new errors_js_1.TooManyRequestsError('You have exceeded the rate limit for token revocation requests').toResponseObject(),
|
|
32
|
+
...rateLimitConfig
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
// Authenticate and extract client details
|
|
36
|
+
router.use((0, clientAuth_js_1.authenticateClient)({ clientsStore: provider.clientsStore }));
|
|
37
|
+
router.post("/", async (req, res) => {
|
|
38
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
39
|
+
try {
|
|
40
|
+
const parseResult = auth_js_1.OAuthTokenRevocationRequestSchema.safeParse(req.body);
|
|
41
|
+
if (!parseResult.success) {
|
|
42
|
+
throw new errors_js_1.InvalidRequestError(parseResult.error.message);
|
|
43
|
+
}
|
|
44
|
+
const client = req.client;
|
|
45
|
+
if (!client) {
|
|
46
|
+
// This should never happen
|
|
47
|
+
console.error("Missing client information after authentication");
|
|
48
|
+
throw new errors_js_1.ServerError("Internal Server Error");
|
|
49
|
+
}
|
|
50
|
+
await provider.revokeToken(client, parseResult.data);
|
|
51
|
+
res.status(200).json({});
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (error instanceof errors_js_1.OAuthError) {
|
|
55
|
+
const status = error instanceof errors_js_1.ServerError ? 500 : 400;
|
|
56
|
+
res.status(status).json(error.toResponseObject());
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
console.error("Unexpected error revoking token:", error);
|
|
60
|
+
const serverError = new errors_js_1.ServerError("Internal Server Error");
|
|
61
|
+
res.status(500).json(serverError.toResponseObject());
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
return router;
|
|
66
|
+
}
|
|
67
|
+
//# 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,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.tokenHandler = tokenHandler;
|
|
7
|
+
const zod_1 = require("zod");
|
|
8
|
+
const express_1 = __importDefault(require("express"));
|
|
9
|
+
const cors_1 = __importDefault(require("cors"));
|
|
10
|
+
const pkce_challenge_1 = require("pkce-challenge");
|
|
11
|
+
const clientAuth_js_1 = require("../middleware/clientAuth.js");
|
|
12
|
+
const express_rate_limit_1 = require("express-rate-limit");
|
|
13
|
+
const allowedMethods_js_1 = require("../middleware/allowedMethods.js");
|
|
14
|
+
const errors_js_1 = require("../errors.js");
|
|
15
|
+
const TokenRequestSchema = zod_1.z.object({
|
|
16
|
+
grant_type: zod_1.z.string(),
|
|
17
|
+
});
|
|
18
|
+
const AuthorizationCodeGrantSchema = zod_1.z.object({
|
|
19
|
+
code: zod_1.z.string(),
|
|
20
|
+
code_verifier: zod_1.z.string(),
|
|
21
|
+
});
|
|
22
|
+
const RefreshTokenGrantSchema = zod_1.z.object({
|
|
23
|
+
refresh_token: zod_1.z.string(),
|
|
24
|
+
scope: zod_1.z.string().optional(),
|
|
25
|
+
});
|
|
26
|
+
function tokenHandler({ provider, rateLimit: rateLimitConfig }) {
|
|
27
|
+
// Nested router so we can configure middleware and restrict HTTP method
|
|
28
|
+
const router = express_1.default.Router();
|
|
29
|
+
// Configure CORS to allow any origin, to make accessible to web-based MCP clients
|
|
30
|
+
router.use((0, cors_1.default)());
|
|
31
|
+
router.use((0, allowedMethods_js_1.allowedMethods)(["POST"]));
|
|
32
|
+
router.use(express_1.default.urlencoded({ extended: false }));
|
|
33
|
+
// Apply rate limiting unless explicitly disabled
|
|
34
|
+
if (rateLimitConfig !== false) {
|
|
35
|
+
router.use((0, express_rate_limit_1.rateLimit)({
|
|
36
|
+
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
37
|
+
max: 50, // 50 requests per windowMs
|
|
38
|
+
standardHeaders: true,
|
|
39
|
+
legacyHeaders: false,
|
|
40
|
+
message: new errors_js_1.TooManyRequestsError('You have exceeded the rate limit for token requests').toResponseObject(),
|
|
41
|
+
...rateLimitConfig
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
// Authenticate and extract client details
|
|
45
|
+
router.use((0, clientAuth_js_1.authenticateClient)({ clientsStore: provider.clientsStore }));
|
|
46
|
+
router.post("/", async (req, res) => {
|
|
47
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
48
|
+
try {
|
|
49
|
+
const parseResult = TokenRequestSchema.safeParse(req.body);
|
|
50
|
+
if (!parseResult.success) {
|
|
51
|
+
throw new errors_js_1.InvalidRequestError(parseResult.error.message);
|
|
52
|
+
}
|
|
53
|
+
const { grant_type } = parseResult.data;
|
|
54
|
+
const client = req.client;
|
|
55
|
+
if (!client) {
|
|
56
|
+
// This should never happen
|
|
57
|
+
console.error("Missing client information after authentication");
|
|
58
|
+
throw new errors_js_1.ServerError("Internal Server Error");
|
|
59
|
+
}
|
|
60
|
+
switch (grant_type) {
|
|
61
|
+
case "authorization_code": {
|
|
62
|
+
const parseResult = AuthorizationCodeGrantSchema.safeParse(req.body);
|
|
63
|
+
if (!parseResult.success) {
|
|
64
|
+
throw new errors_js_1.InvalidRequestError(parseResult.error.message);
|
|
65
|
+
}
|
|
66
|
+
const { code, code_verifier } = parseResult.data;
|
|
67
|
+
// Verify PKCE challenge
|
|
68
|
+
const codeChallenge = await provider.challengeForAuthorizationCode(client, code);
|
|
69
|
+
if (!(await (0, pkce_challenge_1.verifyChallenge)(code_verifier, codeChallenge))) {
|
|
70
|
+
throw new errors_js_1.InvalidGrantError("code_verifier does not match the challenge");
|
|
71
|
+
}
|
|
72
|
+
const tokens = await provider.exchangeAuthorizationCode(client, code);
|
|
73
|
+
res.status(200).json(tokens);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
case "refresh_token": {
|
|
77
|
+
const parseResult = RefreshTokenGrantSchema.safeParse(req.body);
|
|
78
|
+
if (!parseResult.success) {
|
|
79
|
+
throw new errors_js_1.InvalidRequestError(parseResult.error.message);
|
|
80
|
+
}
|
|
81
|
+
const { refresh_token, scope } = parseResult.data;
|
|
82
|
+
const scopes = scope === null || scope === void 0 ? void 0 : scope.split(" ");
|
|
83
|
+
const tokens = await provider.exchangeRefreshToken(client, refresh_token, scopes);
|
|
84
|
+
res.status(200).json(tokens);
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
// Not supported right now
|
|
88
|
+
//case "client_credentials":
|
|
89
|
+
default:
|
|
90
|
+
throw new errors_js_1.UnsupportedGrantTypeError("The grant type is not supported by this authorization server.");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
if (error instanceof errors_js_1.OAuthError) {
|
|
95
|
+
const status = error instanceof errors_js_1.ServerError ? 500 : 400;
|
|
96
|
+
res.status(status).json(error.toResponseObject());
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
console.error("Unexpected error exchanging token:", error);
|
|
100
|
+
const serverError = new errors_js_1.ServerError("Internal Server Error");
|
|
101
|
+
res.status(500).json(serverError.toResponseObject());
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
return router;
|
|
106
|
+
}
|
|
107
|
+
//# 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,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.allowedMethods = allowedMethods;
|
|
4
|
+
const errors_js_1 = require("../errors.js");
|
|
5
|
+
/**
|
|
6
|
+
* Middleware to handle unsupported HTTP methods with a 405 Method Not Allowed response.
|
|
7
|
+
*
|
|
8
|
+
* @param allowedMethods Array of allowed HTTP methods for this endpoint (e.g., ['GET', 'POST'])
|
|
9
|
+
* @returns Express middleware that returns a 405 error if method not in allowed list
|
|
10
|
+
*/
|
|
11
|
+
function allowedMethods(allowedMethods) {
|
|
12
|
+
return (req, res, next) => {
|
|
13
|
+
if (allowedMethods.includes(req.method)) {
|
|
14
|
+
next();
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const error = new errors_js_1.MethodNotAllowedError(`The method ${req.method} is not allowed for this endpoint`);
|
|
18
|
+
res.status(405)
|
|
19
|
+
.set('Allow', allowedMethods.join(', '))
|
|
20
|
+
.json(error.toResponseObject());
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=allowedMethods.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allowedMethods.js","sourceRoot":"","sources":["../../../../../src/server/auth/middleware/allowedMethods.ts"],"names":[],"mappings":";;AASA,wCAYC;AApBD,4CAAqD;AAErD;;;;;GAKG;AACH,SAAgB,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,iCAAqB,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,CA8ChH"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requireBearerAuth = requireBearerAuth;
|
|
4
|
+
const errors_js_1 = require("../errors.js");
|
|
5
|
+
/**
|
|
6
|
+
* Middleware that requires a valid Bearer token in the Authorization header.
|
|
7
|
+
*
|
|
8
|
+
* This will validate the token with the auth provider and add the resulting auth info to the request object.
|
|
9
|
+
*/
|
|
10
|
+
function requireBearerAuth({ provider, requiredScopes = [] }) {
|
|
11
|
+
return async (req, res, next) => {
|
|
12
|
+
try {
|
|
13
|
+
const authHeader = req.headers.authorization;
|
|
14
|
+
if (!authHeader) {
|
|
15
|
+
throw new errors_js_1.InvalidTokenError("Missing Authorization header");
|
|
16
|
+
}
|
|
17
|
+
const [type, token] = authHeader.split(' ');
|
|
18
|
+
if (type.toLowerCase() !== 'bearer' || !token) {
|
|
19
|
+
throw new errors_js_1.InvalidTokenError("Invalid Authorization header format, expected 'Bearer TOKEN'");
|
|
20
|
+
}
|
|
21
|
+
const authInfo = await provider.verifyAccessToken(token);
|
|
22
|
+
// Check if token has the required scopes (if any)
|
|
23
|
+
if (requiredScopes.length > 0) {
|
|
24
|
+
const hasAllScopes = requiredScopes.every(scope => authInfo.scopes.includes(scope));
|
|
25
|
+
if (!hasAllScopes) {
|
|
26
|
+
throw new errors_js_1.InsufficientScopeError("Insufficient scope");
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
req.auth = authInfo;
|
|
30
|
+
next();
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
if (error instanceof errors_js_1.InvalidTokenError) {
|
|
34
|
+
res.set("WWW-Authenticate", `Bearer error="${error.errorCode}", error_description="${error.message}"`);
|
|
35
|
+
res.status(401).json(error.toResponseObject());
|
|
36
|
+
}
|
|
37
|
+
else if (error instanceof errors_js_1.InsufficientScopeError) {
|
|
38
|
+
res.set("WWW-Authenticate", `Bearer error="${error.errorCode}", error_description="${error.message}"`);
|
|
39
|
+
res.status(403).json(error.toResponseObject());
|
|
40
|
+
}
|
|
41
|
+
else if (error instanceof errors_js_1.ServerError) {
|
|
42
|
+
res.status(500).json(error.toResponseObject());
|
|
43
|
+
}
|
|
44
|
+
else if (error instanceof errors_js_1.OAuthError) {
|
|
45
|
+
res.status(400).json(error.toResponseObject());
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
console.error("Unexpected error authenticating bearer token:", error);
|
|
49
|
+
const serverError = new errors_js_1.ServerError("Internal Server Error");
|
|
50
|
+
res.status(500).json(serverError.toResponseObject());
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=bearerAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bearerAuth.js","sourceRoot":"","sources":["../../../../../src/server/auth/middleware/bearerAuth.ts"],"names":[],"mappings":";;AA+BA,8CA8CC;AA5ED,4CAAkG;AAyBlG;;;;GAIG;AACH,SAAgB,iBAAiB,CAAC,EAAE,QAAQ,EAAE,cAAc,GAAG,EAAE,EAA+B;IAC9F,OAAO,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC9B,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;YAC7C,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,6BAAiB,CAAC,8BAA8B,CAAC,CAAC;YAC9D,CAAC;YAED,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC5C,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;gBAC9C,MAAM,IAAI,6BAAiB,CAAC,8DAA8D,CAAC,CAAC;YAC9F,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;YAEzD,kDAAkD;YAClD,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,MAAM,YAAY,GAAG,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAChD,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAChC,CAAC;gBAEF,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,MAAM,IAAI,kCAAsB,CAAC,oBAAoB,CAAC,CAAC;gBACzD,CAAC;YACH,CAAC;YAED,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAC;YACpB,IAAI,EAAE,CAAC;QACT,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,6BAAiB,EAAE,CAAC;gBACvC,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,iBAAiB,KAAK,CAAC,SAAS,yBAAyB,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC;gBACvG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC;YACjD,CAAC;iBAAM,IAAI,KAAK,YAAY,kCAAsB,EAAE,CAAC;gBACnD,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,iBAAiB,KAAK,CAAC,SAAS,yBAAyB,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC;gBACvG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC;YACjD,CAAC;iBAAM,IAAI,KAAK,YAAY,uBAAW,EAAE,CAAC;gBACxC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC;YACjD,CAAC;iBAAM,IAAI,KAAK,YAAY,sBAAU,EAAE,CAAC;gBACvC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC;YACjD,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,+CAA+C,EAAE,KAAK,CAAC,CAAC;gBACtE,MAAM,WAAW,GAAG,IAAI,uBAAW,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,CAAC;AACJ,CAAC"}
|
|
@@ -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,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.authenticateClient = authenticateClient;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const errors_js_1 = require("../errors.js");
|
|
6
|
+
const ClientAuthenticatedRequestSchema = zod_1.z.object({
|
|
7
|
+
client_id: zod_1.z.string(),
|
|
8
|
+
client_secret: zod_1.z.string().optional(),
|
|
9
|
+
});
|
|
10
|
+
function authenticateClient({ clientsStore }) {
|
|
11
|
+
return async (req, res, next) => {
|
|
12
|
+
try {
|
|
13
|
+
const result = ClientAuthenticatedRequestSchema.safeParse(req.body);
|
|
14
|
+
if (!result.success) {
|
|
15
|
+
throw new errors_js_1.InvalidRequestError(String(result.error));
|
|
16
|
+
}
|
|
17
|
+
const { client_id, client_secret } = result.data;
|
|
18
|
+
const client = await clientsStore.getClient(client_id);
|
|
19
|
+
if (!client) {
|
|
20
|
+
throw new errors_js_1.InvalidClientError("Invalid client_id");
|
|
21
|
+
}
|
|
22
|
+
// If client has a secret, validate it
|
|
23
|
+
if (client.client_secret) {
|
|
24
|
+
// Check if client_secret is required but not provided
|
|
25
|
+
if (!client_secret) {
|
|
26
|
+
throw new errors_js_1.InvalidClientError("Client secret is required");
|
|
27
|
+
}
|
|
28
|
+
// Check if client_secret matches
|
|
29
|
+
if (client.client_secret !== client_secret) {
|
|
30
|
+
throw new errors_js_1.InvalidClientError("Invalid client_secret");
|
|
31
|
+
}
|
|
32
|
+
// Check if client_secret has expired
|
|
33
|
+
if (client.client_secret_expires_at && client.client_secret_expires_at < Math.floor(Date.now() / 1000)) {
|
|
34
|
+
throw new errors_js_1.InvalidClientError("Client secret has expired");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
req.client = client;
|
|
38
|
+
next();
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (error instanceof errors_js_1.OAuthError) {
|
|
42
|
+
const status = error instanceof errors_js_1.ServerError ? 500 : 400;
|
|
43
|
+
res.status(status).json(error.toResponseObject());
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
console.error("Unexpected error authenticating client:", error);
|
|
47
|
+
const serverError = new errors_js_1.ServerError("Internal Server Error");
|
|
48
|
+
res.status(500).json(serverError.toResponseObject());
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=clientAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clientAuth.js","sourceRoot":"","sources":["../../../../../src/server/auth/middleware/clientAuth.ts"],"names":[],"mappings":";;AA2BA,gDA6CC;AAxED,6BAAwB;AAIxB,4CAAgG;AAShG,MAAM,gCAAgC,GAAG,OAAC,CAAC,MAAM,CAAC;IAChD,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE;IACrB,aAAa,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAC;AAWH,SAAgB,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,+BAAmB,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,8BAAkB,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,8BAAkB,CAAC,2BAA2B,CAAC,CAAC;gBAC5D,CAAC;gBAED,iCAAiC;gBACjC,IAAI,MAAM,CAAC,aAAa,KAAK,aAAa,EAAE,CAAC;oBAC3C,MAAM,IAAI,8BAAkB,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,8BAAkB,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,sBAAU,EAAE,CAAC;gBAChC,MAAM,MAAM,GAAG,KAAK,YAAY,uBAAW,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,uBAAW,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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.mcpAuthRouter = mcpAuthRouter;
|
|
7
|
+
const express_1 = __importDefault(require("express"));
|
|
8
|
+
const register_js_1 = require("./handlers/register.js");
|
|
9
|
+
const token_js_1 = require("./handlers/token.js");
|
|
10
|
+
const authorize_js_1 = require("./handlers/authorize.js");
|
|
11
|
+
const revoke_js_1 = require("./handlers/revoke.js");
|
|
12
|
+
const metadata_js_1 = require("./handlers/metadata.js");
|
|
13
|
+
/**
|
|
14
|
+
* 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.
|
|
15
|
+
*
|
|
16
|
+
* By default, rate limiting is applied to all endpoints to prevent abuse.
|
|
17
|
+
*
|
|
18
|
+
* This router MUST be installed at the application root, like so:
|
|
19
|
+
*
|
|
20
|
+
* const app = express();
|
|
21
|
+
* app.use(mcpAuthRouter(...));
|
|
22
|
+
*/
|
|
23
|
+
function mcpAuthRouter(options) {
|
|
24
|
+
var _a;
|
|
25
|
+
const issuer = options.issuerUrl;
|
|
26
|
+
// Technically RFC 8414 does not permit a localhost HTTPS exemption, but this will be necessary for ease of testing
|
|
27
|
+
if (issuer.protocol !== "https:" && issuer.hostname !== "localhost" && issuer.hostname !== "127.0.0.1") {
|
|
28
|
+
throw new Error("Issuer URL must be HTTPS");
|
|
29
|
+
}
|
|
30
|
+
if (issuer.hash) {
|
|
31
|
+
throw new Error("Issuer URL must not have a fragment");
|
|
32
|
+
}
|
|
33
|
+
if (issuer.search) {
|
|
34
|
+
throw new Error("Issuer URL must not have a query string");
|
|
35
|
+
}
|
|
36
|
+
const authorization_endpoint = "/authorize";
|
|
37
|
+
const token_endpoint = "/token";
|
|
38
|
+
const registration_endpoint = options.provider.clientsStore.registerClient ? "/register" : undefined;
|
|
39
|
+
const revocation_endpoint = options.provider.revokeToken ? "/revoke" : undefined;
|
|
40
|
+
const metadata = {
|
|
41
|
+
issuer: issuer.href,
|
|
42
|
+
service_documentation: (_a = options.serviceDocumentationUrl) === null || _a === void 0 ? void 0 : _a.href,
|
|
43
|
+
authorization_endpoint: new URL(authorization_endpoint, issuer).href,
|
|
44
|
+
response_types_supported: ["code"],
|
|
45
|
+
code_challenge_methods_supported: ["S256"],
|
|
46
|
+
token_endpoint: new URL(token_endpoint, issuer).href,
|
|
47
|
+
token_endpoint_auth_methods_supported: ["client_secret_post"],
|
|
48
|
+
grant_types_supported: ["authorization_code", "refresh_token"],
|
|
49
|
+
revocation_endpoint: revocation_endpoint ? new URL(revocation_endpoint, issuer).href : undefined,
|
|
50
|
+
revocation_endpoint_auth_methods_supported: revocation_endpoint ? ["client_secret_post"] : undefined,
|
|
51
|
+
registration_endpoint: registration_endpoint ? new URL(registration_endpoint, issuer).href : undefined,
|
|
52
|
+
};
|
|
53
|
+
const router = express_1.default.Router();
|
|
54
|
+
router.use(authorization_endpoint, (0, authorize_js_1.authorizationHandler)({ provider: options.provider, ...options.authorizationOptions }));
|
|
55
|
+
router.use(token_endpoint, (0, token_js_1.tokenHandler)({ provider: options.provider, ...options.tokenOptions }));
|
|
56
|
+
router.use("/.well-known/oauth-authorization-server", (0, metadata_js_1.metadataHandler)(metadata));
|
|
57
|
+
if (registration_endpoint) {
|
|
58
|
+
router.use(registration_endpoint, (0, register_js_1.clientRegistrationHandler)({
|
|
59
|
+
clientsStore: options.provider.clientsStore,
|
|
60
|
+
...options,
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
if (revocation_endpoint) {
|
|
64
|
+
router.use(revocation_endpoint, (0, revoke_js_1.revocationHandler)({ provider: options.provider, ...options.revocationOptions }));
|
|
65
|
+
}
|
|
66
|
+
return router;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=router.js.map
|