@rekog/mcp-nest 1.7.1 → 1.7.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.
Files changed (73) hide show
  1. package/README.md +1 -1
  2. package/dist/authz/adapters/github.adapter.d.ts +40 -0
  3. package/dist/authz/adapters/github.adapter.d.ts.map +1 -0
  4. package/dist/authz/adapters/github.adapter.js +212 -0
  5. package/dist/authz/adapters/github.adapter.js.map +1 -0
  6. package/dist/authz/adapters/oidc.adapter.d.ts +21 -0
  7. package/dist/authz/adapters/oidc.adapter.d.ts.map +1 -0
  8. package/dist/authz/adapters/oidc.adapter.js +125 -0
  9. package/dist/authz/adapters/oidc.adapter.js.map +1 -0
  10. package/dist/authz/controllers/resource-metadata.controller.d.ts +62 -0
  11. package/dist/authz/controllers/resource-metadata.controller.d.ts.map +1 -0
  12. package/dist/authz/controllers/resource-metadata.controller.js +84 -0
  13. package/dist/authz/controllers/resource-metadata.controller.js.map +1 -0
  14. package/dist/authz/controllers/well-known.controller.d.ts +63 -0
  15. package/dist/authz/controllers/well-known.controller.d.ts.map +1 -0
  16. package/dist/authz/controllers/well-known.controller.js +131 -0
  17. package/dist/authz/controllers/well-known.controller.js.map +1 -0
  18. package/dist/authz/examples/oidc-provider-example.d.ts +3 -0
  19. package/dist/authz/examples/oidc-provider-example.d.ts.map +1 -0
  20. package/dist/authz/examples/oidc-provider-example.js +51 -0
  21. package/dist/authz/examples/oidc-provider-example.js.map +1 -0
  22. package/dist/authz/guards/jwt-auth.guard.js +1 -1
  23. package/dist/authz/guards/jwt-auth.guard.js.map +1 -1
  24. package/dist/authz/mcp-oauth.controller.d.ts +20 -11
  25. package/dist/authz/mcp-oauth.controller.d.ts.map +1 -1
  26. package/dist/authz/mcp-oauth.controller.js +91 -17
  27. package/dist/authz/mcp-oauth.controller.js.map +1 -1
  28. package/dist/authz/mcp-oauth.module.d.ts.map +1 -1
  29. package/dist/authz/mcp-oauth.module.js +2 -2
  30. package/dist/authz/mcp-oauth.module.js.map +1 -1
  31. package/dist/authz/oidc-provider.controller.d.ts +48 -0
  32. package/dist/authz/oidc-provider.controller.d.ts.map +1 -0
  33. package/dist/authz/oidc-provider.controller.js +194 -0
  34. package/dist/authz/oidc-provider.controller.js.map +1 -0
  35. package/dist/authz/oidc-provider.module.d.ts +11 -0
  36. package/dist/authz/oidc-provider.module.d.ts.map +1 -0
  37. package/dist/authz/oidc-provider.module.js +275 -0
  38. package/dist/authz/oidc-provider.module.js.map +1 -0
  39. package/dist/authz/providers/oauth-provider.interface.d.ts +1 -1
  40. package/dist/authz/providers/oauth-provider.interface.d.ts.map +1 -1
  41. package/dist/authz/providers/oauth-provider.interface.js.map +1 -1
  42. package/dist/authz/services/client.service.d.ts.map +1 -1
  43. package/dist/authz/services/client.service.js +14 -1
  44. package/dist/authz/services/client.service.js.map +1 -1
  45. package/dist/authz/services/jwt-token.service.d.ts +1 -0
  46. package/dist/authz/services/jwt-token.service.d.ts.map +1 -1
  47. package/dist/authz/services/jwt-token.service.js +10 -6
  48. package/dist/authz/services/jwt-token.service.js.map +1 -1
  49. package/dist/authz/stores/oauth-store.interface.d.ts +1 -0
  50. package/dist/authz/stores/oauth-store.interface.d.ts.map +1 -1
  51. package/dist/authz/stores/oauth-store.interface.js.map +1 -1
  52. package/dist/authz/stores/typeorm/entities/authorization-code.entity.d.ts +1 -0
  53. package/dist/authz/stores/typeorm/entities/authorization-code.entity.d.ts.map +1 -1
  54. package/dist/authz/stores/typeorm/entities/authorization-code.entity.js +4 -0
  55. package/dist/authz/stores/typeorm/entities/authorization-code.entity.js.map +1 -1
  56. package/dist/authz/stores/typeorm/entities/oauth-client.entity.d.ts +1 -0
  57. package/dist/authz/stores/typeorm/entities/oauth-client.entity.d.ts.map +1 -1
  58. package/dist/authz/stores/typeorm/entities/oauth-client.entity.js +4 -0
  59. package/dist/authz/stores/typeorm/entities/oauth-client.entity.js.map +1 -1
  60. package/dist/mcp/decorators/prompt.decorator.d.ts.map +1 -1
  61. package/dist/mcp/decorators/resource-template.decorator.d.ts.map +1 -1
  62. package/dist/mcp/decorators/resource.decorator.d.ts.map +1 -1
  63. package/dist/mcp/decorators/tool.decorator.d.ts.map +1 -1
  64. package/package.json +2 -2
  65. package/src/authz/guards/jwt-auth.guard.ts +1 -1
  66. package/src/authz/mcp-oauth.controller.ts +152 -15
  67. package/src/authz/mcp-oauth.module.ts +4 -2
  68. package/src/authz/providers/oauth-provider.interface.ts +1 -1
  69. package/src/authz/services/client.service.ts +25 -1
  70. package/src/authz/services/jwt-token.service.ts +16 -8
  71. package/src/authz/stores/oauth-store.interface.ts +1 -0
  72. package/src/authz/stores/typeorm/entities/authorization-code.entity.ts +3 -0
  73. package/src/authz/stores/typeorm/entities/oauth-client.entity.ts +3 -0
@@ -0,0 +1,63 @@
1
+ import { OAuthModuleOptions } from '../providers/oauth-provider.interface';
2
+ export declare class WellKnownController {
3
+ private readonly options;
4
+ constructor(options: OAuthModuleOptions);
5
+ getAuthorizationServerMetadata(): {
6
+ issuer: string;
7
+ authorization_endpoint: string;
8
+ token_endpoint: string;
9
+ userinfo_endpoint: string;
10
+ jwks_uri: string;
11
+ registration_endpoint: string;
12
+ scopes_supported: string[];
13
+ response_types_supported: string[];
14
+ grant_types_supported: string[];
15
+ subject_types_supported: string[];
16
+ token_endpoint_auth_methods_supported: string[];
17
+ code_challenge_methods_supported: string[];
18
+ claims_supported: string[];
19
+ introspection_endpoint: string;
20
+ revocation_endpoint: string;
21
+ service_documentation: string;
22
+ end_session_endpoint: string;
23
+ check_session_iframe: string;
24
+ 'x-mcp-capabilities': string[];
25
+ 'x-mcp-version': string;
26
+ 'x-api-version': string;
27
+ };
28
+ getOpenIdConfiguration(): {
29
+ url: string;
30
+ statusCode: number;
31
+ };
32
+ getOAuthAuthorizationServer(): {
33
+ issuer: string;
34
+ authorization_endpoint: string;
35
+ token_endpoint: string;
36
+ userinfo_endpoint: string;
37
+ jwks_uri: string;
38
+ registration_endpoint: string;
39
+ scopes_supported: string[];
40
+ response_types_supported: string[];
41
+ grant_types_supported: string[];
42
+ subject_types_supported: string[];
43
+ token_endpoint_auth_methods_supported: string[];
44
+ code_challenge_methods_supported: string[];
45
+ claims_supported: string[];
46
+ introspection_endpoint: string;
47
+ revocation_endpoint: string;
48
+ service_documentation: string;
49
+ end_session_endpoint: string;
50
+ check_session_iframe: string;
51
+ 'x-mcp-capabilities': string[];
52
+ 'x-mcp-version': string;
53
+ 'x-api-version': string;
54
+ };
55
+ getWebFinger(): {
56
+ subject: string;
57
+ links: {
58
+ rel: string;
59
+ href: string;
60
+ }[];
61
+ };
62
+ }
63
+ //# sourceMappingURL=well-known.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"well-known.controller.d.ts","sourceRoot":"","sources":["../../../src/authz/controllers/well-known.controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAQ3E,qBACa,mBAAmB;IAEI,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,kBAAkB;IAU9E,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;IAwE9B,sBAAsB;;;;IAWtB,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;IAS3B,YAAY;;;;;;;CAWb"}
@@ -0,0 +1,131 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.WellKnownController = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ let WellKnownController = class WellKnownController {
18
+ constructor(options) {
19
+ this.options = options;
20
+ }
21
+ getAuthorizationServerMetadata() {
22
+ return {
23
+ issuer: this.options.serverUrl,
24
+ authorization_endpoint: `${this.options.serverUrl}/oidc/auth`,
25
+ token_endpoint: `${this.options.serverUrl}/oidc/token`,
26
+ userinfo_endpoint: `${this.options.serverUrl}/oidc/me`,
27
+ jwks_uri: `${this.options.serverUrl}/oidc/jwks`,
28
+ registration_endpoint: `${this.options.serverUrl}/oidc/reg`,
29
+ scopes_supported: [
30
+ 'openid',
31
+ 'profile',
32
+ 'email',
33
+ 'offline_access'
34
+ ],
35
+ response_types_supported: [
36
+ 'code',
37
+ 'id_token',
38
+ 'code id_token'
39
+ ],
40
+ grant_types_supported: [
41
+ 'authorization_code',
42
+ 'refresh_token'
43
+ ],
44
+ subject_types_supported: [
45
+ 'public'
46
+ ],
47
+ token_endpoint_auth_methods_supported: [
48
+ 'client_secret_basic',
49
+ 'client_secret_post',
50
+ 'none'
51
+ ],
52
+ code_challenge_methods_supported: [
53
+ 'plain',
54
+ 'S256'
55
+ ],
56
+ claims_supported: [
57
+ 'sub',
58
+ 'name',
59
+ 'preferred_username',
60
+ 'email',
61
+ 'email_verified'
62
+ ],
63
+ introspection_endpoint: `${this.options.serverUrl}/oidc/introspect`,
64
+ revocation_endpoint: `${this.options.serverUrl}/oidc/revoke`,
65
+ service_documentation: `${this.options.serverUrl}/docs`,
66
+ end_session_endpoint: `${this.options.serverUrl}/oidc/session/end`,
67
+ check_session_iframe: `${this.options.serverUrl}/oidc/session/check`,
68
+ 'x-mcp-capabilities': [
69
+ 'tools',
70
+ 'resources',
71
+ 'prompts',
72
+ 'server-side-events',
73
+ 'streamable-http'
74
+ ],
75
+ 'x-mcp-version': '2024-11-05',
76
+ 'x-api-version': '1.0'
77
+ };
78
+ }
79
+ getOpenIdConfiguration() {
80
+ return {
81
+ url: `/oidc/.well-known/openid_configuration`,
82
+ statusCode: 302
83
+ };
84
+ }
85
+ getOAuthAuthorizationServer() {
86
+ return this.getAuthorizationServerMetadata();
87
+ }
88
+ getWebFinger() {
89
+ return {
90
+ subject: this.options.serverUrl,
91
+ links: [
92
+ {
93
+ rel: 'http://openid.net/specs/connect/1.0/issuer',
94
+ href: this.options.serverUrl
95
+ }
96
+ ]
97
+ };
98
+ }
99
+ };
100
+ exports.WellKnownController = WellKnownController;
101
+ __decorate([
102
+ (0, common_1.Get)('.well-known/oauth-authorization-server'),
103
+ __metadata("design:type", Function),
104
+ __metadata("design:paramtypes", []),
105
+ __metadata("design:returntype", void 0)
106
+ ], WellKnownController.prototype, "getAuthorizationServerMetadata", null);
107
+ __decorate([
108
+ (0, common_1.Get)('.well-known/openid_configuration'),
109
+ (0, common_1.Redirect)(),
110
+ __metadata("design:type", Function),
111
+ __metadata("design:paramtypes", []),
112
+ __metadata("design:returntype", void 0)
113
+ ], WellKnownController.prototype, "getOpenIdConfiguration", null);
114
+ __decorate([
115
+ (0, common_1.Get)('.well-known/oauth_authorization_server'),
116
+ __metadata("design:type", Function),
117
+ __metadata("design:paramtypes", []),
118
+ __metadata("design:returntype", void 0)
119
+ ], WellKnownController.prototype, "getOAuthAuthorizationServer", null);
120
+ __decorate([
121
+ (0, common_1.Get)('.well-known/webfinger'),
122
+ __metadata("design:type", Function),
123
+ __metadata("design:paramtypes", []),
124
+ __metadata("design:returntype", void 0)
125
+ ], WellKnownController.prototype, "getWebFinger", null);
126
+ exports.WellKnownController = WellKnownController = __decorate([
127
+ (0, common_1.Controller)(),
128
+ __param(0, (0, common_1.Inject)('OAUTH_MODULE_OPTIONS')),
129
+ __metadata("design:paramtypes", [Object])
130
+ ], WellKnownController);
131
+ //# sourceMappingURL=well-known.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"well-known.controller.js","sourceRoot":"","sources":["../../../src/authz/controllers/well-known.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAmE;AAU5D,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAC9B,YACmD,OAA2B;QAA3B,YAAO,GAAP,OAAO,CAAoB;IAC3E,CAAC;IASJ,8BAA8B;QAC5B,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;YAC9B,sBAAsB,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,YAAY;YAC7D,cAAc,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,aAAa;YACtD,iBAAiB,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,UAAU;YACtD,QAAQ,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,YAAY;YAC/C,qBAAqB,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,WAAW;YAC3D,gBAAgB,EAAE;gBAChB,QAAQ;gBACR,SAAS;gBACT,OAAO;gBACP,gBAAgB;aACjB;YACD,wBAAwB,EAAE;gBACxB,MAAM;gBACN,UAAU;gBACV,eAAe;aAChB;YACD,qBAAqB,EAAE;gBACrB,oBAAoB;gBACpB,eAAe;aAChB;YACD,uBAAuB,EAAE;gBACvB,QAAQ;aACT;YACD,qCAAqC,EAAE;gBACrC,qBAAqB;gBACrB,oBAAoB;gBACpB,MAAM;aACP;YACD,gCAAgC,EAAE;gBAChC,OAAO;gBACP,MAAM;aACP;YACD,gBAAgB,EAAE;gBAChB,KAAK;gBACL,MAAM;gBACN,oBAAoB;gBACpB,OAAO;gBACP,gBAAgB;aACjB;YAED,sBAAsB,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,kBAAkB;YACnE,mBAAmB,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,cAAc;YAC5D,qBAAqB,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,OAAO;YAGvD,oBAAoB,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,mBAAmB;YAClE,oBAAoB,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,qBAAqB;YAGpE,oBAAoB,EAAE;gBACpB,OAAO;gBACP,WAAW;gBACX,SAAS;gBACT,oBAAoB;gBACpB,iBAAiB;aAClB;YACD,eAAe,EAAE,YAAY;YAC7B,eAAe,EAAE,KAAK;SACvB,CAAC;IACJ,CAAC;IAUD,sBAAsB;QACpB,OAAO;YACL,GAAG,EAAE,wCAAwC;YAC7C,UAAU,EAAE,GAAG;SAChB,CAAC;IACJ,CAAC;IAMD,2BAA2B;QACzB,OAAO,IAAI,CAAC,8BAA8B,EAAE,CAAC;IAC/C,CAAC;IAOD,YAAY;QACV,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;YAC/B,KAAK,EAAE;gBACL;oBACE,GAAG,EAAE,4CAA4C;oBACjD,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;iBAC7B;aACF;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AAnHY,kDAAmB;AAY9B;IADC,IAAA,YAAG,EAAC,wCAAwC,CAAC;;;;yEA+D7C;AAUD;IAFC,IAAA,YAAG,EAAC,kCAAkC,CAAC;IACvC,IAAA,iBAAQ,GAAE;;;;iEAMV;AAMD;IADC,IAAA,YAAG,EAAC,wCAAwC,CAAC;;;;sEAG7C;AAOD;IADC,IAAA,YAAG,EAAC,uBAAuB,CAAC;;;;uDAW5B;8BAlHU,mBAAmB;IAD/B,IAAA,mBAAU,GAAE;IAGR,WAAA,IAAA,eAAM,EAAC,sBAAsB,CAAC,CAAA;;GAFtB,mBAAmB,CAmH/B","sourcesContent":["import { Controller, Get, Inject, Redirect } from '@nestjs/common';\nimport { OAuthModuleOptions } from '../providers/oauth-provider.interface';\n\n/**\n * Root Well-Known Endpoints Controller\n * \n * Handles OAuth 2.0 and OIDC well-known endpoints at the root level\n * as required by RFC 8414 and RFC 8623\n */\n@Controller()\nexport class WellKnownController {\n constructor(\n @Inject('OAUTH_MODULE_OPTIONS') private readonly options: OAuthModuleOptions,\n ) {}\n\n /**\n * OAuth Authorization Server Metadata Endpoint (RFC 8414)\n * MUST be at /.well-known/oauth-authorization-server (not prefixed)\n * \n * This returns the same metadata as the OIDC provider but at the correct root path\n */\n @Get('.well-known/oauth-authorization-server')\n getAuthorizationServerMetadata() {\n return {\n issuer: this.options.serverUrl,\n authorization_endpoint: `${this.options.serverUrl}/oidc/auth`,\n token_endpoint: `${this.options.serverUrl}/oidc/token`,\n userinfo_endpoint: `${this.options.serverUrl}/oidc/me`,\n jwks_uri: `${this.options.serverUrl}/oidc/jwks`,\n registration_endpoint: `${this.options.serverUrl}/oidc/reg`,\n scopes_supported: [\n 'openid',\n 'profile',\n 'email',\n 'offline_access'\n ],\n response_types_supported: [\n 'code',\n 'id_token',\n 'code id_token'\n ],\n grant_types_supported: [\n 'authorization_code',\n 'refresh_token'\n ],\n subject_types_supported: [\n 'public'\n ],\n token_endpoint_auth_methods_supported: [\n 'client_secret_basic',\n 'client_secret_post',\n 'none'\n ],\n code_challenge_methods_supported: [\n 'plain',\n 'S256'\n ],\n claims_supported: [\n 'sub',\n 'name',\n 'preferred_username',\n 'email',\n 'email_verified'\n ],\n // Additional OAuth 2.0 Authorization Server metadata\n introspection_endpoint: `${this.options.serverUrl}/oidc/introspect`,\n revocation_endpoint: `${this.options.serverUrl}/oidc/revoke`,\n service_documentation: `${this.options.serverUrl}/docs`,\n \n // OIDC-specific metadata\n end_session_endpoint: `${this.options.serverUrl}/oidc/session/end`,\n check_session_iframe: `${this.options.serverUrl}/oidc/session/check`,\n \n // MCP-specific extensions (non-standard but useful)\n 'x-mcp-capabilities': [\n 'tools',\n 'resources', \n 'prompts',\n 'server-side-events',\n 'streamable-http'\n ],\n 'x-mcp-version': '2024-11-05',\n 'x-api-version': '1.0'\n };\n }\n\n /**\n * OpenID Connect Discovery Document (RFC 8414 Section 3)\n * Should be at /.well-known/openid_configuration \n * \n * We redirect to the OIDC provider's discovery endpoint\n */\n @Get('.well-known/openid_configuration')\n @Redirect()\n getOpenIdConfiguration() {\n return {\n url: `/oidc/.well-known/openid_configuration`,\n statusCode: 302\n };\n }\n\n /**\n * Alternative OAuth Discovery endpoint (some implementations check here)\n */\n @Get('.well-known/oauth_authorization_server')\n getOAuthAuthorizationServer() {\n return this.getAuthorizationServerMetadata();\n }\n\n /**\n * WebFinger endpoint for OpenID Connect Discovery (RFC 7033)\n * Some clients use this for discovery\n */\n @Get('.well-known/webfinger')\n getWebFinger() {\n return {\n subject: this.options.serverUrl,\n links: [\n {\n rel: 'http://openid.net/specs/connect/1.0/issuer',\n href: this.options.serverUrl\n }\n ]\n };\n }\n}"]}
@@ -0,0 +1,3 @@
1
+ export declare class AppModuleWithOidcProvider {
2
+ }
3
+ //# sourceMappingURL=oidc-provider-example.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-provider-example.d.ts","sourceRoot":"","sources":["../../../src/authz/examples/oidc-provider-example.ts"],"names":[],"mappings":"AASA,qBAsDa,yBAAyB;CAAG"}
@@ -0,0 +1,51 @@
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.AppModuleWithOidcProvider = void 0;
10
+ const common_1 = require("@nestjs/common");
11
+ const oidc_provider_module_1 = require("../oidc-provider.module");
12
+ const github_provider_1 = require("../providers/github.provider");
13
+ let AppModuleWithOidcProvider = class AppModuleWithOidcProvider {
14
+ };
15
+ exports.AppModuleWithOidcProvider = AppModuleWithOidcProvider;
16
+ exports.AppModuleWithOidcProvider = AppModuleWithOidcProvider = __decorate([
17
+ (0, common_1.Module)({
18
+ imports: [
19
+ oidc_provider_module_1.McpOidcProviderModule.forRoot({
20
+ clientId: process.env.GITHUB_CLIENT_ID,
21
+ clientSecret: process.env.GITHUB_CLIENT_SECRET,
22
+ jwtSecret: process.env.JWT_SECRET,
23
+ serverUrl: process.env.SERVER_URL || 'https://localhost:3000',
24
+ resource: process.env.RESOURCE_URL || 'https://localhost:3000/mcp',
25
+ jwtIssuer: process.env.JWT_ISSUER || 'https://localhost:3000',
26
+ jwtAudience: process.env.JWT_AUDIENCE || 'mcp-client',
27
+ jwtAccessTokenExpiresIn: '1h',
28
+ jwtRefreshTokenExpiresIn: '30d',
29
+ cookieMaxAge: 24 * 60 * 60 * 1000,
30
+ cookieSecure: process.env.NODE_ENV === 'production',
31
+ oauthSessionExpiresIn: 10 * 60 * 1000,
32
+ authCodeExpiresIn: 10 * 60 * 1000,
33
+ provider: github_provider_1.GitHubOAuthProvider,
34
+ apiPrefix: 'oidc',
35
+ endpoints: {
36
+ wellKnownAuthorizationServerMetadata: '/.well-known/oauth-authorization-server',
37
+ register: '/reg',
38
+ authorize: '/auth',
39
+ callback: '/callback',
40
+ token: '/token',
41
+ validate: '/introspect',
42
+ revoke: '/revoke',
43
+ },
44
+ storeConfiguration: {
45
+ type: 'memory',
46
+ },
47
+ }),
48
+ ],
49
+ })
50
+ ], AppModuleWithOidcProvider);
51
+ //# sourceMappingURL=oidc-provider-example.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-provider-example.js","sourceRoot":"","sources":["../../../src/authz/examples/oidc-provider-example.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,kEAAgE;AAChE,kEAAmE;AA6D5D,IAAM,yBAAyB,GAA/B,MAAM,yBAAyB;CAAG,CAAA;AAA5B,8DAAyB;oCAAzB,yBAAyB;IAtDrC,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YAEP,4CAAqB,CAAC,OAAO,CAAC;gBAE5B,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAiB;gBACvC,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAqB;gBAG/C,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,UAAW;gBAGlC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,wBAAwB;gBAC7D,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,4BAA4B;gBAGlE,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,wBAAwB;gBAC7D,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,YAAY;gBAGrD,uBAAuB,EAAE,IAAI;gBAC7B,wBAAwB,EAAE,KAAK;gBAG/B,YAAY,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI;gBACjC,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY;gBACnD,qBAAqB,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI;gBACrC,iBAAiB,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI;gBAGjC,QAAQ,EAAE,qCAAmB;gBAG7B,SAAS,EAAE,MAAM;gBAGjB,SAAS,EAAE;oBACT,oCAAoC,EAClC,yCAAyC;oBAC3C,QAAQ,EAAE,MAAM;oBAChB,SAAS,EAAE,OAAO;oBAClB,QAAQ,EAAE,WAAW;oBACrB,KAAK,EAAE,QAAQ;oBACf,QAAQ,EAAE,aAAa;oBACvB,MAAM,EAAE,SAAS;iBAClB;gBAGD,kBAAkB,EAAE;oBAClB,IAAI,EAAE,QAAQ;iBACf;aACF,CAAC;SACH;KACF,CAAC;GACW,yBAAyB,CAAG","sourcesContent":["import { Module } from '@nestjs/common';\nimport { McpOidcProviderModule } from '../oidc-provider.module';\nimport { GitHubOAuthProvider } from '../providers/github.provider';\n\n/**\n * Example configuration for using the new OIDC Provider\n * instead of the legacy custom OAuth implementation\n */\n\n@Module({\n imports: [\n // Replace McpAuthModule.forRoot with McpOidcProviderModule.forRoot\n McpOidcProviderModule.forRoot({\n // GitHub OAuth App credentials\n clientId: process.env.GITHUB_CLIENT_ID!,\n clientSecret: process.env.GITHUB_CLIENT_SECRET!,\n\n // JWT signing secret (should be at least 32 characters)\n jwtSecret: process.env.JWT_SECRET!,\n\n // Server configuration\n serverUrl: process.env.SERVER_URL || 'https://localhost:3000',\n resource: process.env.RESOURCE_URL || 'https://localhost:3000/mcp',\n\n // OIDC Provider configuration\n jwtIssuer: process.env.JWT_ISSUER || 'https://localhost:3000',\n jwtAudience: process.env.JWT_AUDIENCE || 'mcp-client',\n\n // Token expiration settings\n jwtAccessTokenExpiresIn: '1h',\n jwtRefreshTokenExpiresIn: '30d',\n\n // Cookie and session settings\n cookieMaxAge: 24 * 60 * 60 * 1000, // 24 hours\n cookieSecure: process.env.NODE_ENV === 'production',\n oauthSessionExpiresIn: 10 * 60 * 1000, // 10 minutes\n authCodeExpiresIn: 10 * 60 * 1000, // 10 minutes\n\n // GitHub provider configuration\n provider: GitHubOAuthProvider,\n\n // Optional: API prefix for OIDC endpoints (defaults to 'oidc')\n apiPrefix: 'oidc',\n\n // Optional: Custom endpoint configuration\n endpoints: {\n wellKnownAuthorizationServerMetadata:\n '/.well-known/oauth-authorization-server',\n register: '/reg',\n authorize: '/auth',\n callback: '/callback',\n token: '/token',\n validate: '/introspect',\n revoke: '/revoke',\n },\n\n // Optional: Storage configuration (defaults to memory)\n storeConfiguration: {\n type: 'memory', // or 'typeorm' for persistent storage\n },\n }),\n ],\n})\nexport class AppModuleWithOidcProvider {}\n\n/**\n * Environment variables required:\n *\n * GITHUB_CLIENT_ID=your_github_oauth_app_client_id\n * GITHUB_CLIENT_SECRET=your_github_oauth_app_client_secret\n * JWT_SECRET=your_jwt_signing_secret_at_least_32_characters_long\n * SERVER_URL=https://your-server.com (optional, defaults to localhost:3000)\n * RESOURCE_URL=https://your-server.com/mcp (optional)\n * JWT_ISSUER=https://your-server.com (optional)\n * JWT_AUDIENCE=mcp-client (optional)\n * NODE_ENV=production (for secure cookies)\n */\n\n/**\n * OIDC Endpoints provided by this configuration:\n *\n * Well-known metadata:\n * - GET /.well-known/oauth-authorization-server\n * - GET /.well-known/oauth-protected-resource\n * - GET /oidc/.well-known/openid_configuration\n *\n * OAuth 2.0 / OIDC endpoints:\n * - GET /oidc/auth - Authorization endpoint\n * - POST /oidc/token - Token endpoint\n * - GET /oidc/me - UserInfo endpoint\n * - GET /oidc/jwks - JSON Web Key Set\n * - POST /oidc/reg - Dynamic client registration\n * - POST /oidc/introspect - Token introspection\n * - POST /oidc/revoke - Token revocation\n *\n * Custom interaction endpoints:\n * - GET /oidc/interaction/:uid - GitHub authentication initiation\n * - GET /oidc/callback - GitHub OAuth callback\n */\n\n/**\n * Migration from legacy McpAuthModule:\n *\n * 1. Replace imports:\n * - Change: import { McpAuthModule } from '@rekog/mcp-nest/authz'\n * - To: import { McpOidcProviderModule } from '@rekog/mcp-nest/authz'\n *\n * 2. Update module registration:\n * - Change: McpAuthModule.forRoot(...)\n * - To: McpOidcProviderModule.forRoot(...)\n *\n * 3. Update endpoints (if you have hardcoded URLs):\n * - Authorization: /authorize → /oidc/auth\n * - Token: /token → /oidc/token\n * - Callback: /callback → /oidc/callback\n * - Well-known: /.well-known/oauth-authorization-server (unchanged)\n *\n * 4. Benefits of the new implementation:\n * - Standards-compliant OIDC provider\n * - Better security with proper OIDC flows\n * - Automatic JWKS endpoint\n * - Built-in token introspection\n * - Support for ID tokens\n * - Better integration with OIDC-compliant clients\n */\n"]}
@@ -23,7 +23,7 @@ let McpAuthJwtGuard = class McpAuthJwtGuard {
23
23
  throw new common_1.UnauthorizedException('Access token required');
24
24
  }
25
25
  const payload = this.jwtTokenService.validateToken(token);
26
- if (!payload || payload.type !== 'access') {
26
+ if (!payload) {
27
27
  throw new common_1.UnauthorizedException('Invalid or expired access token');
28
28
  }
29
29
  request.user = payload;
@@ -1 +1 @@
1
- {"version":3,"file":"jwt-auth.guard.js","sourceRoot":"","sources":["../../../src/authz/guards/jwt-auth.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAKwB;AAExB,qEAA4E;AAOrE,IAAM,eAAe,GAArB,MAAM,eAAe;IAC1B,YAA6B,eAAgC;QAAhC,oBAAe,GAAf,eAAe,CAAiB;IAAG,CAAC;IAEjE,WAAW,CAAC,OAAyB;QACnC,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAwB,CAAC;QAC1E,MAAM,KAAK,GAAG,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAEnD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,8BAAqB,CAAC,uBAAuB,CAAC,CAAC;QAC3D,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAE1D,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC1C,MAAM,IAAI,8BAAqB,CAAC,iCAAiC,CAAC,CAAC;QACrE,CAAC;QAED,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,sBAAsB,CAAC,OAAgB;QAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;QACjD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5C,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/C,CAAC;CACF,CAAA;AA9BY,0CAAe;0BAAf,eAAe;IAD3B,IAAA,mBAAU,GAAE;qCAEmC,mCAAe;GADlD,eAAe,CA8B3B","sourcesContent":["import {\n Injectable,\n CanActivate,\n ExecutionContext,\n UnauthorizedException,\n} from '@nestjs/common';\nimport { Request } from 'express';\nimport { JwtPayload, JwtTokenService } from '../services/jwt-token.service';\n\nexport interface AuthenticatedRequest extends Request {\n user: JwtPayload;\n}\n\n@Injectable()\nexport class McpAuthJwtGuard implements CanActivate {\n constructor(private readonly jwtTokenService: JwtTokenService) {}\n\n canActivate(context: ExecutionContext): boolean {\n const request = context.switchToHttp().getRequest<AuthenticatedRequest>();\n const token = this.extractTokenFromHeader(request);\n\n if (!token) {\n throw new UnauthorizedException('Access token required');\n }\n\n const payload = this.jwtTokenService.validateToken(token);\n\n if (!payload || payload.type !== 'access') {\n throw new UnauthorizedException('Invalid or expired access token');\n }\n\n request.user = payload;\n return true;\n }\n\n private extractTokenFromHeader(request: Request): string | undefined {\n const authHeader = request.headers.authorization;\n if (!authHeader) {\n return undefined;\n }\n\n const [type, token] = authHeader.split(' ');\n return type === 'Bearer' ? token : undefined;\n }\n}\n"]}
1
+ {"version":3,"file":"jwt-auth.guard.js","sourceRoot":"","sources":["../../../src/authz/guards/jwt-auth.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAKwB;AAExB,qEAA4E;AAOrE,IAAM,eAAe,GAArB,MAAM,eAAe;IAC1B,YAA6B,eAAgC;QAAhC,oBAAe,GAAf,eAAe,CAAiB;IAAG,CAAC;IAEjE,WAAW,CAAC,OAAyB;QACnC,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAwB,CAAC;QAC1E,MAAM,KAAK,GAAG,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAEnD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,8BAAqB,CAAC,uBAAuB,CAAC,CAAC;QAC3D,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAE1D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,8BAAqB,CAAC,iCAAiC,CAAC,CAAC;QACrE,CAAC;QAED,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,sBAAsB,CAAC,OAAgB;QAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;QACjD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5C,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/C,CAAC;CACF,CAAA;AA9BY,0CAAe;0BAAf,eAAe;IAD3B,IAAA,mBAAU,GAAE;qCAEmC,mCAAe;GADlD,eAAe,CA8B3B","sourcesContent":["import {\n Injectable,\n CanActivate,\n ExecutionContext,\n UnauthorizedException,\n} from '@nestjs/common';\nimport { Request } from 'express';\nimport { JwtPayload, JwtTokenService } from '../services/jwt-token.service';\n\nexport interface AuthenticatedRequest extends Request {\n user: JwtPayload;\n}\n\n@Injectable()\nexport class McpAuthJwtGuard implements CanActivate {\n constructor(private readonly jwtTokenService: JwtTokenService) {}\n\n canActivate(context: ExecutionContext): boolean {\n const request = context.switchToHttp().getRequest<AuthenticatedRequest>();\n const token = this.extractTokenFromHeader(request);\n\n if (!token) {\n throw new UnauthorizedException('Access token required');\n }\n\n const payload = this.jwtTokenService.validateToken(token);\n\n if (!payload) {\n throw new UnauthorizedException('Invalid or expired access token');\n }\n\n request.user = payload;\n return true;\n }\n\n private extractTokenFromHeader(request: Request): string | undefined {\n const authHeader = request.headers.authorization;\n if (!authHeader) {\n return undefined;\n }\n\n const [type, token] = authHeader.split(' ');\n return type === 'Bearer' ? token : undefined;\n }\n}\n"]}
@@ -4,7 +4,7 @@ import { AuthenticatedRequest } from './guards/jwt-auth.guard';
4
4
  import { OAuthEndpointConfiguration, OAuthModuleOptions, OAuthUserProfile } from './providers/oauth-provider.interface';
5
5
  import { ClientService } from './services/client.service';
6
6
  import { JwtTokenService, TokenPair } from './services/jwt-token.service';
7
- import { ClientRegistrationDto, IOAuthStore } from './stores/oauth-store.interface';
7
+ import { IOAuthStore } from './stores/oauth-store.interface';
8
8
  interface OAuthCallbackRequest extends ExpressRequest {
9
9
  user?: {
10
10
  profile: OAuthUserProfile;
@@ -30,23 +30,32 @@ export declare function createMcpOAuthController(endpoints?: OAuthEndpointConfig
30
30
  response_modes_supported: string[];
31
31
  grant_types_supported: string[];
32
32
  token_endpoint_auth_methods_supported: string[];
33
+ scopes_supported: string[];
33
34
  revocation_endpoint: string;
34
35
  code_challenge_methods_supported: string[];
35
36
  };
36
- registerClient(registrationDto: ClientRegistrationDto): Promise<import("./stores/oauth-store.interface").OAuthClient>;
37
+ registerClient(registrationDto: any): Promise<import("./stores/oauth-store.interface").OAuthClient>;
37
38
  authorize(query: any, req: any, res: Response, next: NextFunction): Promise<void>;
38
39
  handleProviderCallback(req: OAuthCallbackRequest, res: Response, next: NextFunction): void;
39
40
  processAuthenticationSuccess(req: OAuthCallbackRequest, res: Response): Promise<void>;
40
- exchangeToken(body: any): Promise<TokenPair>;
41
- handleAuthorizationCodeGrant(code: string, code_verifier: string, _redirect_uri: string, client_id: string): Promise<TokenPair>;
42
- handleRefreshTokenGrant(refresh_token: string): TokenPair;
43
- validateToken(req: AuthenticatedRequest): {
44
- valid: boolean;
45
- user_id: string;
46
- client_id: string | undefined;
47
- scope: string | undefined;
48
- expires_at: number;
41
+ exchangeToken(body: any, req: any): Promise<TokenPair>;
42
+ extractClientCredentials(req: any, body: any): {
43
+ client_id: string;
44
+ client_secret?: string;
49
45
  };
46
+ validateClientAuthentication(client: any, clientCredentials: {
47
+ client_id: string;
48
+ client_secret?: string;
49
+ }): void;
50
+ handleAuthorizationCodeGrant(code: string, code_verifier: string, _redirect_uri: string, clientCredentials: {
51
+ client_id: string;
52
+ client_secret?: string;
53
+ }): Promise<TokenPair>;
54
+ handleRefreshTokenGrant(refresh_token: string, clientCredentials: {
55
+ client_id: string;
56
+ client_secret?: string;
57
+ }): Promise<TokenPair>;
58
+ validateToken(req: AuthenticatedRequest): any;
50
59
  validatePKCE(code_verifier: string, code_challenge: string, method: string): boolean;
51
60
  };
52
61
  };
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-oauth.controller.d.ts","sourceRoot":"","sources":["../../src/authz/mcp-oauth.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,MAAM,EAOP,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE5E,OAAO,EAAE,oBAAoB,EAAmB,MAAM,yBAAyB,CAAC;AAChF,OAAO,EACL,0BAA0B,EAC1B,kBAAkB,EAElB,gBAAgB,EACjB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAE1E,OAAO,EACL,qBAAqB,EACrB,WAAW,EACZ,MAAM,gCAAgC,CAAC;AAGxC,UAAU,oBAAqB,SAAQ,cAAc;IACnD,IAAI,CAAC,EAAE;QACL,OAAO,EAAE,gBAAgB,CAAC;QAC1B,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,wBAAgB,wBAAwB,CACtC,SAAS,GAAE,0BAA+B;kBASG,kBAAkB,SACpB,WAAW,mBACxB,eAAe,iBACjB,aAAa;;4BAPnB,MAAM;+BACH,OAAO;0BACZ,kBAAkB;wBAGK,WAAW;kCACxB,eAAe;gCACjB,aAAa;;;;;;;;;;;;;wCAqCO,qBAAqB;yBAMjD,GAAG,OAEd,GAAG,OACI,QAAQ,QACN,YAAY;oCA0Ed,oBAAoB,OACpB,QAAQ,QACN,YAAY;0CA2BrB,oBAAoB,OACpB,QAAQ;4BAwEmB,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC;2CAyBlD,MAAM,iBACG,MAAM,iBACN,MAAM,aACV,MAAM,GAChB,OAAO,CAAC,SAAS,CAAC;+CA+DkB,MAAM,GAAG,SAAS;2BAW/B,oBAAoB;;;;;;;oCAW7B,MAAM,kBACL,MAAM,UACd,MAAM,GACb,OAAO;;EAcb"}
1
+ {"version":3,"file":"mcp-oauth.controller.d.ts","sourceRoot":"","sources":["../../src/authz/mcp-oauth.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,MAAM,EAOP,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE5E,OAAO,EAAE,oBAAoB,EAAmB,MAAM,yBAAyB,CAAC;AAChF,OAAO,EACL,0BAA0B,EAC1B,kBAAkB,EAElB,gBAAgB,EACjB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAE1E,OAAO,EAEL,WAAW,EACZ,MAAM,gCAAgC,CAAC;AAGxC,UAAU,oBAAqB,SAAQ,cAAc;IACnD,IAAI,CAAC,EAAE;QACL,OAAO,EAAE,gBAAgB,CAAC;QAC1B,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,wBAAgB,wBAAwB,CACtC,SAAS,GAAE,0BAA+B;kBASG,kBAAkB,SACpB,WAAW,mBACxB,eAAe,iBACjB,aAAa;;4BAPnB,MAAM;+BACH,OAAO;0BACZ,kBAAkB;wBAGK,WAAW;kCACxB,eAAe;gCACjB,aAAa;;;;;;;;;;;;;;wCAsCO,GAAG;yBAM/B,GAAG,OAEd,GAAG,OACI,QAAQ,QACN,YAAY;oCA2Ed,oBAAoB,OACpB,QAAQ,QACN,YAAY;0CA2BrB,oBAAoB,OACpB,QAAQ;4BAyEC,GAAG,OACL,GAAG,GACd,OAAO,CAAC,SAAS,CAAC;sCAuCd,GAAG,QACF,GAAG,GACR;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,aAAa,CAAC,EAAE,MAAM,CAAA;SAAE;6CA4BtC,GAAG,qBACQ;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,aAAa,CAAC,EAAE,MAAM,CAAA;SAAE,GAC/D,IAAI;2CAqCC,MAAM,iBACG,MAAM,iBACN,MAAM,qBACF;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,aAAa,CAAC,EAAE,MAAM,CAAA;SAAE,GAC/D,OAAO,CAAC,SAAS,CAAC;+CAyEJ,MAAM,qBACF;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,aAAa,CAAC,EAAE,MAAM,CAAA;SAAE,GAC/D,OAAO,CAAC,SAAS,CAAC;2BA0CK,oBAAoB;oCAiB7B,MAAM,kBACL,MAAM,UACd,MAAM,GACb,OAAO;;EAcb"}
@@ -50,6 +50,7 @@ function createMcpOAuthController(endpoints = {}) {
50
50
  'client_secret_post',
51
51
  'none',
52
52
  ],
53
+ scopes_supported: ['offline_access'],
53
54
  revocation_endpoint: (0, normalize_endpoint_1.normalizeEndpoint)(`${this.serverUrl}/${endpoints?.revoke}`),
54
55
  code_challenge_methods_supported: ['plain', 'S256'],
55
56
  };
@@ -58,7 +59,7 @@ function createMcpOAuthController(endpoints = {}) {
58
59
  return await this.clientService.registerClient(registrationDto);
59
60
  }
60
61
  async authorize(query, req, res, next) {
61
- const { response_type, client_id, redirect_uri, code_challenge, code_challenge_method, state, } = query;
62
+ const { response_type, client_id, redirect_uri, code_challenge, code_challenge_method, state, scope, } = query;
62
63
  const resource = this.options.resource;
63
64
  if (response_type !== 'code') {
64
65
  throw new common_1.BadRequestException('Only response_type=code is supported');
@@ -84,7 +85,7 @@ function createMcpOAuthController(endpoints = {}) {
84
85
  codeChallenge: code_challenge,
85
86
  codeChallengeMethod: code_challenge_method || 'plain',
86
87
  oauthState: state,
87
- scope: query.scope || '',
88
+ scope: scope,
88
89
  resource,
89
90
  expiresAt: Date.now() + this.options.oauthSessionExpiresIn,
90
91
  };
@@ -167,22 +168,71 @@ function createMcpOAuthController(endpoints = {}) {
167
168
  await this.store.removeOAuthSession(sessionId);
168
169
  res.redirect(redirectUrl.toString());
169
170
  }
170
- async exchangeToken(body) {
171
- const { grant_type, code, code_verifier, redirect_uri, client_id, refresh_token, } = body;
171
+ async exchangeToken(body, req) {
172
+ const { grant_type, code, code_verifier, redirect_uri, client_id, client_secret, refresh_token, } = body;
172
173
  if (grant_type === 'authorization_code') {
173
- return this.handleAuthorizationCodeGrant(code, code_verifier, redirect_uri, client_id);
174
+ const clientCredentials = this.extractClientCredentials(req, body);
175
+ return this.handleAuthorizationCodeGrant(code, code_verifier, redirect_uri, clientCredentials);
174
176
  }
175
177
  else if (grant_type === 'refresh_token') {
176
- return this.handleRefreshTokenGrant(refresh_token);
178
+ let clientCredentials;
179
+ try {
180
+ clientCredentials = this.extractClientCredentials(req, body);
181
+ }
182
+ catch {
183
+ clientCredentials = { client_id: '' };
184
+ }
185
+ return this.handleRefreshTokenGrant(refresh_token, clientCredentials);
177
186
  }
178
187
  else {
179
188
  throw new common_1.BadRequestException('Unsupported grant_type');
180
189
  }
181
190
  }
182
- async handleAuthorizationCodeGrant(code, code_verifier, _redirect_uri, client_id) {
191
+ extractClientCredentials(req, body) {
192
+ const authHeader = req.headers?.authorization;
193
+ if (authHeader && authHeader.startsWith('Basic ')) {
194
+ const credentials = Buffer.from(authHeader.slice(6), 'base64').toString('utf-8');
195
+ const [client_id, client_secret] = credentials.split(':', 2);
196
+ if (client_id) {
197
+ return { client_id, client_secret };
198
+ }
199
+ }
200
+ if (body.client_id) {
201
+ return {
202
+ client_id: body.client_id,
203
+ client_secret: body.client_secret,
204
+ };
205
+ }
206
+ throw new common_1.BadRequestException('Missing client credentials');
207
+ }
208
+ validateClientAuthentication(client, clientCredentials) {
209
+ if (!client) {
210
+ throw new common_1.BadRequestException('Invalid client_id');
211
+ }
212
+ const { token_endpoint_auth_method } = client;
213
+ switch (token_endpoint_auth_method) {
214
+ case 'client_secret_basic':
215
+ case 'client_secret_post':
216
+ if (!clientCredentials.client_secret) {
217
+ throw new common_1.BadRequestException('Client secret required for this authentication method');
218
+ }
219
+ if (client.client_secret !== clientCredentials.client_secret) {
220
+ throw new common_1.BadRequestException('Invalid client credentials');
221
+ }
222
+ break;
223
+ case 'none':
224
+ if (clientCredentials.client_secret) {
225
+ throw new common_1.BadRequestException('Client secret not allowed for public clients');
226
+ }
227
+ break;
228
+ default:
229
+ throw new common_1.BadRequestException(`Unsupported authentication method: ${token_endpoint_auth_method}`);
230
+ }
231
+ }
232
+ async handleAuthorizationCodeGrant(code, code_verifier, _redirect_uri, clientCredentials) {
183
233
  this.logger.debug('handleAuthorizationCodeGrant - Params:', {
184
234
  code,
185
- client_id,
235
+ client_id: clientCredentials.client_id,
186
236
  });
187
237
  const authCode = await this.store.getAuthCode(code);
188
238
  if (!authCode) {
@@ -194,10 +244,12 @@ function createMcpOAuthController(endpoints = {}) {
194
244
  this.logger.error('handleAuthorizationCodeGrant - Authorization code expired:', code);
195
245
  throw new common_1.BadRequestException('Authorization code has expired');
196
246
  }
197
- if (authCode.client_id !== client_id) {
198
- this.logger.error('handleAuthorizationCodeGrant - Client ID mismatch:', { expected: authCode.client_id, got: client_id });
247
+ if (authCode.client_id !== clientCredentials.client_id) {
248
+ this.logger.error('handleAuthorizationCodeGrant - Client ID mismatch:', { expected: authCode.client_id, got: clientCredentials.client_id });
199
249
  throw new common_1.BadRequestException('Client ID mismatch');
200
250
  }
251
+ const client = await this.clientService.getClient(clientCredentials.client_id);
252
+ this.validateClientAuthentication(client, clientCredentials);
201
253
  if (authCode.code_challenge) {
202
254
  const isValid = this.validatePKCE(code_verifier, authCode.code_challenge, authCode.code_challenge_method);
203
255
  if (!isValid) {
@@ -209,12 +261,30 @@ function createMcpOAuthController(endpoints = {}) {
209
261
  this.logger.error('handleAuthorizationCodeGrant - No resource associated with code');
210
262
  throw new common_1.BadRequestException('Authorization code is not associated with a resource');
211
263
  }
212
- const tokens = this.jwtTokenService.generateTokenPair(authCode.user_id, client_id, authCode.scope, authCode.resource);
264
+ const tokens = this.jwtTokenService.generateTokenPair(authCode.user_id, clientCredentials.client_id, authCode.scope, authCode.resource);
213
265
  await this.store.removeAuthCode(code);
214
266
  this.logger.log('handleAuthorizationCodeGrant - Token pair generated for user:', authCode.user_id);
215
267
  return tokens;
216
268
  }
217
- handleRefreshTokenGrant(refresh_token) {
269
+ async handleRefreshTokenGrant(refresh_token, clientCredentials) {
270
+ const payload = this.jwtTokenService.validateToken(refresh_token);
271
+ if (!payload || payload.type !== 'refresh') {
272
+ throw new common_1.BadRequestException('Invalid or expired refresh token');
273
+ }
274
+ const clientId = clientCredentials.client_id || payload.client_id;
275
+ if (!clientId) {
276
+ throw new common_1.BadRequestException('Unable to determine client_id');
277
+ }
278
+ const client = await this.clientService.getClient(clientId);
279
+ if (client?.token_endpoint_auth_method !== 'none') {
280
+ this.validateClientAuthentication(client, {
281
+ ...clientCredentials,
282
+ client_id: clientId,
283
+ });
284
+ }
285
+ if (payload.client_id !== clientId) {
286
+ throw new common_1.BadRequestException('Invalid refresh token or token does not belong to this client');
287
+ }
218
288
  const newTokens = this.jwtTokenService.refreshAccessToken(refresh_token);
219
289
  if (!newTokens) {
220
290
  throw new common_1.BadRequestException('Failed to refresh token');
@@ -222,13 +292,16 @@ function createMcpOAuthController(endpoints = {}) {
222
292
  return newTokens;
223
293
  }
224
294
  validateToken(req) {
225
- return {
295
+ const response = {
226
296
  valid: true,
227
297
  user_id: req.user.sub,
228
- client_id: req.user.client_id,
229
- scope: req.user.scope,
298
+ client_id: req.user.azp || req.user.client_id,
230
299
  expires_at: req.user.exp * 1000,
231
300
  };
301
+ if (req.user.scope) {
302
+ response.scope = req.user.scope;
303
+ }
304
+ return response;
232
305
  }
233
306
  validatePKCE(code_verifier, code_challenge, method) {
234
307
  if (method === 'plain') {
@@ -244,7 +317,7 @@ function createMcpOAuthController(endpoints = {}) {
244
317
  }
245
318
  };
246
319
  __decorate([
247
- (0, common_1.Get)(endpoints.wellKnown),
320
+ (0, common_1.Get)(endpoints.wellKnownAuthorizationServerMetadata),
248
321
  __metadata("design:type", Function),
249
322
  __metadata("design:paramtypes", []),
250
323
  __metadata("design:returntype", void 0)
@@ -278,8 +351,9 @@ function createMcpOAuthController(endpoints = {}) {
278
351
  __decorate([
279
352
  (0, common_1.Post)(endpoints.token),
280
353
  __param(0, (0, common_1.Body)()),
354
+ __param(1, (0, common_1.Req)()),
281
355
  __metadata("design:type", Function),
282
- __metadata("design:paramtypes", [Object]),
356
+ __metadata("design:paramtypes", [Object, Object]),
283
357
  __metadata("design:returntype", Promise)
284
358
  ], McpOAuthController.prototype, "exchangeToken", null);
285
359
  __decorate([