@rekog/mcp-nest 1.7.0-alpha.0 → 1.7.0-alpha.2
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/authz/guards/jwt-auth.guard.d.ts +13 -0
- package/dist/authz/guards/jwt-auth.guard.d.ts.map +1 -0
- package/dist/authz/guards/jwt-auth.guard.js +46 -0
- package/dist/authz/guards/jwt-auth.guard.js.map +1 -0
- package/dist/authz/index.d.ts +8 -1
- package/dist/authz/index.d.ts.map +1 -1
- package/dist/authz/index.js +22 -0
- package/dist/authz/index.js.map +1 -1
- package/dist/authz/interfaces/index.d.ts +3 -0
- package/dist/authz/interfaces/index.d.ts.map +1 -0
- package/dist/authz/interfaces/index.js +19 -0
- package/dist/authz/interfaces/index.js.map +1 -0
- package/dist/authz/mcp-oauth.controller.d.ts +53 -0
- package/dist/authz/mcp-oauth.controller.d.ts.map +1 -0
- package/dist/authz/mcp-oauth.controller.js +305 -0
- package/dist/authz/mcp-oauth.controller.js.map +1 -0
- package/dist/authz/mcp-oauth.module.d.ts +11 -0
- package/dist/authz/mcp-oauth.module.d.ts.map +1 -0
- package/dist/authz/mcp-oauth.module.js +173 -0
- package/dist/authz/mcp-oauth.module.js.map +1 -0
- package/dist/authz/providers/github.provider.d.ts +3 -0
- package/dist/authz/providers/github.provider.d.ts.map +1 -0
- package/dist/authz/providers/github.provider.js +23 -0
- package/dist/authz/providers/github.provider.js.map +1 -0
- package/dist/authz/providers/google.provider.d.ts +3 -0
- package/dist/authz/providers/google.provider.d.ts.map +1 -0
- package/dist/authz/providers/google.provider.js +24 -0
- package/dist/authz/providers/google.provider.js.map +1 -0
- package/dist/authz/providers/oauth-provider.interface.d.ts +75 -0
- package/dist/authz/providers/oauth-provider.interface.d.ts.map +1 -0
- package/dist/authz/providers/oauth-provider.interface.js +3 -0
- package/dist/authz/providers/oauth-provider.interface.js.map +1 -0
- package/dist/authz/services/client.service.d.ts +10 -0
- package/dist/authz/services/client.service.d.ts.map +1 -0
- package/dist/authz/services/client.service.js +84 -0
- package/dist/authz/services/client.service.js.map +1 -0
- package/dist/authz/services/jwt-token.service.d.ts +29 -0
- package/dist/authz/services/jwt-token.service.d.ts.map +1 -0
- package/dist/authz/services/jwt-token.service.js +103 -0
- package/dist/authz/services/jwt-token.service.js.map +1 -0
- package/dist/authz/services/oauth-strategy.service.d.ts +11 -0
- package/dist/authz/services/oauth-strategy.service.d.ts.map +1 -0
- package/dist/authz/services/oauth-strategy.service.js +64 -0
- package/dist/authz/services/oauth-strategy.service.js.map +1 -0
- package/dist/authz/stores/memory-store.service.d.ts +19 -0
- package/dist/authz/stores/memory-store.service.d.ts.map +1 -0
- package/dist/authz/stores/memory-store.service.js +84 -0
- package/dist/authz/stores/memory-store.service.js.map +1 -0
- package/dist/authz/stores/memory-store.service.spec.d.ts +2 -0
- package/dist/authz/stores/memory-store.service.spec.d.ts.map +1 -0
- package/dist/authz/stores/memory-store.service.spec.js +195 -0
- package/dist/authz/stores/memory-store.service.spec.js.map +1 -0
- package/dist/authz/stores/oauth-store.interface.d.ts +52 -0
- package/dist/authz/stores/oauth-store.interface.d.ts.map +1 -0
- package/dist/authz/stores/oauth-store.interface.js +3 -0
- package/dist/authz/stores/oauth-store.interface.js.map +1 -0
- package/dist/authz/stores/sqlite/sqlite-store.service.d.ts +18 -0
- package/dist/authz/stores/sqlite/sqlite-store.service.d.ts.map +1 -0
- package/dist/authz/stores/sqlite/sqlite-store.service.js +206 -0
- package/dist/authz/stores/sqlite/sqlite-store.service.js.map +1 -0
- package/dist/authz/stores/typeorm/entities/authorization-code.entity.d.ts +13 -0
- package/dist/authz/stores/typeorm/entities/authorization-code.entity.d.ts.map +1 -0
- package/dist/authz/stores/typeorm/entities/authorization-code.entity.js +60 -0
- package/dist/authz/stores/typeorm/entities/authorization-code.entity.js.map +1 -0
- package/dist/authz/stores/typeorm/entities/index.d.ts +4 -0
- package/dist/authz/stores/typeorm/entities/index.d.ts.map +1 -0
- package/dist/authz/stores/typeorm/entities/index.js +10 -0
- package/dist/authz/stores/typeorm/entities/index.js.map +1 -0
- package/dist/authz/stores/typeorm/entities/oauth-client.entity.d.ts +16 -0
- package/dist/authz/stores/typeorm/entities/oauth-client.entity.d.ts.map +1 -0
- package/dist/authz/stores/typeorm/entities/oauth-client.entity.js +72 -0
- package/dist/authz/stores/typeorm/entities/oauth-client.entity.js.map +1 -0
- package/dist/authz/stores/typeorm/entities/oauth-session.entity.d.ts +13 -0
- package/dist/authz/stores/typeorm/entities/oauth-session.entity.d.ts.map +1 -0
- package/dist/authz/stores/typeorm/entities/oauth-session.entity.js +60 -0
- package/dist/authz/stores/typeorm/entities/oauth-session.entity.js.map +1 -0
- package/dist/authz/stores/typeorm/typeorm-store.service.d.ts +21 -0
- package/dist/authz/stores/typeorm/typeorm-store.service.d.ts.map +1 -0
- package/dist/authz/stores/typeorm/typeorm-store.service.js +87 -0
- package/dist/authz/stores/typeorm/typeorm-store.service.js.map +1 -0
- package/dist/mcp/services/handlers/mcp-tools.handler.d.ts.map +1 -1
- package/dist/mcp/services/handlers/mcp-tools.handler.js.map +1 -1
- package/package.json +17 -2
- package/src/authz/guards/jwt-auth.guard.ts +45 -0
- package/src/authz/index.ts +8 -1
- package/src/authz/mcp-oauth.controller.ts +394 -0
- package/src/authz/mcp-oauth.module.ts +235 -0
- package/src/authz/providers/github.provider.ts +24 -0
- package/src/authz/providers/google.provider.ts +22 -0
- package/src/authz/providers/oauth-provider.interface.ts +102 -0
- package/src/authz/services/client.service.ts +110 -0
- package/src/authz/services/jwt-token.service.ts +127 -0
- package/src/authz/services/oauth-strategy.service.ts +55 -0
- package/src/authz/stores/memory-store.service.spec.ts +240 -0
- package/src/authz/stores/memory-store.service.ts +100 -0
- package/src/authz/stores/oauth-store.interface.ts +105 -0
- package/src/authz/stores/sqlite/sqlite-store.service.ts +279 -0
- package/src/authz/stores/typeorm/README.md +133 -0
- package/src/authz/stores/typeorm/entities/authorization-code.entity.ts +34 -0
- package/src/authz/stores/typeorm/entities/index.ts +3 -0
- package/src/authz/stores/typeorm/entities/oauth-client.entity.ts +49 -0
- package/src/authz/stores/typeorm/entities/oauth-session.entity.ts +34 -0
- package/src/authz/stores/typeorm/typeorm-store.service.ts +98 -0
- package/src/mcp/services/handlers/mcp-tools.handler.ts +5 -2
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { OAuthModuleOptions } from '../providers/oauth-provider.interface';
|
|
3
|
+
export declare const STRATEGY_NAME = "oauth-provider";
|
|
4
|
+
export declare class OAuthStrategyService implements OnModuleInit {
|
|
5
|
+
private options;
|
|
6
|
+
constructor(options: OAuthModuleOptions);
|
|
7
|
+
onModuleInit(): void;
|
|
8
|
+
private registerStrategy;
|
|
9
|
+
getStrategyName(): string;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=oauth-strategy.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-strategy.service.d.ts","sourceRoot":"","sources":["../../../src/authz/services/oauth-strategy.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,YAAY,EAAU,MAAM,gBAAgB,CAAC;AAElE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAE3E,eAAO,MAAM,aAAa,mBAAmB,CAAC;AAE9C,qBACa,oBAAqB,YAAW,YAAY;IAErB,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,kBAAkB;IAGrE,YAAY;IAIZ,OAAO,CAAC,gBAAgB;IAmCxB,eAAe,IAAI,MAAM;CAG1B"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.OAuthStrategyService = exports.STRATEGY_NAME = void 0;
|
|
19
|
+
const common_1 = require("@nestjs/common");
|
|
20
|
+
const passport_1 = __importDefault(require("passport"));
|
|
21
|
+
exports.STRATEGY_NAME = 'oauth-provider';
|
|
22
|
+
let OAuthStrategyService = class OAuthStrategyService {
|
|
23
|
+
constructor(options) {
|
|
24
|
+
this.options = options;
|
|
25
|
+
}
|
|
26
|
+
onModuleInit() {
|
|
27
|
+
this.registerStrategy();
|
|
28
|
+
}
|
|
29
|
+
registerStrategy() {
|
|
30
|
+
const provider = this.options.provider;
|
|
31
|
+
const clientId = this.options.clientId;
|
|
32
|
+
const clientSecret = this.options.clientSecret;
|
|
33
|
+
const serverUrl = this.options.serverUrl;
|
|
34
|
+
const strategyOptions = provider.strategyOptions({
|
|
35
|
+
serverUrl,
|
|
36
|
+
clientId,
|
|
37
|
+
clientSecret,
|
|
38
|
+
});
|
|
39
|
+
const strategy = new provider.strategy(strategyOptions, (accessToken, refreshToken, profile, done) => {
|
|
40
|
+
try {
|
|
41
|
+
const mappedProfile = provider.profileMapper(profile);
|
|
42
|
+
return done(null, {
|
|
43
|
+
profile: mappedProfile,
|
|
44
|
+
accessToken,
|
|
45
|
+
provider: provider.name,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
return done(error, null);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
passport_1.default.use(exports.STRATEGY_NAME, strategy);
|
|
53
|
+
}
|
|
54
|
+
getStrategyName() {
|
|
55
|
+
return exports.STRATEGY_NAME;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
exports.OAuthStrategyService = OAuthStrategyService;
|
|
59
|
+
exports.OAuthStrategyService = OAuthStrategyService = __decorate([
|
|
60
|
+
(0, common_1.Injectable)(),
|
|
61
|
+
__param(0, (0, common_1.Inject)('OAUTH_MODULE_OPTIONS')),
|
|
62
|
+
__metadata("design:paramtypes", [Object])
|
|
63
|
+
], OAuthStrategyService);
|
|
64
|
+
//# sourceMappingURL=oauth-strategy.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-strategy.service.js","sourceRoot":"","sources":["../../../src/authz/services/oauth-strategy.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,2CAAkE;AAClE,wDAAgC;AAGnB,QAAA,aAAa,GAAG,gBAAgB,CAAC;AAGvC,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAC/B,YAC0C,OAA2B;QAA3B,YAAO,GAAP,OAAO,CAAoB;IAClE,CAAC;IAEJ,YAAY;QACV,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC1B,CAAC;IAEO,gBAAgB;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;QAGvC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;QACvC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;QAG/C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;QAEzC,MAAM,eAAe,GAAG,QAAQ,CAAC,eAAe,CAAC;YAC/C,SAAS;YACT,QAAQ;YACR,YAAY;SACb,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,QAAQ,CACpC,eAAe,EACf,CAAC,WAAmB,EAAE,YAAoB,EAAE,OAAY,EAAE,IAAS,EAAE,EAAE;YACrE,IAAI,CAAC;gBACH,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;gBACtD,OAAO,IAAI,CAAC,IAAI,EAAE;oBAChB,OAAO,EAAE,aAAa;oBACtB,WAAW;oBACX,QAAQ,EAAE,QAAQ,CAAC,IAAI;iBACxB,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC,CACF,CAAC;QAEF,kBAAQ,CAAC,GAAG,CAAC,qBAAa,EAAE,QAAQ,CAAC,CAAC;IACxC,CAAC;IAED,eAAe;QACb,OAAO,qBAAa,CAAC;IACvB,CAAC;CACF,CAAA;AA/CY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,mBAAU,GAAE;IAGR,WAAA,IAAA,eAAM,EAAC,sBAAsB,CAAC,CAAA;;GAFtB,oBAAoB,CA+ChC","sourcesContent":["import { Injectable, OnModuleInit, Inject } from '@nestjs/common';\nimport passport from 'passport';\nimport { OAuthModuleOptions } from '../providers/oauth-provider.interface';\n\nexport const STRATEGY_NAME = 'oauth-provider';\n\n@Injectable()\nexport class OAuthStrategyService implements OnModuleInit {\n constructor(\n @Inject('OAUTH_MODULE_OPTIONS') private options: OAuthModuleOptions,\n ) {}\n\n onModuleInit() {\n this.registerStrategy();\n }\n\n private registerStrategy() {\n const provider = this.options.provider;\n\n // Use client credentials from resolved options\n const clientId = this.options.clientId;\n const clientSecret = this.options.clientSecret;\n\n // Use resolved serverUrl (no fallbacks needed)\n const serverUrl = this.options.serverUrl;\n\n const strategyOptions = provider.strategyOptions({\n serverUrl,\n clientId,\n clientSecret,\n });\n\n const strategy = new provider.strategy(\n strategyOptions,\n (accessToken: string, refreshToken: string, profile: any, done: any) => {\n try {\n const mappedProfile = provider.profileMapper(profile);\n return done(null, {\n profile: mappedProfile,\n accessToken,\n provider: provider.name,\n });\n } catch (error) {\n return done(error, null);\n }\n },\n );\n\n passport.use(STRATEGY_NAME, strategy);\n }\n\n getStrategyName(): string {\n return STRATEGY_NAME;\n }\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { OAuthSession } from '../providers/oauth-provider.interface';
|
|
2
|
+
import { AuthorizationCode, IOAuthStore, OAuthClient } from './oauth-store.interface';
|
|
3
|
+
export declare class MemoryStore implements IOAuthStore {
|
|
4
|
+
private clients;
|
|
5
|
+
private authCodes;
|
|
6
|
+
private oauthSessions;
|
|
7
|
+
storeClient(client: OAuthClient): Promise<OAuthClient>;
|
|
8
|
+
getClient(client_id: string): Promise<OAuthClient | undefined>;
|
|
9
|
+
findClient(client_name: string): Promise<OAuthClient | undefined>;
|
|
10
|
+
storeAuthCode(code: AuthorizationCode): Promise<void>;
|
|
11
|
+
getAuthCode(code: string): Promise<AuthorizationCode | undefined>;
|
|
12
|
+
removeAuthCode(code: string): Promise<void>;
|
|
13
|
+
storeOAuthSession(sessionId: string, session: OAuthSession): Promise<void>;
|
|
14
|
+
getOAuthSession(sessionId: string): Promise<OAuthSession | undefined>;
|
|
15
|
+
removeOAuthSession(sessionId: string): Promise<void>;
|
|
16
|
+
generateClientId(client: OAuthClient): string;
|
|
17
|
+
private normalizeClientObject;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=memory-store.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-store.service.d.ts","sourceRoot":"","sources":["../../../src/authz/stores/memory-store.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AACrE,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,WAAW,EACZ,MAAM,yBAAyB,CAAC;AAGjC,qBACa,WAAY,YAAW,WAAW;IAC7C,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,SAAS,CAAwC;IACzD,OAAO,CAAC,aAAa,CAAmC;IAElD,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAKtD,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAI9D,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IASjE,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;IAIjE,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK3C,iBAAiB,CACrB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC;IAIV,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC;IASrE,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1D,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM;IAa7C,OAAO,CAAC,qBAAqB;CAmB9B"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.MemoryStore = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const crypto_1 = require("crypto");
|
|
12
|
+
let MemoryStore = class MemoryStore {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.clients = new Map();
|
|
15
|
+
this.authCodes = new Map();
|
|
16
|
+
this.oauthSessions = new Map();
|
|
17
|
+
}
|
|
18
|
+
async storeClient(client) {
|
|
19
|
+
this.clients.set(client.client_id, client);
|
|
20
|
+
return client;
|
|
21
|
+
}
|
|
22
|
+
async getClient(client_id) {
|
|
23
|
+
return this.clients.get(client_id);
|
|
24
|
+
}
|
|
25
|
+
async findClient(client_name) {
|
|
26
|
+
for (const client of this.clients.values()) {
|
|
27
|
+
if (client.client_name === client_name) {
|
|
28
|
+
return client;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
async storeAuthCode(code) {
|
|
34
|
+
this.authCodes.set(code.code, code);
|
|
35
|
+
}
|
|
36
|
+
async getAuthCode(code) {
|
|
37
|
+
return this.authCodes.get(code);
|
|
38
|
+
}
|
|
39
|
+
async removeAuthCode(code) {
|
|
40
|
+
this.authCodes.delete(code);
|
|
41
|
+
}
|
|
42
|
+
async storeOAuthSession(sessionId, session) {
|
|
43
|
+
this.oauthSessions.set(sessionId, session);
|
|
44
|
+
}
|
|
45
|
+
async getOAuthSession(sessionId) {
|
|
46
|
+
const session = this.oauthSessions.get(sessionId);
|
|
47
|
+
if (session && session.expiresAt < Date.now()) {
|
|
48
|
+
this.oauthSessions.delete(sessionId);
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
return session;
|
|
52
|
+
}
|
|
53
|
+
async removeOAuthSession(sessionId) {
|
|
54
|
+
this.oauthSessions.delete(sessionId);
|
|
55
|
+
}
|
|
56
|
+
generateClientId(client) {
|
|
57
|
+
const normalizedClient = this.normalizeClientObject(client);
|
|
58
|
+
const clientString = JSON.stringify(normalizedClient);
|
|
59
|
+
const hash = (0, crypto_1.createHash)('sha256').update(clientString).digest('hex');
|
|
60
|
+
const normalizedName = client.client_name
|
|
61
|
+
.toLowerCase()
|
|
62
|
+
.replace(/[^a-z0-9]/g, '');
|
|
63
|
+
return `${normalizedName}_${hash.substring(0, 16)}`;
|
|
64
|
+
}
|
|
65
|
+
normalizeClientObject(client) {
|
|
66
|
+
const normalized = {};
|
|
67
|
+
const sortedKeys = Object.keys(client).sort();
|
|
68
|
+
for (const key of sortedKeys) {
|
|
69
|
+
const value = client[key];
|
|
70
|
+
if (Array.isArray(value)) {
|
|
71
|
+
normalized[key] = [...value].sort();
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
normalized[key] = value;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return normalized;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
exports.MemoryStore = MemoryStore;
|
|
81
|
+
exports.MemoryStore = MemoryStore = __decorate([
|
|
82
|
+
(0, common_1.Injectable)()
|
|
83
|
+
], MemoryStore);
|
|
84
|
+
//# sourceMappingURL=memory-store.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-store.service.js","sourceRoot":"","sources":["../../../src/authz/stores/memory-store.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@nestjs/common';\nimport { createHash } from 'crypto';\nimport { OAuthSession } from '../providers/oauth-provider.interface';\nimport {\n AuthorizationCode,\n IOAuthStore,\n OAuthClient,\n} from './oauth-store.interface';\n\n// In-memory storage (in production, use a database)\n@Injectable()\nexport class MemoryStore implements IOAuthStore {\n private clients = new Map<string, OAuthClient>();\n private authCodes = new Map<string, AuthorizationCode>();\n private oauthSessions = new Map<string, OAuthSession>();\n\n async storeClient(client: OAuthClient): Promise<OAuthClient> {\n this.clients.set(client.client_id, client);\n return client;\n }\n\n async getClient(client_id: string): Promise<OAuthClient | undefined> {\n return this.clients.get(client_id);\n }\n\n async findClient(client_name: string): Promise<OAuthClient | undefined> {\n for (const client of this.clients.values()) {\n if (client.client_name === client_name) {\n return client;\n }\n }\n return undefined;\n }\n\n async storeAuthCode(code: AuthorizationCode): Promise<void> {\n this.authCodes.set(code.code, code);\n }\n\n async getAuthCode(code: string): Promise<AuthorizationCode | undefined> {\n return this.authCodes.get(code);\n }\n\n async removeAuthCode(code: string): Promise<void> {\n this.authCodes.delete(code);\n }\n\n // New OAuth session methods for provider-agnostic flow\n async storeOAuthSession(\n sessionId: string,\n session: OAuthSession,\n ): Promise<void> {\n this.oauthSessions.set(sessionId, session);\n }\n\n async getOAuthSession(sessionId: string): Promise<OAuthSession | undefined> {\n const session = this.oauthSessions.get(sessionId);\n if (session && session.expiresAt < Date.now()) {\n this.oauthSessions.delete(sessionId);\n return undefined;\n }\n return session;\n }\n\n async removeOAuthSession(sessionId: string): Promise<void> {\n this.oauthSessions.delete(sessionId);\n }\n\n generateClientId(client: OAuthClient): string {\n // Create deterministic client ID based on entire client object\n const normalizedClient = this.normalizeClientObject(client);\n const clientString = JSON.stringify(normalizedClient);\n const hash = createHash('sha256').update(clientString).digest('hex');\n\n // Use first 16 characters of hash with client name prefix for readability\n const normalizedName = client.client_name\n .toLowerCase()\n .replace(/[^a-z0-9]/g, '');\n return `${normalizedName}_${hash.substring(0, 16)}`;\n }\n\n private normalizeClientObject(client: OAuthClient): any {\n // Create a normalized version of the client object for consistent hashing\n const normalized: any = {};\n\n // Sort object keys to ensure consistent ordering\n const sortedKeys = Object.keys(client).sort();\n\n for (const key of sortedKeys) {\n const value = (client as any)[key];\n if (Array.isArray(value)) {\n // Sort arrays to ensure consistent ordering\n normalized[key] = [...value].sort();\n } else {\n normalized[key] = value;\n }\n }\n\n return normalized;\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-store.service.spec.d.ts","sourceRoot":"","sources":["../../../src/authz/stores/memory-store.service.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,195 @@
|
|
|
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
|
+
});
|
|
195
|
+
//# sourceMappingURL=memory-store.service.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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 } from './oauth-store.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"]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { OAuthSession } from '../providers/oauth-provider.interface';
|
|
2
|
+
export interface OAuthClient {
|
|
3
|
+
client_id: string;
|
|
4
|
+
client_name: string;
|
|
5
|
+
client_description?: string;
|
|
6
|
+
logo_uri?: string;
|
|
7
|
+
client_uri?: string;
|
|
8
|
+
developer_name?: string;
|
|
9
|
+
developer_email?: string;
|
|
10
|
+
redirect_uris: string[];
|
|
11
|
+
grant_types: string[];
|
|
12
|
+
response_types: string[];
|
|
13
|
+
token_endpoint_auth_method: string;
|
|
14
|
+
created_at: Date;
|
|
15
|
+
updated_at: Date;
|
|
16
|
+
}
|
|
17
|
+
export interface AuthorizationCode {
|
|
18
|
+
code: string;
|
|
19
|
+
user_id: string;
|
|
20
|
+
client_id: string;
|
|
21
|
+
redirect_uri: string;
|
|
22
|
+
code_challenge: string;
|
|
23
|
+
code_challenge_method: string;
|
|
24
|
+
expires_at: number;
|
|
25
|
+
used_at?: Date;
|
|
26
|
+
github_access_token: string;
|
|
27
|
+
}
|
|
28
|
+
export interface ClientRegistrationDto {
|
|
29
|
+
client_name: string;
|
|
30
|
+
client_description?: string;
|
|
31
|
+
logo_uri?: string;
|
|
32
|
+
client_uri?: string;
|
|
33
|
+
developer_name?: string;
|
|
34
|
+
developer_email?: string;
|
|
35
|
+
redirect_uris: string[];
|
|
36
|
+
grant_types?: string[];
|
|
37
|
+
response_types?: string[];
|
|
38
|
+
token_endpoint_auth_method?: string;
|
|
39
|
+
}
|
|
40
|
+
export interface IOAuthStore {
|
|
41
|
+
storeClient(client: OAuthClient): Promise<OAuthClient>;
|
|
42
|
+
getClient(client_id: string): Promise<OAuthClient | undefined>;
|
|
43
|
+
findClient(client_name: string): Promise<OAuthClient | undefined>;
|
|
44
|
+
generateClientId(client: OAuthClient): string;
|
|
45
|
+
storeAuthCode(code: AuthorizationCode): Promise<void>;
|
|
46
|
+
getAuthCode(code: string): Promise<AuthorizationCode | undefined>;
|
|
47
|
+
removeAuthCode(code: string): Promise<void>;
|
|
48
|
+
storeOAuthSession(sessionId: string, session: OAuthSession): Promise<void>;
|
|
49
|
+
getOAuthSession(sessionId: string): Promise<OAuthSession | undefined>;
|
|
50
|
+
removeOAuthSession(sessionId: string): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=oauth-store.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-store.interface.d.ts","sourceRoot":"","sources":["../../../src/authz/stores/oauth-store.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAErE,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,0BAA0B,EAAE,MAAM,CAAC;IACnC,UAAU,EAAE,IAAI,CAAC;IACjB,UAAU,EAAE,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC;AA+CD,MAAM,WAAW,WAAW;IAE1B,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACvD,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC;IAC/D,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC;IAClE,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC;IAG9C,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAAC;IAClE,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAG5C,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC;IACtE,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-store.interface.js","sourceRoot":"","sources":["../../../src/authz/stores/oauth-store.interface.ts"],"names":[],"mappings":"","sourcesContent":["import { OAuthSession } from '../providers/oauth-provider.interface';\n\nexport interface OAuthClient {\n client_id: string;\n client_name: string;\n client_description?: string;\n logo_uri?: string;\n client_uri?: string;\n developer_name?: string;\n developer_email?: string;\n redirect_uris: string[];\n grant_types: string[];\n response_types: string[];\n token_endpoint_auth_method: string;\n created_at: Date;\n updated_at: Date;\n}\n\nexport interface AuthorizationCode {\n code: string;\n user_id: string;\n client_id: string;\n redirect_uri: string;\n code_challenge: string;\n code_challenge_method: string;\n expires_at: number;\n used_at?: Date;\n github_access_token: string;\n}\n\nexport interface ClientRegistrationDto {\n client_name: string;\n client_description?: string;\n logo_uri?: string;\n client_uri?: string;\n developer_name?: string;\n developer_email?: string;\n redirect_uris: string[];\n grant_types?: string[];\n response_types?: string[];\n token_endpoint_auth_method?: string;\n}\n\n/**\n * Interface for OAuth store implementations.\n *\n * Implement this interface to create custom storage solutions (e.g., Redis, Database, etc.).\n * The default implementation is an in-memory store suitable for development.\n *\n * @example\n * ```typescript\n * class RedisOAuthStore implements IOAuthStore {\n * constructor(private redisClient: RedisClient) {}\n *\n * async storeClient(client: OAuthClient): Promise<void> {\n * await this.redisClient.set(`client:${client.client_id}`, JSON.stringify(client));\n * }\n *\n * async getClient(client_id: string): Promise<OAuthClient | undefined> {\n * const data = await this.redisClient.get(`client:${client_id}`);\n * return data ? JSON.parse(data) : undefined;\n * }\n *\n * async findClient(client_name: string): Promise<OAuthClient | undefined> {\n * const data = await this.redisClient.get(`client_name:${client_name}`);\n * return data ? JSON.parse(data) : undefined;\n * }\n *\n * generateClientId(client: OAuthClient): string {\n * // Custom client ID generation logic\n * const normalizedName = client.client_name.toLowerCase().replace(/[^a-z0-9]/g, '');\n * const timestamp = Date.now().toString(36);\n * return `${normalizedName}_${timestamp}`;\n * }\n *\n * // ... implement other methods\n * }\n *\n * // Usage in module:\n * McpOAuthModule.forRoot({\n * provider: GoogleOAuthProvider,\n * clientId: process.env.GOOGLE_CLIENT_ID!,\n * clientSecret: process.env.GOOGLE_CLIENT_SECRET!,\n * jwtSecret: process.env.JWT_SECRET!,\n * memoryStore: new RedisOAuthStore(redisClient), // Custom implementation\n * })\n * ```\n */\nexport interface IOAuthStore {\n // Client management\n storeClient(client: OAuthClient): Promise<OAuthClient>;\n getClient(client_id: string): Promise<OAuthClient | undefined>;\n findClient(client_name: string): Promise<OAuthClient | undefined>;\n generateClientId(client: OAuthClient): string;\n\n // Authorization code management\n storeAuthCode(code: AuthorizationCode): Promise<void>;\n getAuthCode(code: string): Promise<AuthorizationCode | undefined>;\n removeAuthCode(code: string): Promise<void>;\n\n // OAuth session management\n storeOAuthSession(sessionId: string, session: OAuthSession): Promise<void>;\n getOAuthSession(sessionId: string): Promise<OAuthSession | undefined>;\n removeOAuthSession(sessionId: string): Promise<void>;\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { OAuthSession } from '../../providers/oauth-provider.interface';
|
|
2
|
+
import { AuthorizationCode, IOAuthStore, OAuthClient } from '../oauth-store.interface';
|
|
3
|
+
export declare class SQLiteStore implements IOAuthStore {
|
|
4
|
+
private sqlite;
|
|
5
|
+
constructor(databasePath?: string);
|
|
6
|
+
private initializeTables;
|
|
7
|
+
storeClient(client: OAuthClient): Promise<OAuthClient>;
|
|
8
|
+
getClient(client_id: string): Promise<OAuthClient | undefined>;
|
|
9
|
+
findClient(client_name: string): Promise<OAuthClient | undefined>;
|
|
10
|
+
storeAuthCode(code: AuthorizationCode): Promise<void>;
|
|
11
|
+
getAuthCode(code: string): Promise<AuthorizationCode | undefined>;
|
|
12
|
+
removeAuthCode(code: string): Promise<void>;
|
|
13
|
+
storeOAuthSession(sessionId: string, session: OAuthSession): Promise<void>;
|
|
14
|
+
getOAuthSession(sessionId: string): Promise<OAuthSession | undefined>;
|
|
15
|
+
removeOAuthSession(sessionId: string): Promise<void>;
|
|
16
|
+
generateClientId(client: OAuthClient): string;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=sqlite-store.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-store.service.d.ts","sourceRoot":"","sources":["../../../../src/authz/stores/sqlite/sqlite-store.service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,0CAA0C,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,WAAW,EACZ,MAAM,0BAA0B,CAAC;AAElC,qBACa,WAAY,YAAW,WAAW;IAC7C,OAAO,CAAC,MAAM,CAAM;gBAER,YAAY,GAAE,MAA4B;IAKtD,OAAO,CAAC,gBAAgB;IAoDlB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IA4BtD,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IA2B9D,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IA4BjE,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBrD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;IA6BjE,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ3C,iBAAiB,CACrB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC;IAoBV,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC;IA4BrE,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO1D,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM;CAQ9C"}
|