@rekog/mcp-nest 1.9.4 → 1.9.6
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/README.md +5 -1
- package/dist/mcp/decorators/prompt.decorator.d.ts +1 -2
- package/dist/mcp/decorators/prompt.decorator.d.ts.map +1 -1
- package/dist/mcp/decorators/prompt.decorator.js.map +1 -1
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +2 -2
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/interfaces/dynamic-prompt.interface.d.ts +11 -0
- package/dist/mcp/interfaces/dynamic-prompt.interface.d.ts.map +1 -0
- package/dist/mcp/interfaces/dynamic-prompt.interface.js +3 -0
- package/dist/mcp/interfaces/dynamic-prompt.interface.js.map +1 -0
- package/dist/mcp/interfaces/dynamic-resource.interface.d.ts +11 -0
- package/dist/mcp/interfaces/dynamic-resource.interface.d.ts.map +1 -0
- package/dist/mcp/interfaces/dynamic-resource.interface.js +3 -0
- package/dist/mcp/interfaces/dynamic-resource.interface.js.map +1 -0
- package/dist/mcp/interfaces/dynamic-tool.interface.js.map +1 -1
- package/dist/mcp/interfaces/index.d.ts +2 -0
- package/dist/mcp/interfaces/index.d.ts.map +1 -1
- package/dist/mcp/interfaces/index.js.map +1 -1
- package/dist/mcp/mcp.module.d.ts.map +1 -1
- package/dist/mcp/mcp.module.js +15 -11
- package/dist/mcp/mcp.module.js.map +1 -1
- package/dist/mcp/services/handlers/mcp-handler.base.d.ts +4 -4
- package/dist/mcp/services/handlers/mcp-handler.base.d.ts.map +1 -1
- package/dist/mcp/services/handlers/mcp-handler.base.js.map +1 -1
- package/dist/mcp/services/handlers/mcp-prompts.handler.d.ts +2 -2
- package/dist/mcp/services/handlers/mcp-prompts.handler.d.ts.map +1 -1
- package/dist/mcp/services/handlers/mcp-prompts.handler.js +13 -3
- package/dist/mcp/services/handlers/mcp-prompts.handler.js.map +1 -1
- package/dist/mcp/services/handlers/mcp-resources.handler.d.ts +2 -2
- package/dist/mcp/services/handlers/mcp-resources.handler.d.ts.map +1 -1
- package/dist/mcp/services/handlers/mcp-resources.handler.js +12 -2
- package/dist/mcp/services/handlers/mcp-resources.handler.js.map +1 -1
- package/dist/mcp/services/handlers/mcp-tools.handler.d.ts +2 -2
- package/dist/mcp/services/handlers/mcp-tools.handler.d.ts.map +1 -1
- package/dist/mcp/services/handlers/mcp-tools.handler.js +5 -5
- package/dist/mcp/services/handlers/mcp-tools.handler.js.map +1 -1
- package/dist/mcp/services/mcp-dynamic-registry.service.d.ts +26 -0
- package/dist/mcp/services/mcp-dynamic-registry.service.d.ts.map +1 -0
- package/dist/mcp/services/mcp-dynamic-registry.service.js +133 -0
- package/dist/mcp/services/mcp-dynamic-registry.service.js.map +1 -0
- package/dist/mcp/services/mcp-executor.service.d.ts +2 -2
- package/dist/mcp/services/mcp-executor.service.d.ts.map +1 -1
- package/dist/mcp/services/mcp-executor.service.js +2 -2
- package/dist/mcp/services/mcp-executor.service.js.map +1 -1
- package/dist/mcp/services/{mcp-registry.service.d.ts → mcp-registry-discovery.service.d.ts} +16 -15
- package/dist/mcp/services/mcp-registry-discovery.service.d.ts.map +1 -0
- package/dist/mcp/services/{mcp-registry.service.js → mcp-registry-discovery.service.js} +41 -25
- package/dist/mcp/services/mcp-registry-discovery.service.js.map +1 -0
- package/dist/mcp/services/mcp-sse.service.d.ts +2 -2
- package/dist/mcp/services/mcp-sse.service.d.ts.map +1 -1
- package/dist/mcp/services/mcp-sse.service.js +2 -2
- package/dist/mcp/services/mcp-sse.service.js.map +1 -1
- package/dist/mcp/services/mcp-streamable-http.service.d.ts +2 -2
- package/dist/mcp/services/mcp-streamable-http.service.d.ts.map +1 -1
- package/dist/mcp/services/mcp-streamable-http.service.js +2 -2
- package/dist/mcp/services/mcp-streamable-http.service.js.map +1 -1
- package/dist/mcp/services/tool-authorization.service.d.ts +4 -4
- package/dist/mcp/services/tool-authorization.service.d.ts.map +1 -1
- package/dist/mcp/services/tool-authorization.service.js.map +1 -1
- package/dist/mcp/transport/stdio.service.d.ts +2 -2
- package/dist/mcp/transport/stdio.service.d.ts.map +1 -1
- package/dist/mcp/transport/stdio.service.js +7 -7
- package/dist/mcp/transport/stdio.service.js.map +1 -1
- package/dist/mcp/utils/capabilities-builder.d.ts +2 -2
- package/dist/mcp/utils/capabilities-builder.d.ts.map +1 -1
- package/dist/mcp/utils/capabilities-builder.js.map +1 -1
- package/dist/mcp/utils/mcp-server.factory.d.ts +2 -2
- package/dist/mcp/utils/mcp-server.factory.d.ts.map +1 -1
- package/dist/mcp/utils/mcp-server.factory.js.map +1 -1
- package/package.json +9 -9
- package/src/mcp/decorators/prompt.decorator.ts +1 -1
- package/src/mcp/index.ts +2 -2
- package/src/mcp/interfaces/dynamic-prompt.interface.ts +20 -0
- package/src/mcp/interfaces/dynamic-resource.interface.ts +22 -0
- package/src/mcp/interfaces/dynamic-tool.interface.ts +2 -2
- package/src/mcp/interfaces/index.ts +10 -0
- package/src/mcp/mcp.module.ts +15 -11
- package/src/mcp/services/handlers/mcp-handler.base.ts +6 -3
- package/src/mcp/services/handlers/mcp-prompts.handler.ts +36 -4
- package/src/mcp/services/handlers/mcp-resources.handler.ts +24 -2
- package/src/mcp/services/handlers/mcp-tools.handler.ts +11 -8
- package/src/mcp/services/mcp-dynamic-registry.service.ts +236 -0
- package/src/mcp/services/mcp-executor.service.ts +2 -2
- package/src/mcp/services/{mcp-registry.service.spec.ts → mcp-registry-discovery.service.spec.ts} +18 -12
- package/src/mcp/services/{mcp-registry.service.ts → mcp-registry-discovery.service.ts} +77 -35
- package/src/mcp/services/mcp-sse.service.ts +2 -2
- package/src/mcp/services/mcp-streamable-http.service.ts +2 -2
- package/src/mcp/services/tool-authorization.service.ts +4 -4
- package/src/mcp/transport/stdio.service.ts +8 -8
- package/src/mcp/utils/capabilities-builder.ts +2 -2
- package/src/mcp/utils/mcp-server.factory.ts +2 -2
- package/dist/authz/services/jwt-token.service.spec.d.ts +0 -2
- package/dist/authz/services/jwt-token.service.spec.d.ts.map +0 -1
- package/dist/authz/services/jwt-token.service.spec.js +0 -86
- package/dist/authz/services/jwt-token.service.spec.js.map +0 -1
- package/dist/authz/stores/memory-store.service.spec.d.ts +0 -2
- package/dist/authz/stores/memory-store.service.spec.d.ts.map +0 -1
- package/dist/authz/stores/memory-store.service.spec.js +0 -382
- package/dist/authz/stores/memory-store.service.spec.js.map +0 -1
- package/dist/authz/stores/typeorm/typeorm-store.service.spec.d.ts +0 -2
- package/dist/authz/stores/typeorm/typeorm-store.service.spec.d.ts.map +0 -1
- package/dist/authz/stores/typeorm/typeorm-store.service.spec.js +0 -340
- package/dist/authz/stores/typeorm/typeorm-store.service.spec.js.map +0 -1
- package/dist/mcp/services/mcp-registry.service.d.ts.map +0 -1
- package/dist/mcp/services/mcp-registry.service.js.map +0 -1
- package/dist/mcp/services/mcp-registry.service.spec.d.ts +0 -2
- package/dist/mcp/services/mcp-registry.service.spec.d.ts.map +0 -1
- package/dist/mcp/services/mcp-registry.service.spec.js +0 -245
- package/dist/mcp/services/mcp-registry.service.spec.js.map +0 -1
- package/dist/mcp/services/mcp-tool-builder.service.d.ts +0 -15
- package/dist/mcp/services/mcp-tool-builder.service.d.ts.map +0 -1
- package/dist/mcp/services/mcp-tool-builder.service.js +0 -70
- package/dist/mcp/services/mcp-tool-builder.service.js.map +0 -1
- package/dist/mcp/transport/custom-decorator.spec.d.ts +0 -2
- package/dist/mcp/transport/custom-decorator.spec.d.ts.map +0 -1
- package/dist/mcp/transport/custom-decorator.spec.js +0 -34
- package/dist/mcp/transport/custom-decorator.spec.js.map +0 -1
- package/dist/mcp/utils/mcp-logger.factory.spec.d.ts +0 -2
- package/dist/mcp/utils/mcp-logger.factory.spec.d.ts.map +0 -1
- package/dist/mcp/utils/mcp-logger.factory.spec.js +0 -150
- package/dist/mcp/utils/mcp-logger.factory.spec.js.map +0 -1
- package/dist/mcp/utils/normalize-endpoint.spec.d.ts +0 -2
- package/dist/mcp/utils/normalize-endpoint.spec.d.ts.map +0 -1
- package/dist/mcp/utils/normalize-endpoint.spec.js +0 -40
- package/dist/mcp/utils/normalize-endpoint.spec.js.map +0 -1
- package/src/mcp/services/mcp-tool-builder.service.ts +0 -151
|
@@ -9,7 +9,7 @@ import { ContextIdFactory, ModuleRef } from '@nestjs/core';
|
|
|
9
9
|
import { McpTransportType } from '../interfaces';
|
|
10
10
|
import type { McpOptions } from '../interfaces';
|
|
11
11
|
import { McpExecutorService } from '../services/mcp-executor.service';
|
|
12
|
-
import {
|
|
12
|
+
import { McpRegistryDiscoveryService } from '../services/mcp-registry-discovery.service';
|
|
13
13
|
import { createMcpLogger } from '../utils/mcp-logger.factory';
|
|
14
14
|
import { createMcpServer } from '../utils/mcp-server.factory';
|
|
15
15
|
|
|
@@ -21,15 +21,17 @@ export class StdioService implements OnApplicationBootstrap {
|
|
|
21
21
|
@Inject('MCP_OPTIONS') private readonly options: McpOptions,
|
|
22
22
|
@Inject('MCP_MODULE_ID') private readonly mcpModuleId: string,
|
|
23
23
|
private readonly moduleRef: ModuleRef,
|
|
24
|
-
private readonly toolRegistry:
|
|
24
|
+
private readonly toolRegistry: McpRegistryDiscoveryService,
|
|
25
25
|
) {
|
|
26
26
|
this.logger = createMcpLogger(StdioService.name, this.options);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
async onApplicationBootstrap() {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
const transports = Array.isArray(this.options.transport)
|
|
31
|
+
? this.options.transport
|
|
32
|
+
: [this.options.transport];
|
|
33
|
+
if (!transports.includes(McpTransportType.STDIO)) return;
|
|
34
|
+
|
|
33
35
|
this.logger.log('Bootstrapping MCP STDIO...');
|
|
34
36
|
|
|
35
37
|
// Warn about tools with @ToolGuards() - they require HTTP context
|
|
@@ -40,9 +42,7 @@ export class StdioService implements OnApplicationBootstrap {
|
|
|
40
42
|
);
|
|
41
43
|
|
|
42
44
|
if (toolsWithGuards.length > 0) {
|
|
43
|
-
const toolNames = toolsWithGuards
|
|
44
|
-
.map((t) => t.metadata.name)
|
|
45
|
-
.join(', ');
|
|
45
|
+
const toolNames = toolsWithGuards.map((t) => t.metadata.name).join(', ');
|
|
46
46
|
this.logger.warn(
|
|
47
47
|
`@ToolGuards() are not supported with STDIO transport. ` +
|
|
48
48
|
`The following tools have guards configured and will be hidden: ${toolNames}. ` +
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ServerCapabilities } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { McpRegistryDiscoveryService } from '../services/mcp-registry-discovery.service';
|
|
3
3
|
import type { McpOptions } from '../interfaces';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -8,7 +8,7 @@ import type { McpOptions } from '../interfaces';
|
|
|
8
8
|
*/
|
|
9
9
|
export function buildMcpCapabilities(
|
|
10
10
|
mcpModuleId: string,
|
|
11
|
-
registry:
|
|
11
|
+
registry: McpRegistryDiscoveryService,
|
|
12
12
|
options: McpOptions,
|
|
13
13
|
): ServerCapabilities {
|
|
14
14
|
// Start with user-provided capabilities or empty object
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { McpOptions } from '../interfaces';
|
|
2
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import { buildMcpCapabilities } from './capabilities-builder';
|
|
4
|
-
import {
|
|
4
|
+
import { McpRegistryDiscoveryService } from '../services/mcp-registry-discovery.service';
|
|
5
5
|
import { Logger } from '@nestjs/common';
|
|
6
6
|
|
|
7
7
|
export function createMcpServer(
|
|
8
8
|
mcpModuleId: string,
|
|
9
|
-
registry:
|
|
9
|
+
registry: McpRegistryDiscoveryService,
|
|
10
10
|
options: McpOptions,
|
|
11
11
|
logger: Logger,
|
|
12
12
|
): McpServer {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"jwt-token.service.spec.d.ts","sourceRoot":"","sources":["../../../src/authz/services/jwt-token.service.spec.ts"],"names":[],"mappings":""}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
const testing_1 = require("@nestjs/testing");
|
|
37
|
-
const jwt = __importStar(require("jsonwebtoken"));
|
|
38
|
-
const jwt_token_service_1 = require("./jwt-token.service");
|
|
39
|
-
describe('JwtTokenService', () => {
|
|
40
|
-
const baseOptions = {
|
|
41
|
-
jwtSecret: 'a'.repeat(32),
|
|
42
|
-
jwtIssuer: 'http://localhost',
|
|
43
|
-
serverUrl: 'http://localhost',
|
|
44
|
-
jwtAccessTokenExpiresIn: '2h',
|
|
45
|
-
jwtRefreshTokenExpiresIn: '3d',
|
|
46
|
-
enableRefreshTokens: true,
|
|
47
|
-
};
|
|
48
|
-
let service;
|
|
49
|
-
beforeEach(async () => {
|
|
50
|
-
const module = await testing_1.Test.createTestingModule({
|
|
51
|
-
providers: [
|
|
52
|
-
jwt_token_service_1.JwtTokenService,
|
|
53
|
-
{
|
|
54
|
-
provide: 'OAUTH_MODULE_OPTIONS',
|
|
55
|
-
useValue: baseOptions,
|
|
56
|
-
},
|
|
57
|
-
],
|
|
58
|
-
}).compile();
|
|
59
|
-
service = module.get(jwt_token_service_1.JwtTokenService);
|
|
60
|
-
});
|
|
61
|
-
it('generates tokens with configured expirations', () => {
|
|
62
|
-
const tokens = service.generateTokenPair('user1', 'client1', '', 'resource1');
|
|
63
|
-
expect(tokens.refresh_token).toBeDefined();
|
|
64
|
-
const decoded = jwt.decode(tokens.access_token);
|
|
65
|
-
const decodedRefresh = jwt.decode(tokens.refresh_token);
|
|
66
|
-
expect(decoded.exp - decoded.iat).toBe(2 * 60 * 60);
|
|
67
|
-
expect(decodedRefresh.exp - decodedRefresh.iat).toBe(3 * 24 * 60 * 60);
|
|
68
|
-
expect(tokens.expires_in).toBe(2 * 60 * 60);
|
|
69
|
-
});
|
|
70
|
-
it('can disable refresh tokens', async () => {
|
|
71
|
-
const module = await testing_1.Test.createTestingModule({
|
|
72
|
-
providers: [
|
|
73
|
-
jwt_token_service_1.JwtTokenService,
|
|
74
|
-
{
|
|
75
|
-
provide: 'OAUTH_MODULE_OPTIONS',
|
|
76
|
-
useValue: { ...baseOptions, enableRefreshTokens: false },
|
|
77
|
-
},
|
|
78
|
-
],
|
|
79
|
-
}).compile();
|
|
80
|
-
const serviceNoRefresh = module.get(jwt_token_service_1.JwtTokenService);
|
|
81
|
-
const tokens = serviceNoRefresh.generateTokenPair('user1', 'client1', '', 'resource1');
|
|
82
|
-
expect(tokens.refresh_token).toBeUndefined();
|
|
83
|
-
expect(tokens.expires_in).toBe(2 * 60 * 60);
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
//# sourceMappingURL=jwt-token.service.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"jwt-token.service.spec.js","sourceRoot":"","sources":["../../../src/authz/services/jwt-token.service.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6CAAsD;AACtD,kDAAoC;AACpC,2DAAsD;AAEtD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,MAAM,WAAW,GAAG;QAClB,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,SAAS,EAAE,kBAAkB;QAC7B,SAAS,EAAE,kBAAkB;QAC7B,uBAAuB,EAAE,IAAI;QAC7B,wBAAwB,EAAE,IAAI;QAC9B,mBAAmB,EAAE,IAAI;KACnB,CAAC;IAET,IAAI,OAAwB,CAAC;IAE7B,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,MAAM,MAAM,GAAkB,MAAM,cAAI,CAAC,mBAAmB,CAAC;YAC3D,SAAS,EAAE;gBACT,mCAAe;gBACf;oBACE,OAAO,EAAE,sBAAsB;oBAC/B,QAAQ,EAAE,WAAW;iBACtB;aACF;SACF,CAAC,CAAC,OAAO,EAAE,CAAC;QAEb,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,mCAAe,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,MAAM,GAAG,OAAO,CAAC,iBAAiB,CACtC,OAAO,EACP,SAAS,EACT,EAAE,EACF,WAAW,CACZ,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAmB,CAAC;QAClE,MAAM,cAAc,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,aAAc,CAAmB,CAAC;QAC3E,MAAM,CAAC,OAAO,CAAC,GAAI,GAAG,OAAO,CAAC,GAAI,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;QACtD,MAAM,CAAC,cAAc,CAAC,GAAI,GAAG,cAAc,CAAC,GAAI,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;QACzE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;QAC1C,MAAM,MAAM,GAAkB,MAAM,cAAI,CAAC,mBAAmB,CAAC;YAC3D,SAAS,EAAE;gBACT,mCAAe;gBACf;oBACE,OAAO,EAAE,sBAAsB;oBAC/B,QAAQ,EAAE,EAAE,GAAG,WAAW,EAAE,mBAAmB,EAAE,KAAK,EAAE;iBACzD;aACF;SACF,CAAC,CAAC,OAAO,EAAE,CAAC;QAEb,MAAM,gBAAgB,GAAG,MAAM,CAAC,GAAG,CAAC,mCAAe,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,gBAAgB,CAAC,iBAAiB,CAC/C,OAAO,EACP,SAAS,EACT,EAAE,EACF,WAAW,CACZ,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,aAAa,EAAE,CAAC;QAC7C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { Test, TestingModule } from '@nestjs/testing';\nimport * as jwt from 'jsonwebtoken';\nimport { JwtTokenService } from './jwt-token.service';\n\ndescribe('JwtTokenService', () => {\n const baseOptions = {\n jwtSecret: 'a'.repeat(32),\n jwtIssuer: 'http://localhost',\n serverUrl: 'http://localhost',\n jwtAccessTokenExpiresIn: '2h',\n jwtRefreshTokenExpiresIn: '3d',\n enableRefreshTokens: true,\n } as any;\n\n let service: JwtTokenService;\n\n beforeEach(async () => {\n const module: TestingModule = await Test.createTestingModule({\n providers: [\n JwtTokenService,\n {\n provide: 'OAUTH_MODULE_OPTIONS',\n useValue: baseOptions,\n },\n ],\n }).compile();\n\n service = module.get(JwtTokenService);\n });\n\n it('generates tokens with configured expirations', () => {\n const tokens = service.generateTokenPair(\n 'user1',\n 'client1',\n '',\n 'resource1',\n );\n expect(tokens.refresh_token).toBeDefined();\n const decoded = jwt.decode(tokens.access_token) as jwt.JwtPayload;\n const decodedRefresh = jwt.decode(tokens.refresh_token!) as jwt.JwtPayload;\n expect(decoded.exp! - decoded.iat!).toBe(2 * 60 * 60);\n expect(decodedRefresh.exp! - decodedRefresh.iat!).toBe(3 * 24 * 60 * 60);\n expect(tokens.expires_in).toBe(2 * 60 * 60);\n });\n\n it('can disable refresh tokens', async () => {\n const module: TestingModule = await Test.createTestingModule({\n providers: [\n JwtTokenService,\n {\n provide: 'OAUTH_MODULE_OPTIONS',\n useValue: { ...baseOptions, enableRefreshTokens: false },\n },\n ],\n }).compile();\n\n const serviceNoRefresh = module.get(JwtTokenService);\n const tokens = serviceNoRefresh.generateTokenPair(\n 'user1',\n 'client1',\n '',\n 'resource1',\n );\n expect(tokens.refresh_token).toBeUndefined();\n expect(tokens.expires_in).toBe(2 * 60 * 60);\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"memory-store.service.spec.d.ts","sourceRoot":"","sources":["../../../src/authz/stores/memory-store.service.spec.ts"],"names":[],"mappings":""}
|
|
@@ -1,382 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const testing_1 = require("@nestjs/testing");
|
|
4
|
-
const memory_store_service_1 = require("./memory-store.service");
|
|
5
|
-
describe('MemoryStore', () => {
|
|
6
|
-
let service;
|
|
7
|
-
beforeEach(async () => {
|
|
8
|
-
const module = await testing_1.Test.createTestingModule({
|
|
9
|
-
providers: [memory_store_service_1.MemoryStore],
|
|
10
|
-
}).compile();
|
|
11
|
-
service = module.get(memory_store_service_1.MemoryStore);
|
|
12
|
-
});
|
|
13
|
-
it('should be defined', () => {
|
|
14
|
-
expect(service).toBeDefined();
|
|
15
|
-
});
|
|
16
|
-
describe('generateClientId', () => {
|
|
17
|
-
it('should generate consistent client IDs for identical objects', () => {
|
|
18
|
-
const client1 = {
|
|
19
|
-
client_name: 'MCP Inspector',
|
|
20
|
-
client_uri: 'https://github.com/modelcontextprotocol/inspector',
|
|
21
|
-
redirect_uris: ['http://localhost:6274/oauth/callback'],
|
|
22
|
-
token_endpoint_auth_method: 'none',
|
|
23
|
-
grant_types: ['authorization_code', 'refresh_token'],
|
|
24
|
-
response_types: ['code'],
|
|
25
|
-
};
|
|
26
|
-
const client2 = {
|
|
27
|
-
client_name: 'MCP Inspector',
|
|
28
|
-
client_uri: 'https://github.com/modelcontextprotocol/inspector',
|
|
29
|
-
redirect_uris: ['http://localhost:6274/oauth/callback'],
|
|
30
|
-
token_endpoint_auth_method: 'none',
|
|
31
|
-
grant_types: ['authorization_code', 'refresh_token'],
|
|
32
|
-
response_types: ['code'],
|
|
33
|
-
};
|
|
34
|
-
const id1 = service.generateClientId(client1);
|
|
35
|
-
const id2 = service.generateClientId(client2);
|
|
36
|
-
expect(id1).toBe(id2);
|
|
37
|
-
});
|
|
38
|
-
it('should generate consistent client IDs regardless of property order', () => {
|
|
39
|
-
const clientJson1 = `{
|
|
40
|
-
"client_name": "MCP Inspector",
|
|
41
|
-
"client_uri": "https://github.com/modelcontextprotocol/inspector",
|
|
42
|
-
"redirect_uris": ["http://localhost:6274/oauth/callback"],
|
|
43
|
-
"token_endpoint_auth_method": "none",
|
|
44
|
-
"grant_types": ["authorization_code", "refresh_token"],
|
|
45
|
-
"response_types": ["code"]
|
|
46
|
-
}`;
|
|
47
|
-
const clientJson2 = `{
|
|
48
|
-
"response_types": ["code"],
|
|
49
|
-
"grant_types": ["authorization_code", "refresh_token"],
|
|
50
|
-
"token_endpoint_auth_method": "none",
|
|
51
|
-
"redirect_uris": ["http://localhost:6274/oauth/callback"],
|
|
52
|
-
"client_uri": "https://github.com/modelcontextprotocol/inspector",
|
|
53
|
-
"client_name": "MCP Inspector"
|
|
54
|
-
}`;
|
|
55
|
-
const client1 = JSON.parse(clientJson1);
|
|
56
|
-
const client2 = JSON.parse(clientJson2);
|
|
57
|
-
const id1 = service.generateClientId(client1);
|
|
58
|
-
const id2 = service.generateClientId(client2);
|
|
59
|
-
expect(id1).toBe(id2);
|
|
60
|
-
});
|
|
61
|
-
it('should generate consistent client IDs regardless of array order', () => {
|
|
62
|
-
const clientJson1 = `{
|
|
63
|
-
"client_name": "MCP Inspector",
|
|
64
|
-
"client_uri": "https://github.com/modelcontextprotocol/inspector",
|
|
65
|
-
"redirect_uris": [
|
|
66
|
-
"http://localhost:6274/oauth/callback",
|
|
67
|
-
"http://localhost:8080/callback",
|
|
68
|
-
"http://127.0.0.1:3000/auth"
|
|
69
|
-
],
|
|
70
|
-
"token_endpoint_auth_method": "none",
|
|
71
|
-
"grant_types": [
|
|
72
|
-
"authorization_code",
|
|
73
|
-
"refresh_token",
|
|
74
|
-
"client_credentials"
|
|
75
|
-
],
|
|
76
|
-
"response_types": ["code", "token"]
|
|
77
|
-
}`;
|
|
78
|
-
const clientJson2 = `{
|
|
79
|
-
"client_name": "MCP Inspector",
|
|
80
|
-
"client_uri": "https://github.com/modelcontextprotocol/inspector",
|
|
81
|
-
"redirect_uris": [
|
|
82
|
-
"http://127.0.0.1:3000/auth",
|
|
83
|
-
"http://localhost:6274/oauth/callback",
|
|
84
|
-
"http://localhost:8080/callback"
|
|
85
|
-
],
|
|
86
|
-
"token_endpoint_auth_method": "none",
|
|
87
|
-
"grant_types": ["client_credentials", "authorization_code", "refresh_token"],
|
|
88
|
-
"response_types": ["token", "code"]
|
|
89
|
-
}`;
|
|
90
|
-
const client1 = JSON.parse(clientJson1);
|
|
91
|
-
const client2 = JSON.parse(clientJson2);
|
|
92
|
-
const id1 = service.generateClientId(client1);
|
|
93
|
-
const id2 = service.generateClientId(client2);
|
|
94
|
-
expect(id1).toBe(id2);
|
|
95
|
-
});
|
|
96
|
-
it('should generate consistent client IDs regardless of both property and array order', () => {
|
|
97
|
-
const clientJson1 = `{
|
|
98
|
-
"grant_types": ["refresh_token", "authorization_code"],
|
|
99
|
-
"client_name": "MCP Inspector",
|
|
100
|
-
"response_types": ["code"],
|
|
101
|
-
"redirect_uris": [
|
|
102
|
-
"http://localhost:8080/callback",
|
|
103
|
-
"http://localhost:6274/oauth/callback"
|
|
104
|
-
],
|
|
105
|
-
"token_endpoint_auth_method": "none",
|
|
106
|
-
"client_uri": "https://github.com/modelcontextprotocol/inspector"
|
|
107
|
-
}`;
|
|
108
|
-
const clientJson2 = `{
|
|
109
|
-
"client_uri": "https://github.com/modelcontextprotocol/inspector",
|
|
110
|
-
"token_endpoint_auth_method": "none",
|
|
111
|
-
"redirect_uris": [
|
|
112
|
-
"http://localhost:6274/oauth/callback",
|
|
113
|
-
"http://localhost:8080/callback"
|
|
114
|
-
],
|
|
115
|
-
"response_types": ["code"],
|
|
116
|
-
"client_name": "MCP Inspector",
|
|
117
|
-
"grant_types": ["authorization_code", "refresh_token"]
|
|
118
|
-
}`;
|
|
119
|
-
const client1 = JSON.parse(clientJson1);
|
|
120
|
-
const client2 = JSON.parse(clientJson2);
|
|
121
|
-
const id1 = service.generateClientId(client1);
|
|
122
|
-
const id2 = service.generateClientId(client2);
|
|
123
|
-
expect(id1).toBe(id2);
|
|
124
|
-
});
|
|
125
|
-
it('should generate different client IDs for different objects', () => {
|
|
126
|
-
const client1 = {
|
|
127
|
-
client_name: 'MCP Inspector',
|
|
128
|
-
client_uri: 'https://github.com/modelcontextprotocol/inspector',
|
|
129
|
-
redirect_uris: ['http://localhost:6274/oauth/callback'],
|
|
130
|
-
token_endpoint_auth_method: 'none',
|
|
131
|
-
grant_types: ['authorization_code', 'refresh_token'],
|
|
132
|
-
response_types: ['code'],
|
|
133
|
-
};
|
|
134
|
-
const client2 = {
|
|
135
|
-
client_name: 'Different App',
|
|
136
|
-
client_uri: 'https://github.com/modelcontextprotocol/inspector',
|
|
137
|
-
redirect_uris: ['http://localhost:6274/oauth/callback'],
|
|
138
|
-
token_endpoint_auth_method: 'none',
|
|
139
|
-
grant_types: ['authorization_code', 'refresh_token'],
|
|
140
|
-
response_types: ['code'],
|
|
141
|
-
};
|
|
142
|
-
const id1 = service.generateClientId(client1);
|
|
143
|
-
const id2 = service.generateClientId(client2);
|
|
144
|
-
expect(id1).not.toBe(id2);
|
|
145
|
-
});
|
|
146
|
-
it('should generate different client IDs when array contents differ', () => {
|
|
147
|
-
const client1 = {
|
|
148
|
-
client_name: 'MCP Inspector',
|
|
149
|
-
client_uri: 'https://github.com/modelcontextprotocol/inspector',
|
|
150
|
-
redirect_uris: ['http://localhost:6274/oauth/callback'],
|
|
151
|
-
token_endpoint_auth_method: 'none',
|
|
152
|
-
grant_types: ['authorization_code', 'refresh_token'],
|
|
153
|
-
response_types: ['code'],
|
|
154
|
-
};
|
|
155
|
-
const client2 = {
|
|
156
|
-
client_name: 'MCP Inspector',
|
|
157
|
-
client_uri: 'https://github.com/modelcontextprotocol/inspector',
|
|
158
|
-
redirect_uris: ['http://localhost:6274/oauth/callback'],
|
|
159
|
-
token_endpoint_auth_method: 'none',
|
|
160
|
-
grant_types: ['authorization_code'],
|
|
161
|
-
response_types: ['code'],
|
|
162
|
-
};
|
|
163
|
-
const id1 = service.generateClientId(client1);
|
|
164
|
-
const id2 = service.generateClientId(client2);
|
|
165
|
-
expect(id1).not.toBe(id2);
|
|
166
|
-
});
|
|
167
|
-
it('should include normalized client name in the generated ID', () => {
|
|
168
|
-
const client = {
|
|
169
|
-
client_name: 'MCP Inspector!@#',
|
|
170
|
-
client_uri: 'https://github.com/modelcontextprotocol/inspector',
|
|
171
|
-
redirect_uris: ['http://localhost:6274/oauth/callback'],
|
|
172
|
-
token_endpoint_auth_method: 'none',
|
|
173
|
-
grant_types: ['authorization_code', 'refresh_token'],
|
|
174
|
-
response_types: ['code'],
|
|
175
|
-
};
|
|
176
|
-
const clientId = service.generateClientId(client);
|
|
177
|
-
expect(clientId).toMatch(/^mcpinspector_[a-f0-9]{16}$/);
|
|
178
|
-
});
|
|
179
|
-
it('should generate IDs with consistent format', () => {
|
|
180
|
-
const client = {
|
|
181
|
-
client_name: 'Test App',
|
|
182
|
-
client_uri: 'https://example.com',
|
|
183
|
-
redirect_uris: ['http://localhost:3000/callback'],
|
|
184
|
-
token_endpoint_auth_method: 'none',
|
|
185
|
-
grant_types: ['authorization_code'],
|
|
186
|
-
response_types: ['code'],
|
|
187
|
-
};
|
|
188
|
-
const clientId = service.generateClientId(client);
|
|
189
|
-
expect(clientId).toMatch(/^[a-z0-9]+_[a-f0-9]{16}$/);
|
|
190
|
-
const clientId2 = service.generateClientId(client);
|
|
191
|
-
expect(clientId).toBe(clientId2);
|
|
192
|
-
});
|
|
193
|
-
});
|
|
194
|
-
describe('Client Management', () => {
|
|
195
|
-
const mockClient = {
|
|
196
|
-
client_id: 'test-client-id',
|
|
197
|
-
client_name: 'Test Client',
|
|
198
|
-
client_description: 'A test OAuth client',
|
|
199
|
-
logo_uri: 'https://example.com/logo.png',
|
|
200
|
-
client_uri: 'https://example.com',
|
|
201
|
-
developer_name: 'Test Developer',
|
|
202
|
-
developer_email: 'test@example.com',
|
|
203
|
-
redirect_uris: ['http://localhost:3000/callback'],
|
|
204
|
-
grant_types: ['authorization_code', 'refresh_token'],
|
|
205
|
-
response_types: ['code'],
|
|
206
|
-
token_endpoint_auth_method: 'none',
|
|
207
|
-
created_at: new Date(),
|
|
208
|
-
updated_at: new Date(),
|
|
209
|
-
};
|
|
210
|
-
describe('storeClient', () => {
|
|
211
|
-
it('should store a client and return it', async () => {
|
|
212
|
-
const result = await service.storeClient(mockClient);
|
|
213
|
-
expect(result).toEqual(mockClient);
|
|
214
|
-
});
|
|
215
|
-
it('should allow retrieving the stored client', async () => {
|
|
216
|
-
await service.storeClient(mockClient);
|
|
217
|
-
const retrieved = await service.getClient(mockClient.client_id);
|
|
218
|
-
expect(retrieved).toEqual(mockClient);
|
|
219
|
-
});
|
|
220
|
-
it('should overwrite existing client with same ID', async () => {
|
|
221
|
-
await service.storeClient(mockClient);
|
|
222
|
-
const updatedClient = { ...mockClient, client_name: 'Updated Client' };
|
|
223
|
-
await service.storeClient(updatedClient);
|
|
224
|
-
const retrieved = await service.getClient(mockClient.client_id);
|
|
225
|
-
expect(retrieved?.client_name).toBe('Updated Client');
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
describe('getClient', () => {
|
|
229
|
-
it('should return undefined for non-existent client', async () => {
|
|
230
|
-
const result = await service.getClient('non-existent-id');
|
|
231
|
-
expect(result).toBeUndefined();
|
|
232
|
-
});
|
|
233
|
-
it('should return the correct client when it exists', async () => {
|
|
234
|
-
await service.storeClient(mockClient);
|
|
235
|
-
const result = await service.getClient(mockClient.client_id);
|
|
236
|
-
expect(result).toEqual(mockClient);
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
describe('findClient', () => {
|
|
240
|
-
it('should return undefined for non-existent client name', async () => {
|
|
241
|
-
const result = await service.findClient('Non-existent Client');
|
|
242
|
-
expect(result).toBeUndefined();
|
|
243
|
-
});
|
|
244
|
-
it('should find client by exact name match', async () => {
|
|
245
|
-
await service.storeClient(mockClient);
|
|
246
|
-
const result = await service.findClient(mockClient.client_name);
|
|
247
|
-
expect(result).toEqual(mockClient);
|
|
248
|
-
});
|
|
249
|
-
it('should be case sensitive', async () => {
|
|
250
|
-
await service.storeClient(mockClient);
|
|
251
|
-
const result = await service.findClient(mockClient.client_name.toUpperCase());
|
|
252
|
-
expect(result).toBeUndefined();
|
|
253
|
-
});
|
|
254
|
-
it('should return first match when multiple clients exist', async () => {
|
|
255
|
-
const client1 = { ...mockClient, client_id: 'client-1' };
|
|
256
|
-
const client2 = {
|
|
257
|
-
...mockClient,
|
|
258
|
-
client_id: 'client-2',
|
|
259
|
-
client_name: 'Different Client',
|
|
260
|
-
};
|
|
261
|
-
await service.storeClient(client1);
|
|
262
|
-
await service.storeClient(client2);
|
|
263
|
-
const result = await service.findClient(client1.client_name);
|
|
264
|
-
expect(result).toEqual(client1);
|
|
265
|
-
});
|
|
266
|
-
});
|
|
267
|
-
});
|
|
268
|
-
describe('Authorization Code Management', () => {
|
|
269
|
-
const mockAuthCode = {
|
|
270
|
-
code: 'test-auth-code',
|
|
271
|
-
user_id: 'user-123',
|
|
272
|
-
client_id: 'client-123',
|
|
273
|
-
redirect_uri: 'http://localhost:3000/callback',
|
|
274
|
-
code_challenge: 'test-challenge',
|
|
275
|
-
code_challenge_method: 'S256',
|
|
276
|
-
expires_at: Date.now() + 600000,
|
|
277
|
-
};
|
|
278
|
-
describe('storeAuthCode', () => {
|
|
279
|
-
it('should store an authorization code', async () => {
|
|
280
|
-
await service.storeAuthCode(mockAuthCode);
|
|
281
|
-
const retrieved = await service.getAuthCode(mockAuthCode.code);
|
|
282
|
-
expect(retrieved).toEqual(mockAuthCode);
|
|
283
|
-
});
|
|
284
|
-
it('should overwrite existing code with same value', async () => {
|
|
285
|
-
await service.storeAuthCode(mockAuthCode);
|
|
286
|
-
const updatedCode = { ...mockAuthCode, user_id: 'updated-user' };
|
|
287
|
-
await service.storeAuthCode(updatedCode);
|
|
288
|
-
const retrieved = await service.getAuthCode(mockAuthCode.code);
|
|
289
|
-
expect(retrieved?.user_id).toBe('updated-user');
|
|
290
|
-
});
|
|
291
|
-
});
|
|
292
|
-
describe('getAuthCode', () => {
|
|
293
|
-
it('should return undefined for non-existent code', async () => {
|
|
294
|
-
const result = await service.getAuthCode('non-existent-code');
|
|
295
|
-
expect(result).toBeUndefined();
|
|
296
|
-
});
|
|
297
|
-
it('should return the correct authorization code when it exists', async () => {
|
|
298
|
-
await service.storeAuthCode(mockAuthCode);
|
|
299
|
-
const result = await service.getAuthCode(mockAuthCode.code);
|
|
300
|
-
expect(result).toEqual(mockAuthCode);
|
|
301
|
-
});
|
|
302
|
-
});
|
|
303
|
-
describe('removeAuthCode', () => {
|
|
304
|
-
it('should remove an authorization code', async () => {
|
|
305
|
-
await service.storeAuthCode(mockAuthCode);
|
|
306
|
-
await service.removeAuthCode(mockAuthCode.code);
|
|
307
|
-
const retrieved = await service.getAuthCode(mockAuthCode.code);
|
|
308
|
-
expect(retrieved).toBeUndefined();
|
|
309
|
-
});
|
|
310
|
-
it('should not throw when removing non-existent code', async () => {
|
|
311
|
-
await expect(service.removeAuthCode('non-existent-code')).resolves.toBeUndefined();
|
|
312
|
-
});
|
|
313
|
-
});
|
|
314
|
-
});
|
|
315
|
-
describe('OAuth Session Management', () => {
|
|
316
|
-
const mockSession = {
|
|
317
|
-
sessionId: 'session-123',
|
|
318
|
-
state: 'test-state',
|
|
319
|
-
clientId: 'client-123',
|
|
320
|
-
redirectUri: 'http://localhost:3000/callback',
|
|
321
|
-
codeChallenge: 'test-challenge',
|
|
322
|
-
codeChallengeMethod: 'S256',
|
|
323
|
-
oauthState: 'oauth-state-123',
|
|
324
|
-
resource: 'test-resource',
|
|
325
|
-
expiresAt: Date.now() + 3600000,
|
|
326
|
-
};
|
|
327
|
-
const expiredSession = {
|
|
328
|
-
...mockSession,
|
|
329
|
-
sessionId: 'expired-session',
|
|
330
|
-
expiresAt: Date.now() - 1000,
|
|
331
|
-
};
|
|
332
|
-
describe('storeOAuthSession', () => {
|
|
333
|
-
it('should store an OAuth session', async () => {
|
|
334
|
-
const sessionId = 'session-123';
|
|
335
|
-
await service.storeOAuthSession(sessionId, mockSession);
|
|
336
|
-
const retrieved = await service.getOAuthSession(sessionId);
|
|
337
|
-
expect(retrieved).toEqual(mockSession);
|
|
338
|
-
});
|
|
339
|
-
it('should overwrite existing session with same ID', async () => {
|
|
340
|
-
const sessionId = 'session-123';
|
|
341
|
-
await service.storeOAuthSession(sessionId, mockSession);
|
|
342
|
-
const updatedSession = { ...mockSession, state: 'updated-state' };
|
|
343
|
-
await service.storeOAuthSession(sessionId, updatedSession);
|
|
344
|
-
const retrieved = await service.getOAuthSession(sessionId);
|
|
345
|
-
expect(retrieved?.state).toBe('updated-state');
|
|
346
|
-
});
|
|
347
|
-
});
|
|
348
|
-
describe('getOAuthSession', () => {
|
|
349
|
-
it('should return undefined for non-existent session', async () => {
|
|
350
|
-
const result = await service.getOAuthSession('non-existent-session');
|
|
351
|
-
expect(result).toBeUndefined();
|
|
352
|
-
});
|
|
353
|
-
it('should return the correct OAuth session when it exists', async () => {
|
|
354
|
-
const sessionId = 'session-123';
|
|
355
|
-
await service.storeOAuthSession(sessionId, mockSession);
|
|
356
|
-
const result = await service.getOAuthSession(sessionId);
|
|
357
|
-
expect(result).toEqual(mockSession);
|
|
358
|
-
});
|
|
359
|
-
it('should return undefined and auto-remove expired sessions', async () => {
|
|
360
|
-
const sessionId = 'expired-session';
|
|
361
|
-
await service.storeOAuthSession(sessionId, expiredSession);
|
|
362
|
-
const result = await service.getOAuthSession(sessionId);
|
|
363
|
-
expect(result).toBeUndefined();
|
|
364
|
-
const result2 = await service.getOAuthSession(sessionId);
|
|
365
|
-
expect(result2).toBeUndefined();
|
|
366
|
-
});
|
|
367
|
-
});
|
|
368
|
-
describe('removeOAuthSession', () => {
|
|
369
|
-
it('should remove an OAuth session', async () => {
|
|
370
|
-
const sessionId = 'session-123';
|
|
371
|
-
await service.storeOAuthSession(sessionId, mockSession);
|
|
372
|
-
await service.removeOAuthSession(sessionId);
|
|
373
|
-
const retrieved = await service.getOAuthSession(sessionId);
|
|
374
|
-
expect(retrieved).toBeUndefined();
|
|
375
|
-
});
|
|
376
|
-
it('should not throw when removing non-existent session', async () => {
|
|
377
|
-
await expect(service.removeOAuthSession('non-existent-session')).resolves.toBeUndefined();
|
|
378
|
-
});
|
|
379
|
-
});
|
|
380
|
-
});
|
|
381
|
-
});
|
|
382
|
-
//# sourceMappingURL=memory-store.service.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"memory-store.service.spec.js","sourceRoot":"","sources":["../../../src/authz/stores/memory-store.service.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import { Test, TestingModule } from '@nestjs/testing';\nimport { MemoryStore } from './memory-store.service';\nimport { OAuthClient, AuthorizationCode } from './oauth-store.interface';\nimport { OAuthSession } from '../providers/oauth-provider.interface';\n\ndescribe('MemoryStore', () => {\n let service: MemoryStore;\n\n beforeEach(async () => {\n const module: TestingModule = await Test.createTestingModule({\n providers: [MemoryStore],\n }).compile();\n\n service = module.get<MemoryStore>(MemoryStore);\n });\n\n it('should be defined', () => {\n expect(service).toBeDefined();\n });\n\n describe('generateClientId', () => {\n it('should generate consistent client IDs for identical objects', () => {\n const client1: Partial<OAuthClient> = {\n client_name: 'MCP Inspector',\n client_uri: 'https://github.com/modelcontextprotocol/inspector',\n redirect_uris: ['http://localhost:6274/oauth/callback'],\n token_endpoint_auth_method: 'none',\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n };\n\n const client2: Partial<OAuthClient> = {\n client_name: 'MCP Inspector',\n client_uri: 'https://github.com/modelcontextprotocol/inspector',\n redirect_uris: ['http://localhost:6274/oauth/callback'],\n token_endpoint_auth_method: 'none',\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n };\n\n const id1 = service.generateClientId(client1 as OAuthClient);\n const id2 = service.generateClientId(client2 as OAuthClient);\n\n expect(id1).toBe(id2);\n });\n\n it('should generate consistent client IDs regardless of property order', () => {\n // First object with properties in one order\n const clientJson1 = `{\n \"client_name\": \"MCP Inspector\",\n \"client_uri\": \"https://github.com/modelcontextprotocol/inspector\",\n \"redirect_uris\": [\"http://localhost:6274/oauth/callback\"],\n \"token_endpoint_auth_method\": \"none\",\n \"grant_types\": [\"authorization_code\", \"refresh_token\"],\n \"response_types\": [\"code\"]\n }`;\n\n // Second object with properties in different order\n const clientJson2 = `{\n \"response_types\": [\"code\"],\n \"grant_types\": [\"authorization_code\", \"refresh_token\"],\n \"token_endpoint_auth_method\": \"none\",\n \"redirect_uris\": [\"http://localhost:6274/oauth/callback\"],\n \"client_uri\": \"https://github.com/modelcontextprotocol/inspector\",\n \"client_name\": \"MCP Inspector\"\n }`;\n\n const client1 = JSON.parse(clientJson1) as OAuthClient;\n const client2 = JSON.parse(clientJson2) as OAuthClient;\n\n const id1 = service.generateClientId(client1);\n const id2 = service.generateClientId(client2);\n\n expect(id1).toBe(id2);\n });\n\n it('should generate consistent client IDs regardless of array order', () => {\n // First object with arrays in one order\n const clientJson1 = `{\n \"client_name\": \"MCP Inspector\",\n \"client_uri\": \"https://github.com/modelcontextprotocol/inspector\",\n \"redirect_uris\": [\n \"http://localhost:6274/oauth/callback\",\n \"http://localhost:8080/callback\",\n \"http://127.0.0.1:3000/auth\"\n ],\n \"token_endpoint_auth_method\": \"none\",\n \"grant_types\": [\n \"authorization_code\",\n \"refresh_token\",\n \"client_credentials\"\n ],\n \"response_types\": [\"code\", \"token\"]\n }`;\n\n // Second object with arrays in different order\n const clientJson2 = `{\n \"client_name\": \"MCP Inspector\",\n \"client_uri\": \"https://github.com/modelcontextprotocol/inspector\",\n \"redirect_uris\": [\n \"http://127.0.0.1:3000/auth\",\n \"http://localhost:6274/oauth/callback\",\n \"http://localhost:8080/callback\"\n ],\n \"token_endpoint_auth_method\": \"none\",\n \"grant_types\": [\"client_credentials\", \"authorization_code\", \"refresh_token\"],\n \"response_types\": [\"token\", \"code\"]\n }`;\n\n const client1 = JSON.parse(clientJson1) as OAuthClient;\n const client2 = JSON.parse(clientJson2) as OAuthClient;\n\n const id1 = service.generateClientId(client1);\n const id2 = service.generateClientId(client2);\n\n expect(id1).toBe(id2);\n });\n\n it('should generate consistent client IDs regardless of both property and array order', () => {\n // First object with mixed ordering\n const clientJson1 = `{\n \"grant_types\": [\"refresh_token\", \"authorization_code\"],\n \"client_name\": \"MCP Inspector\",\n \"response_types\": [\"code\"],\n \"redirect_uris\": [\n \"http://localhost:8080/callback\",\n \"http://localhost:6274/oauth/callback\"\n ],\n \"token_endpoint_auth_method\": \"none\",\n \"client_uri\": \"https://github.com/modelcontextprotocol/inspector\"\n }`;\n\n // Second object with different mixed ordering\n const clientJson2 = `{\n \"client_uri\": \"https://github.com/modelcontextprotocol/inspector\",\n \"token_endpoint_auth_method\": \"none\",\n \"redirect_uris\": [\n \"http://localhost:6274/oauth/callback\",\n \"http://localhost:8080/callback\"\n ],\n \"response_types\": [\"code\"],\n \"client_name\": \"MCP Inspector\",\n \"grant_types\": [\"authorization_code\", \"refresh_token\"]\n }`;\n\n const client1 = JSON.parse(clientJson1) as OAuthClient;\n const client2 = JSON.parse(clientJson2) as OAuthClient;\n\n const id1 = service.generateClientId(client1);\n const id2 = service.generateClientId(client2);\n\n expect(id1).toBe(id2);\n });\n\n it('should generate different client IDs for different objects', () => {\n const client1: Partial<OAuthClient> = {\n client_name: 'MCP Inspector',\n client_uri: 'https://github.com/modelcontextprotocol/inspector',\n redirect_uris: ['http://localhost:6274/oauth/callback'],\n token_endpoint_auth_method: 'none',\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n };\n\n const client2: Partial<OAuthClient> = {\n client_name: 'Different App', // Changed client name\n client_uri: 'https://github.com/modelcontextprotocol/inspector',\n redirect_uris: ['http://localhost:6274/oauth/callback'],\n token_endpoint_auth_method: 'none',\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n };\n\n const id1 = service.generateClientId(client1 as OAuthClient);\n const id2 = service.generateClientId(client2 as OAuthClient);\n\n expect(id1).not.toBe(id2);\n });\n\n it('should generate different client IDs when array contents differ', () => {\n const client1: Partial<OAuthClient> = {\n client_name: 'MCP Inspector',\n client_uri: 'https://github.com/modelcontextprotocol/inspector',\n redirect_uris: ['http://localhost:6274/oauth/callback'],\n token_endpoint_auth_method: 'none',\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n };\n\n const client2: Partial<OAuthClient> = {\n client_name: 'MCP Inspector',\n client_uri: 'https://github.com/modelcontextprotocol/inspector',\n redirect_uris: ['http://localhost:6274/oauth/callback'],\n token_endpoint_auth_method: 'none',\n grant_types: ['authorization_code'], // Removed 'refresh_token'\n response_types: ['code'],\n };\n\n const id1 = service.generateClientId(client1 as OAuthClient);\n const id2 = service.generateClientId(client2 as OAuthClient);\n\n expect(id1).not.toBe(id2);\n });\n\n it('should include normalized client name in the generated ID', () => {\n const client: Partial<OAuthClient> = {\n client_name: 'MCP Inspector!@#', // Special characters\n client_uri: 'https://github.com/modelcontextprotocol/inspector',\n redirect_uris: ['http://localhost:6274/oauth/callback'],\n token_endpoint_auth_method: 'none',\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n };\n\n const clientId = service.generateClientId(client as OAuthClient);\n\n // Should start with normalized name (lowercase, alphanumeric only)\n expect(clientId).toMatch(/^mcpinspector_[a-f0-9]{16}$/);\n });\n\n it('should generate IDs with consistent format', () => {\n const client: Partial<OAuthClient> = {\n client_name: 'Test App',\n client_uri: 'https://example.com',\n redirect_uris: ['http://localhost:3000/callback'],\n token_endpoint_auth_method: 'none',\n grant_types: ['authorization_code'],\n response_types: ['code'],\n };\n\n const clientId = service.generateClientId(client as OAuthClient);\n\n // Should match pattern: normalizedname_16hexchars\n expect(clientId).toMatch(/^[a-z0-9]+_[a-f0-9]{16}$/);\n\n // Should be consistent across multiple calls\n const clientId2 = service.generateClientId(client as OAuthClient);\n expect(clientId).toBe(clientId2);\n });\n });\n\n describe('Client Management', () => {\n const mockClient: OAuthClient = {\n client_id: 'test-client-id',\n client_name: 'Test Client',\n client_description: 'A test OAuth client',\n logo_uri: 'https://example.com/logo.png',\n client_uri: 'https://example.com',\n developer_name: 'Test Developer',\n developer_email: 'test@example.com',\n redirect_uris: ['http://localhost:3000/callback'],\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n token_endpoint_auth_method: 'none',\n created_at: new Date(),\n updated_at: new Date(),\n };\n\n describe('storeClient', () => {\n it('should store a client and return it', async () => {\n const result = await service.storeClient(mockClient);\n expect(result).toEqual(mockClient);\n });\n\n it('should allow retrieving the stored client', async () => {\n await service.storeClient(mockClient);\n const retrieved = await service.getClient(mockClient.client_id);\n expect(retrieved).toEqual(mockClient);\n });\n\n it('should overwrite existing client with same ID', async () => {\n await service.storeClient(mockClient);\n\n const updatedClient = { ...mockClient, client_name: 'Updated Client' };\n await service.storeClient(updatedClient);\n\n const retrieved = await service.getClient(mockClient.client_id);\n expect(retrieved?.client_name).toBe('Updated Client');\n });\n });\n\n describe('getClient', () => {\n it('should return undefined for non-existent client', async () => {\n const result = await service.getClient('non-existent-id');\n expect(result).toBeUndefined();\n });\n\n it('should return the correct client when it exists', async () => {\n await service.storeClient(mockClient);\n const result = await service.getClient(mockClient.client_id);\n expect(result).toEqual(mockClient);\n });\n });\n\n describe('findClient', () => {\n it('should return undefined for non-existent client name', async () => {\n const result = await service.findClient('Non-existent Client');\n expect(result).toBeUndefined();\n });\n\n it('should find client by exact name match', async () => {\n await service.storeClient(mockClient);\n const result = await service.findClient(mockClient.client_name);\n expect(result).toEqual(mockClient);\n });\n\n it('should be case sensitive', async () => {\n await service.storeClient(mockClient);\n const result = await service.findClient(\n mockClient.client_name.toUpperCase(),\n );\n expect(result).toBeUndefined();\n });\n\n it('should return first match when multiple clients exist', async () => {\n const client1 = { ...mockClient, client_id: 'client-1' };\n const client2 = {\n ...mockClient,\n client_id: 'client-2',\n client_name: 'Different Client',\n };\n\n await service.storeClient(client1);\n await service.storeClient(client2);\n\n const result = await service.findClient(client1.client_name);\n expect(result).toEqual(client1);\n });\n });\n });\n\n describe('Authorization Code Management', () => {\n const mockAuthCode: AuthorizationCode = {\n code: 'test-auth-code',\n user_id: 'user-123',\n client_id: 'client-123',\n redirect_uri: 'http://localhost:3000/callback',\n code_challenge: 'test-challenge',\n code_challenge_method: 'S256',\n expires_at: Date.now() + 600000, // 10 minutes from now\n };\n\n describe('storeAuthCode', () => {\n it('should store an authorization code', async () => {\n await service.storeAuthCode(mockAuthCode);\n const retrieved = await service.getAuthCode(mockAuthCode.code);\n expect(retrieved).toEqual(mockAuthCode);\n });\n\n it('should overwrite existing code with same value', async () => {\n await service.storeAuthCode(mockAuthCode);\n\n const updatedCode = { ...mockAuthCode, user_id: 'updated-user' };\n await service.storeAuthCode(updatedCode);\n\n const retrieved = await service.getAuthCode(mockAuthCode.code);\n expect(retrieved?.user_id).toBe('updated-user');\n });\n });\n\n describe('getAuthCode', () => {\n it('should return undefined for non-existent code', async () => {\n const result = await service.getAuthCode('non-existent-code');\n expect(result).toBeUndefined();\n });\n\n it('should return the correct authorization code when it exists', async () => {\n await service.storeAuthCode(mockAuthCode);\n const result = await service.getAuthCode(mockAuthCode.code);\n expect(result).toEqual(mockAuthCode);\n });\n });\n\n describe('removeAuthCode', () => {\n it('should remove an authorization code', async () => {\n await service.storeAuthCode(mockAuthCode);\n await service.removeAuthCode(mockAuthCode.code);\n\n const retrieved = await service.getAuthCode(mockAuthCode.code);\n expect(retrieved).toBeUndefined();\n });\n\n it('should not throw when removing non-existent code', async () => {\n await expect(\n service.removeAuthCode('non-existent-code'),\n ).resolves.toBeUndefined();\n });\n });\n });\n\n describe('OAuth Session Management', () => {\n const mockSession: OAuthSession = {\n sessionId: 'session-123',\n state: 'test-state',\n clientId: 'client-123',\n redirectUri: 'http://localhost:3000/callback',\n codeChallenge: 'test-challenge',\n codeChallengeMethod: 'S256',\n oauthState: 'oauth-state-123',\n resource: 'test-resource',\n expiresAt: Date.now() + 3600000, // 1 hour from now\n };\n\n const expiredSession: OAuthSession = {\n ...mockSession,\n sessionId: 'expired-session',\n expiresAt: Date.now() - 1000, // 1 second ago\n };\n\n describe('storeOAuthSession', () => {\n it('should store an OAuth session', async () => {\n const sessionId = 'session-123';\n await service.storeOAuthSession(sessionId, mockSession);\n\n const retrieved = await service.getOAuthSession(sessionId);\n expect(retrieved).toEqual(mockSession);\n });\n\n it('should overwrite existing session with same ID', async () => {\n const sessionId = 'session-123';\n await service.storeOAuthSession(sessionId, mockSession);\n\n const updatedSession = { ...mockSession, state: 'updated-state' };\n await service.storeOAuthSession(sessionId, updatedSession);\n\n const retrieved = await service.getOAuthSession(sessionId);\n expect(retrieved?.state).toBe('updated-state');\n });\n });\n\n describe('getOAuthSession', () => {\n it('should return undefined for non-existent session', async () => {\n const result = await service.getOAuthSession('non-existent-session');\n expect(result).toBeUndefined();\n });\n\n it('should return the correct OAuth session when it exists', async () => {\n const sessionId = 'session-123';\n await service.storeOAuthSession(sessionId, mockSession);\n\n const result = await service.getOAuthSession(sessionId);\n expect(result).toEqual(mockSession);\n });\n\n it('should return undefined and auto-remove expired sessions', async () => {\n const sessionId = 'expired-session';\n await service.storeOAuthSession(sessionId, expiredSession);\n\n const result = await service.getOAuthSession(sessionId);\n expect(result).toBeUndefined();\n\n // Verify it was actually removed\n const result2 = await service.getOAuthSession(sessionId);\n expect(result2).toBeUndefined();\n });\n });\n\n describe('removeOAuthSession', () => {\n it('should remove an OAuth session', async () => {\n const sessionId = 'session-123';\n await service.storeOAuthSession(sessionId, mockSession);\n await service.removeOAuthSession(sessionId);\n\n const retrieved = await service.getOAuthSession(sessionId);\n expect(retrieved).toBeUndefined();\n });\n\n it('should not throw when removing non-existent session', async () => {\n await expect(\n service.removeOAuthSession('non-existent-session'),\n ).resolves.toBeUndefined();\n });\n });\n });\n});\n"]}
|