n8n 1.119.0 → 1.120.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/dist/auth/auth.service.js +1 -0
  2. package/dist/auth/auth.service.js.map +1 -1
  3. package/dist/build.tsbuildinfo +1 -1
  4. package/dist/controller.registry.d.ts +1 -0
  5. package/dist/controller.registry.js +37 -12
  6. package/dist/controller.registry.js.map +1 -1
  7. package/dist/controllers/auth.controller.js +3 -1
  8. package/dist/controllers/auth.controller.js.map +1 -1
  9. package/dist/events/maps/relay.event-map.d.ts +1 -1
  10. package/dist/middlewares/list-query/dtos/workflow.filter.dto.d.ts +1 -1
  11. package/dist/middlewares/list-query/dtos/workflow.filter.dto.js +1 -1
  12. package/dist/middlewares/list-query/dtos/workflow.filter.dto.js.map +1 -1
  13. package/dist/middlewares/list-query/dtos/workflow.select.dto.js +1 -0
  14. package/dist/middlewares/list-query/dtos/workflow.select.dto.js.map +1 -1
  15. package/dist/modules/breaking-changes/breaking-changes.controller.d.ts +7 -3
  16. package/dist/modules/breaking-changes/breaking-changes.controller.js +39 -6
  17. package/dist/modules/breaking-changes/breaking-changes.controller.js.map +1 -1
  18. package/dist/modules/breaking-changes/breaking-changes.service.d.ts +9 -6
  19. package/dist/modules/breaking-changes/breaking-changes.service.js +67 -38
  20. package/dist/modules/breaking-changes/breaking-changes.service.js.map +1 -1
  21. package/dist/modules/breaking-changes/rules/v2/file-access.rule.d.ts +5 -4
  22. package/dist/modules/breaking-changes/rules/v2/file-access.rule.js +4 -3
  23. package/dist/modules/breaking-changes/rules/v2/file-access.rule.js.map +1 -1
  24. package/dist/modules/breaking-changes/rules/v2/process-env-access.rule.d.ts +5 -4
  25. package/dist/modules/breaking-changes/rules/v2/process-env-access.rule.js +11 -13
  26. package/dist/modules/breaking-changes/rules/v2/process-env-access.rule.js.map +1 -1
  27. package/dist/modules/breaking-changes/rules/v2/removed-nodes.rule.d.ts +5 -4
  28. package/dist/modules/breaking-changes/rules/v2/removed-nodes.rule.js +4 -3
  29. package/dist/modules/breaking-changes/rules/v2/removed-nodes.rule.js.map +1 -1
  30. package/dist/modules/breaking-changes/types/detection.types.d.ts +9 -10
  31. package/dist/modules/breaking-changes/types/rule.types.d.ts +9 -48
  32. package/dist/modules/breaking-changes/types/rule.types.js +1 -14
  33. package/dist/modules/breaking-changes/types/rule.types.js.map +1 -1
  34. package/dist/modules/insights/database/repositories/insights-by-period-query.helper.d.ts +9 -2
  35. package/dist/modules/insights/database/repositories/insights-by-period-query.helper.js +28 -64
  36. package/dist/modules/insights/database/repositories/insights-by-period-query.helper.js.map +1 -1
  37. package/dist/modules/insights/insights.controller.js +1 -1
  38. package/dist/modules/mcp/database/entities/oauth-access-token.entity.d.ts +9 -0
  39. package/dist/modules/mcp/database/entities/oauth-access-token.entity.js +44 -0
  40. package/dist/modules/mcp/database/entities/oauth-access-token.entity.js.map +1 -0
  41. package/dist/modules/mcp/database/entities/oauth-authorization-code.entity.d.ts +15 -0
  42. package/dist/modules/mcp/database/entities/oauth-authorization-code.entity.js +69 -0
  43. package/dist/modules/mcp/database/entities/oauth-authorization-code.entity.js.map +1 -0
  44. package/dist/modules/mcp/database/entities/oauth-client.entity.d.ts +18 -0
  45. package/dist/modules/mcp/database/entities/oauth-client.entity.js +65 -0
  46. package/dist/modules/mcp/database/entities/oauth-client.entity.js.map +1 -0
  47. package/dist/modules/mcp/database/entities/oauth-refresh-token.entity.d.ts +10 -0
  48. package/dist/modules/mcp/database/entities/oauth-refresh-token.entity.js +49 -0
  49. package/dist/modules/mcp/database/entities/oauth-refresh-token.entity.js.map +1 -0
  50. package/dist/modules/mcp/database/entities/oauth-user-consent.entity.d.ts +10 -0
  51. package/dist/modules/mcp/database/entities/oauth-user-consent.entity.js +49 -0
  52. package/dist/modules/mcp/database/entities/oauth-user-consent.entity.js.map +1 -0
  53. package/dist/modules/mcp/database/repositories/oauth-access-token.repository.d.ts +5 -0
  54. package/dist/modules/mcp/database/repositories/oauth-access-token.repository.js +26 -0
  55. package/dist/modules/mcp/database/repositories/oauth-access-token.repository.js.map +1 -0
  56. package/dist/modules/mcp/database/repositories/oauth-authorization-code.repository.d.ts +5 -0
  57. package/dist/modules/mcp/database/repositories/oauth-authorization-code.repository.js +26 -0
  58. package/dist/modules/mcp/database/repositories/oauth-authorization-code.repository.js.map +1 -0
  59. package/dist/modules/mcp/database/repositories/oauth-client.repository.d.ts +5 -0
  60. package/dist/modules/mcp/database/repositories/oauth-client.repository.js +26 -0
  61. package/dist/modules/mcp/database/repositories/oauth-client.repository.js.map +1 -0
  62. package/dist/modules/mcp/database/repositories/oauth-refresh-token.repository.d.ts +5 -0
  63. package/dist/modules/mcp/database/repositories/oauth-refresh-token.repository.js +26 -0
  64. package/dist/modules/mcp/database/repositories/oauth-refresh-token.repository.js.map +1 -0
  65. package/dist/modules/mcp/database/repositories/oauth-user-consent.repository.d.ts +6 -0
  66. package/dist/modules/mcp/database/repositories/oauth-user-consent.repository.js +33 -0
  67. package/dist/modules/mcp/database/repositories/oauth-user-consent.repository.js.map +1 -0
  68. package/dist/modules/mcp/dto/approve-consent-request.dto.d.ts +8 -0
  69. package/dist/modules/mcp/dto/approve-consent-request.dto.js +11 -0
  70. package/dist/modules/mcp/dto/approve-consent-request.dto.js.map +1 -0
  71. package/dist/modules/mcp/mcp-api-key.service.d.ts +6 -9
  72. package/dist/modules/mcp/mcp-api-key.service.js +32 -61
  73. package/dist/modules/mcp/mcp-api-key.service.js.map +1 -1
  74. package/dist/modules/mcp/mcp-oauth-authorization-code.service.d.ts +11 -0
  75. package/dist/modules/mcp/mcp-oauth-authorization-code.service.js +76 -0
  76. package/dist/modules/mcp/mcp-oauth-authorization-code.service.js.map +1 -0
  77. package/dist/modules/mcp/mcp-oauth-consent.service.d.ts +20 -0
  78. package/dist/modules/mcp/mcp-oauth-consent.service.js +87 -0
  79. package/dist/modules/mcp/mcp-oauth-consent.service.js.map +1 -0
  80. package/dist/modules/mcp/mcp-oauth-service.d.ts +31 -0
  81. package/dist/modules/mcp/mcp-oauth-service.js +164 -0
  82. package/dist/modules/mcp/mcp-oauth-service.js.map +1 -0
  83. package/dist/modules/mcp/mcp-oauth-token.service.d.ts +28 -0
  84. package/dist/modules/mcp/mcp-oauth-token.service.js +182 -0
  85. package/dist/modules/mcp/mcp-oauth-token.service.js.map +1 -0
  86. package/dist/modules/mcp/mcp-oauth.helpers.d.ts +4 -0
  87. package/dist/modules/mcp/mcp-oauth.helpers.js +24 -0
  88. package/dist/modules/mcp/mcp-oauth.helpers.js.map +1 -0
  89. package/dist/modules/mcp/mcp-server-middleware.service.d.ts +18 -0
  90. package/dist/modules/mcp/mcp-server-middleware.service.js +94 -0
  91. package/dist/modules/mcp/mcp-server-middleware.service.js.map +1 -0
  92. package/dist/modules/mcp/mcp.auth.consent.controller.d.ts +17 -0
  93. package/dist/modules/mcp/mcp.auth.consent.controller.js +120 -0
  94. package/dist/modules/mcp/mcp.auth.consent.controller.js.map +1 -0
  95. package/dist/modules/mcp/mcp.controller.d.ts +2 -1
  96. package/dist/modules/mcp/mcp.controller.js +11 -3
  97. package/dist/modules/mcp/mcp.controller.js.map +1 -1
  98. package/dist/modules/mcp/mcp.module.d.ts +1 -0
  99. package/dist/modules/mcp/mcp.module.js +11 -0
  100. package/dist/modules/mcp/mcp.module.js.map +1 -1
  101. package/dist/modules/mcp/mcp.oauth-clients.controller.d.ts +12 -0
  102. package/dist/modules/mcp/mcp.oauth-clients.controller.js +93 -0
  103. package/dist/modules/mcp/mcp.oauth-clients.controller.js.map +1 -0
  104. package/dist/modules/mcp/mcp.oauth.controller.d.ts +13 -0
  105. package/dist/modules/mcp/mcp.oauth.controller.js +124 -0
  106. package/dist/modules/mcp/mcp.oauth.controller.js.map +1 -0
  107. package/dist/modules/mcp/mcp.types.d.ts +1 -2
  108. package/dist/modules/mcp/oauth-session.service.d.ts +16 -0
  109. package/dist/modules/mcp/oauth-session.service.js +48 -0
  110. package/dist/modules/mcp/oauth-session.service.js.map +1 -0
  111. package/dist/modules/mcp/tools/search-workflows.tool.d.ts +2 -3
  112. package/dist/modules/mcp/tools/search-workflows.tool.js +11 -10
  113. package/dist/modules/mcp/tools/search-workflows.tool.js.map +1 -1
  114. package/dist/modules/provisioning.ee/provisioning.service.ee.d.ts +4 -2
  115. package/dist/modules/provisioning.ee/provisioning.service.ee.js +20 -1
  116. package/dist/modules/provisioning.ee/provisioning.service.ee.js.map +1 -1
  117. package/dist/public-api/v1/handlers/users/users.service.ee.d.ts +6 -2
  118. package/dist/public-api/v1/handlers/users/users.service.ee.js +10 -3
  119. package/dist/public-api/v1/handlers/users/users.service.ee.js.map +1 -1
  120. package/dist/public-api/v1/openapi.yml +1 -1
  121. package/dist/services/import.service.js +0 -5
  122. package/dist/services/import.service.js.map +1 -1
  123. package/dist/services/jwt.service.d.ts +1 -1
  124. package/dist/services/jwt.service.js.map +1 -1
  125. package/dist/sso.ee/oidc/oidc.service.ee.js +6 -4
  126. package/dist/sso.ee/oidc/oidc.service.ee.js.map +1 -1
  127. package/dist/sso.ee/saml/routes/saml.controller.ee.d.ts +2 -10
  128. package/dist/sso.ee/saml/routes/saml.controller.ee.js +2 -9
  129. package/dist/sso.ee/saml/routes/saml.controller.ee.js.map +1 -1
  130. package/dist/sso.ee/saml/saml-helpers.d.ts +4 -1
  131. package/dist/sso.ee/saml/saml-helpers.js +10 -3
  132. package/dist/sso.ee/saml/saml-helpers.js.map +1 -1
  133. package/dist/sso.ee/saml/saml.service.ee.d.ts +4 -1
  134. package/dist/sso.ee/saml/saml.service.ee.js +20 -12
  135. package/dist/sso.ee/saml/saml.service.ee.js.map +1 -1
  136. package/dist/sso.ee/saml/types.d.ts +2 -2
  137. package/dist/telemetry/index.js +17 -3
  138. package/dist/telemetry/index.js.map +1 -1
  139. package/dist/utils/validate-database-type.d.ts +3 -1
  140. package/dist/utils/validate-database-type.js +26 -4
  141. package/dist/utils/validate-database-type.js.map +1 -1
  142. package/dist/workflows/workflow-finder.service.d.ts +1 -0
  143. package/dist/workflows/workflow.request.d.ts +1 -0
  144. package/dist/workflows/workflow.service.d.ts +2 -1
  145. package/dist/workflows/workflow.service.js +1 -0
  146. package/dist/workflows/workflow.service.js.map +1 -1
  147. package/dist/workflows/workflows.controller.d.ts +4 -0
  148. package/package.json +25 -25
@@ -0,0 +1,11 @@
1
+ import type { AuthorizationCode } from './database/entities/oauth-authorization-code.entity';
2
+ import { AuthorizationCodeRepository } from './database/repositories/oauth-authorization-code.repository';
3
+ export declare class McpOAuthAuthorizationCodeService {
4
+ private readonly authorizationCodeRepository;
5
+ private readonly AUTHORIZATION_CODE_EXPIRY_MS;
6
+ constructor(authorizationCodeRepository: AuthorizationCodeRepository);
7
+ createAuthorizationCode(clientId: string, userId: string, redirectUri: string, codeChallenge: string, state: string | null): Promise<string>;
8
+ findAndValidateAuthorizationCode(authorizationCode: string, clientId: string): Promise<AuthorizationCode>;
9
+ validateAndConsumeAuthorizationCode(authorizationCode: string, clientId: string, redirectUri?: string): Promise<AuthorizationCode>;
10
+ getCodeChallenge(authorizationCode: string, clientId: string): Promise<string>;
11
+ }
@@ -0,0 +1,76 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.McpOAuthAuthorizationCodeService = void 0;
13
+ const constants_1 = require("@n8n/constants");
14
+ const di_1 = require("@n8n/di");
15
+ const node_crypto_1 = require("node:crypto");
16
+ const oauth_authorization_code_repository_1 = require("./database/repositories/oauth-authorization-code.repository");
17
+ let McpOAuthAuthorizationCodeService = class McpOAuthAuthorizationCodeService {
18
+ constructor(authorizationCodeRepository) {
19
+ this.authorizationCodeRepository = authorizationCodeRepository;
20
+ this.AUTHORIZATION_CODE_EXPIRY_MS = 10 * constants_1.Time.minutes.toMilliseconds;
21
+ }
22
+ async createAuthorizationCode(clientId, userId, redirectUri, codeChallenge, state) {
23
+ const code = (0, node_crypto_1.randomBytes)(32).toString('hex');
24
+ await this.authorizationCodeRepository.insert({
25
+ code,
26
+ clientId,
27
+ userId,
28
+ redirectUri,
29
+ codeChallenge,
30
+ codeChallengeMethod: 'S256',
31
+ state,
32
+ expiresAt: Date.now() + this.AUTHORIZATION_CODE_EXPIRY_MS,
33
+ used: false,
34
+ });
35
+ return code;
36
+ }
37
+ async findAndValidateAuthorizationCode(authorizationCode, clientId) {
38
+ const authRecord = await this.authorizationCodeRepository.findOne({
39
+ where: {
40
+ code: authorizationCode,
41
+ clientId,
42
+ },
43
+ });
44
+ if (!authRecord) {
45
+ throw new Error('Invalid authorization code');
46
+ }
47
+ if (authRecord.expiresAt < Date.now()) {
48
+ await this.authorizationCodeRepository.remove(authRecord);
49
+ throw new Error('Authorization code expired');
50
+ }
51
+ return authRecord;
52
+ }
53
+ async validateAndConsumeAuthorizationCode(authorizationCode, clientId, redirectUri) {
54
+ const authRecord = await this.findAndValidateAuthorizationCode(authorizationCode, clientId);
55
+ if (redirectUri && authRecord.redirectUri !== redirectUri) {
56
+ throw new Error('Redirect URI mismatch');
57
+ }
58
+ const result = await this.authorizationCodeRepository.update({ code: authorizationCode, used: false }, { used: true });
59
+ const numAffected = result.affected ?? 0;
60
+ if (numAffected < 1) {
61
+ throw new Error('Authorization code already used');
62
+ }
63
+ authRecord.used = true;
64
+ return authRecord;
65
+ }
66
+ async getCodeChallenge(authorizationCode, clientId) {
67
+ const authRecord = await this.findAndValidateAuthorizationCode(authorizationCode, clientId);
68
+ return authRecord.codeChallenge;
69
+ }
70
+ };
71
+ exports.McpOAuthAuthorizationCodeService = McpOAuthAuthorizationCodeService;
72
+ exports.McpOAuthAuthorizationCodeService = McpOAuthAuthorizationCodeService = __decorate([
73
+ (0, di_1.Service)(),
74
+ __metadata("design:paramtypes", [oauth_authorization_code_repository_1.AuthorizationCodeRepository])
75
+ ], McpOAuthAuthorizationCodeService);
76
+ //# sourceMappingURL=mcp-oauth-authorization-code.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-oauth-authorization-code.service.js","sourceRoot":"","sources":["../../../src/modules/mcp/mcp-oauth-authorization-code.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAsC;AACtC,gCAAkC;AAClC,6CAA0C;AAG1C,qHAA0G;AAOnG,IAAM,gCAAgC,GAAtC,MAAM,gCAAgC;IAG5C,YAA6B,2BAAwD;QAAxD,gCAA2B,GAA3B,2BAA2B,CAA6B;QAFpE,iCAA4B,GAAG,EAAE,GAAG,gBAAI,CAAC,OAAO,CAAC,cAAc,CAAC;IAEO,CAAC;IAMzF,KAAK,CAAC,uBAAuB,CAC5B,QAAgB,EAChB,MAAc,EACd,WAAmB,EACnB,aAAqB,EACrB,KAAoB;QAEpB,MAAM,IAAI,GAAG,IAAA,yBAAW,EAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAE7C,MAAM,IAAI,CAAC,2BAA2B,CAAC,MAAM,CAAC;YAC7C,IAAI;YACJ,QAAQ;YACR,MAAM;YACN,WAAW;YACX,aAAa;YACb,mBAAmB,EAAE,MAAM;YAC3B,KAAK;YACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,4BAA4B;YACzD,IAAI,EAAE,KAAK;SACX,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC;IACb,CAAC;IAMD,KAAK,CAAC,gCAAgC,CACrC,iBAAyB,EACzB,QAAgB;QAEhB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,2BAA2B,CAAC,OAAO,CAAC;YACjE,KAAK,EAAE;gBACN,IAAI,EAAE,iBAAiB;gBACvB,QAAQ;aACR;SACD,CAAC,CAAC;QAEH,IAAI,CAAC,UAAU,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,UAAU,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YACvC,MAAM,IAAI,CAAC,2BAA2B,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC/C,CAAC;QAED,OAAO,UAAU,CAAC;IACnB,CAAC;IAMD,KAAK,CAAC,mCAAmC,CACxC,iBAAyB,EACzB,QAAgB,EAChB,WAAoB;QAEpB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,gCAAgC,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;QAE5F,IAAI,WAAW,IAAI,UAAU,CAAC,WAAW,KAAK,WAAW,EAAE,CAAC;YAC3D,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC1C,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,2BAA2B,CAAC,MAAM,CAC3D,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,KAAK,EAAE,EACxC,EAAE,IAAI,EAAE,IAAI,EAAE,CACd,CAAC;QAEF,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;QACzC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACpD,CAAC;QAED,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC;QACvB,OAAO,UAAU,CAAC;IACnB,CAAC;IAMD,KAAK,CAAC,gBAAgB,CAAC,iBAAyB,EAAE,QAAgB;QACjE,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,gCAAgC,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;QAC5F,OAAO,UAAU,CAAC,aAAa,CAAC;IACjC,CAAC;CACD,CAAA;AAjGY,4EAAgC;2CAAhC,gCAAgC;IAD5C,IAAA,YAAO,GAAE;qCAIiD,iEAA2B;GAHzE,gCAAgC,CAiG5C"}
@@ -0,0 +1,20 @@
1
+ import { Logger } from '@n8n/backend-common';
2
+ import { OAuthClientRepository } from './database/repositories/oauth-client.repository';
3
+ import { UserConsentRepository } from './database/repositories/oauth-user-consent.repository';
4
+ import { McpOAuthAuthorizationCodeService } from './mcp-oauth-authorization-code.service';
5
+ import { OAuthSessionService } from './oauth-session.service';
6
+ export declare class McpOAuthConsentService {
7
+ private readonly logger;
8
+ private readonly oauthSessionService;
9
+ private readonly oauthClientRepository;
10
+ private readonly userConsentRepository;
11
+ private readonly authorizationCodeService;
12
+ constructor(logger: Logger, oauthSessionService: OAuthSessionService, oauthClientRepository: OAuthClientRepository, userConsentRepository: UserConsentRepository, authorizationCodeService: McpOAuthAuthorizationCodeService);
13
+ getConsentDetails(sessionToken: string): Promise<{
14
+ clientName: string;
15
+ clientId: string;
16
+ } | null>;
17
+ handleConsentDecision(sessionToken: string, userId: string, approved: boolean): Promise<{
18
+ redirectUrl: string;
19
+ }>;
20
+ }
@@ -0,0 +1,87 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.McpOAuthConsentService = void 0;
13
+ const backend_common_1 = require("@n8n/backend-common");
14
+ const di_1 = require("@n8n/di");
15
+ const n8n_workflow_1 = require("n8n-workflow");
16
+ const oauth_client_repository_1 = require("./database/repositories/oauth-client.repository");
17
+ const oauth_user_consent_repository_1 = require("./database/repositories/oauth-user-consent.repository");
18
+ const mcp_oauth_authorization_code_service_1 = require("./mcp-oauth-authorization-code.service");
19
+ const mcp_oauth_helpers_1 = require("./mcp-oauth.helpers");
20
+ const oauth_session_service_1 = require("./oauth-session.service");
21
+ let McpOAuthConsentService = class McpOAuthConsentService {
22
+ constructor(logger, oauthSessionService, oauthClientRepository, userConsentRepository, authorizationCodeService) {
23
+ this.logger = logger;
24
+ this.oauthSessionService = oauthSessionService;
25
+ this.oauthClientRepository = oauthClientRepository;
26
+ this.userConsentRepository = userConsentRepository;
27
+ this.authorizationCodeService = authorizationCodeService;
28
+ }
29
+ async getConsentDetails(sessionToken) {
30
+ try {
31
+ const sessionPayload = this.oauthSessionService.verifySession(sessionToken);
32
+ const client = await this.oauthClientRepository.findOne({
33
+ where: { id: sessionPayload.clientId },
34
+ });
35
+ if (!client) {
36
+ return null;
37
+ }
38
+ return {
39
+ clientName: client.name,
40
+ clientId: client.id,
41
+ };
42
+ }
43
+ catch (error) {
44
+ this.logger.error('Error getting consent details', { error });
45
+ return null;
46
+ }
47
+ }
48
+ async handleConsentDecision(sessionToken, userId, approved) {
49
+ let sessionPayload;
50
+ try {
51
+ sessionPayload = this.oauthSessionService.verifySession(sessionToken);
52
+ }
53
+ catch (error) {
54
+ throw new n8n_workflow_1.UserError('Invalid or expired session');
55
+ }
56
+ if (!approved) {
57
+ const redirectUrl = mcp_oauth_helpers_1.McpOAuthHelpers.buildErrorRedirectUrl(sessionPayload.redirectUri, 'access_denied', 'User denied the authorization request', sessionPayload.state);
58
+ this.logger.info('Consent denied', {
59
+ clientId: sessionPayload.clientId,
60
+ userId,
61
+ });
62
+ return { redirectUrl };
63
+ }
64
+ await this.userConsentRepository.insert({
65
+ userId,
66
+ clientId: sessionPayload.clientId,
67
+ grantedAt: Date.now(),
68
+ });
69
+ const code = await this.authorizationCodeService.createAuthorizationCode(sessionPayload.clientId, userId, sessionPayload.redirectUri, sessionPayload.codeChallenge, sessionPayload.state);
70
+ const successRedirectUrl = mcp_oauth_helpers_1.McpOAuthHelpers.buildSuccessRedirectUrl(sessionPayload.redirectUri, code, sessionPayload.state);
71
+ this.logger.info('Consent approved', {
72
+ clientId: sessionPayload.clientId,
73
+ userId,
74
+ });
75
+ return { redirectUrl: successRedirectUrl };
76
+ }
77
+ };
78
+ exports.McpOAuthConsentService = McpOAuthConsentService;
79
+ exports.McpOAuthConsentService = McpOAuthConsentService = __decorate([
80
+ (0, di_1.Service)(),
81
+ __metadata("design:paramtypes", [backend_common_1.Logger,
82
+ oauth_session_service_1.OAuthSessionService,
83
+ oauth_client_repository_1.OAuthClientRepository,
84
+ oauth_user_consent_repository_1.UserConsentRepository,
85
+ mcp_oauth_authorization_code_service_1.McpOAuthAuthorizationCodeService])
86
+ ], McpOAuthConsentService);
87
+ //# sourceMappingURL=mcp-oauth-consent.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-oauth-consent.service.js","sourceRoot":"","sources":["../../../src/modules/mcp/mcp-oauth-consent.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { OAuthRegisteredClientsStore } from '@modelcontextprotocol/sdk/server/auth/clients';
2
+ import type { AuthorizationParams, OAuthServerProvider } from '@modelcontextprotocol/sdk/server/auth/provider';
3
+ import type { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types';
4
+ import type { OAuthClientInformationFull, OAuthTokens, OAuthTokenRevocationRequest } from '@modelcontextprotocol/sdk/shared/auth';
5
+ import { Logger } from '@n8n/backend-common';
6
+ import type { Response } from 'express';
7
+ import { OAuthClient } from './database/entities/oauth-client.entity';
8
+ import { OAuthClientRepository } from './database/repositories/oauth-client.repository';
9
+ import { UserConsentRepository } from './database/repositories/oauth-user-consent.repository';
10
+ import { McpOAuthAuthorizationCodeService } from './mcp-oauth-authorization-code.service';
11
+ import { McpOAuthTokenService } from './mcp-oauth-token.service';
12
+ import { OAuthSessionService } from './oauth-session.service';
13
+ export declare const SUPPORTED_SCOPES: string[];
14
+ export declare class McpOAuthService implements OAuthServerProvider {
15
+ private readonly logger;
16
+ private readonly oauthSessionService;
17
+ private readonly oauthClientRepository;
18
+ private readonly tokenService;
19
+ private readonly authorizationCodeService;
20
+ private readonly userConsentRepository;
21
+ constructor(logger: Logger, oauthSessionService: OAuthSessionService, oauthClientRepository: OAuthClientRepository, tokenService: McpOAuthTokenService, authorizationCodeService: McpOAuthAuthorizationCodeService, userConsentRepository: UserConsentRepository);
22
+ get clientsStore(): OAuthRegisteredClientsStore;
23
+ authorize(client: OAuthClientInformationFull, params: AuthorizationParams, res: Response): Promise<void>;
24
+ challengeForAuthorizationCode(client: OAuthClientInformationFull, authorizationCode: string): Promise<string>;
25
+ exchangeAuthorizationCode(client: OAuthClientInformationFull, authorizationCode: string, _codeVerifier?: string, redirectUri?: string): Promise<OAuthTokens>;
26
+ exchangeRefreshToken(client: OAuthClientInformationFull, refreshToken: string, _scopes?: string[]): Promise<OAuthTokens>;
27
+ verifyAccessToken(token: string): Promise<AuthInfo>;
28
+ revokeToken(client: OAuthClientInformationFull, request: OAuthTokenRevocationRequest): Promise<void>;
29
+ getAllClients(userId: string): Promise<Array<Omit<OAuthClient, 'clientSecret' | 'clientSecretExpiresAt' | 'setUpdateDate'>>>;
30
+ deleteClient(clientId: string): Promise<void>;
31
+ }
@@ -0,0 +1,164 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.McpOAuthService = exports.SUPPORTED_SCOPES = void 0;
13
+ const backend_common_1 = require("@n8n/backend-common");
14
+ const di_1 = require("@n8n/di");
15
+ const oauth_client_repository_1 = require("./database/repositories/oauth-client.repository");
16
+ const oauth_user_consent_repository_1 = require("./database/repositories/oauth-user-consent.repository");
17
+ const mcp_oauth_authorization_code_service_1 = require("./mcp-oauth-authorization-code.service");
18
+ const mcp_oauth_token_service_1 = require("./mcp-oauth-token.service");
19
+ const oauth_session_service_1 = require("./oauth-session.service");
20
+ exports.SUPPORTED_SCOPES = ['tool:listWorkflows', 'tool:getWorkflowDetails'];
21
+ let McpOAuthService = class McpOAuthService {
22
+ constructor(logger, oauthSessionService, oauthClientRepository, tokenService, authorizationCodeService, userConsentRepository) {
23
+ this.logger = logger;
24
+ this.oauthSessionService = oauthSessionService;
25
+ this.oauthClientRepository = oauthClientRepository;
26
+ this.tokenService = tokenService;
27
+ this.authorizationCodeService = authorizationCodeService;
28
+ this.userConsentRepository = userConsentRepository;
29
+ }
30
+ get clientsStore() {
31
+ return {
32
+ getClient: async (clientId) => {
33
+ const client = await this.oauthClientRepository.findOneBy({ id: clientId });
34
+ if (!client) {
35
+ return undefined;
36
+ }
37
+ return {
38
+ client_id: client.id,
39
+ client_name: client.name,
40
+ redirect_uris: client.redirectUris,
41
+ grant_types: client.grantTypes,
42
+ token_endpoint_auth_method: client.tokenEndpointAuthMethod,
43
+ ...(client.clientSecret && { client_secret: client.clientSecret }),
44
+ ...(client.clientSecretExpiresAt && {
45
+ client_secret_expires_at: client.clientSecretExpiresAt,
46
+ }),
47
+ response_types: ['code'],
48
+ scope: exports.SUPPORTED_SCOPES.join(' '),
49
+ };
50
+ },
51
+ registerClient: async (client) => {
52
+ try {
53
+ await this.oauthClientRepository.insert({
54
+ id: client.client_id,
55
+ name: client.client_name,
56
+ redirectUris: client.redirect_uris,
57
+ grantTypes: client.grant_types,
58
+ clientSecret: client.client_secret ?? null,
59
+ clientSecretExpiresAt: client.client_secret_expires_at ?? null,
60
+ tokenEndpointAuthMethod: client.token_endpoint_auth_method ?? 'none',
61
+ });
62
+ }
63
+ catch (error) {
64
+ this.logger.error('Error registering OAuth client', {
65
+ error,
66
+ clientId: client.client_id,
67
+ });
68
+ }
69
+ return client;
70
+ },
71
+ };
72
+ }
73
+ async authorize(client, params, res) {
74
+ this.logger.debug('Starting OAuth authorization', { clientId: client.client_id });
75
+ try {
76
+ this.oauthSessionService.createSession(res, {
77
+ clientId: client.client_id,
78
+ redirectUri: params.redirectUri,
79
+ codeChallenge: params.codeChallenge,
80
+ state: params.state ?? null,
81
+ });
82
+ res.redirect('/oauth/consent');
83
+ }
84
+ catch (error) {
85
+ this.logger.error('Error in authorize method', { error, clientId: client.client_id });
86
+ this.oauthSessionService.clearSession(res);
87
+ res.status(500).json({ error: 'server_error', error_description: 'Internal server error' });
88
+ }
89
+ }
90
+ async challengeForAuthorizationCode(client, authorizationCode) {
91
+ return await this.authorizationCodeService.getCodeChallenge(authorizationCode, client.client_id);
92
+ }
93
+ async exchangeAuthorizationCode(client, authorizationCode, _codeVerifier, redirectUri) {
94
+ const authRecord = await this.authorizationCodeService.validateAndConsumeAuthorizationCode(authorizationCode, client.client_id, redirectUri);
95
+ const { accessToken, refreshToken } = this.tokenService.generateTokenPair(authRecord.userId, client.client_id);
96
+ await this.tokenService.saveTokenPair(accessToken, refreshToken, client.client_id, authRecord.userId);
97
+ this.logger.info('Authorization code exchanged for tokens', {
98
+ clientId: client.client_id,
99
+ userId: authRecord.userId,
100
+ });
101
+ return {
102
+ access_token: accessToken,
103
+ token_type: 'Bearer',
104
+ expires_in: 3600,
105
+ refresh_token: refreshToken,
106
+ };
107
+ }
108
+ async exchangeRefreshToken(client, refreshToken, _scopes) {
109
+ return await this.tokenService.validateAndRotateRefreshToken(refreshToken, client.client_id);
110
+ }
111
+ async verifyAccessToken(token) {
112
+ return await this.tokenService.verifyAccessToken(token);
113
+ }
114
+ async revokeToken(client, request) {
115
+ const { token, token_type_hint } = request;
116
+ if (!token_type_hint || token_type_hint === 'access_token') {
117
+ const revoked = await this.tokenService.revokeAccessToken(token, client.client_id);
118
+ if (revoked) {
119
+ return;
120
+ }
121
+ }
122
+ if (!token_type_hint || token_type_hint === 'refresh_token') {
123
+ const revoked = await this.tokenService.revokeRefreshToken(token, client.client_id);
124
+ if (revoked) {
125
+ return;
126
+ }
127
+ }
128
+ this.logger.debug('Token revocation requested for unknown token', {
129
+ clientId: client.client_id,
130
+ });
131
+ }
132
+ async getAllClients(userId) {
133
+ const userConsents = await this.userConsentRepository.findByUserWithClient(userId);
134
+ return userConsents.map((consent) => {
135
+ const { clientSecret, clientSecretExpiresAt, ...sanitizedClient } = consent.client;
136
+ return sanitizedClient;
137
+ });
138
+ }
139
+ async deleteClient(clientId) {
140
+ const client = await this.oauthClientRepository.findOne({
141
+ where: { id: clientId },
142
+ });
143
+ if (!client) {
144
+ throw new Error(`OAuth client with ID ${clientId} not found`);
145
+ }
146
+ this.logger.info('Deleting OAuth client and related data', { clientId });
147
+ await this.oauthClientRepository.delete({ id: clientId });
148
+ this.logger.info('OAuth client deleted successfully', {
149
+ clientId,
150
+ clientName: client.name,
151
+ });
152
+ }
153
+ };
154
+ exports.McpOAuthService = McpOAuthService;
155
+ exports.McpOAuthService = McpOAuthService = __decorate([
156
+ (0, di_1.Service)(),
157
+ __metadata("design:paramtypes", [backend_common_1.Logger,
158
+ oauth_session_service_1.OAuthSessionService,
159
+ oauth_client_repository_1.OAuthClientRepository,
160
+ mcp_oauth_token_service_1.McpOAuthTokenService,
161
+ mcp_oauth_authorization_code_service_1.McpOAuthAuthorizationCodeService,
162
+ oauth_user_consent_repository_1.UserConsentRepository])
163
+ ], McpOAuthService);
164
+ //# sourceMappingURL=mcp-oauth-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-oauth-service.js","sourceRoot":"","sources":["../../../src/modules/mcp/mcp-oauth-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types';
2
+ import { OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth';
3
+ import { Logger } from '@n8n/backend-common';
4
+ import { User, UserRepository } from '@n8n/db';
5
+ import { JwtService } from '../../services/jwt.service';
6
+ import { AccessTokenRepository } from './database/repositories/oauth-access-token.repository';
7
+ import { RefreshTokenRepository } from './database/repositories/oauth-refresh-token.repository';
8
+ export declare class McpOAuthTokenService {
9
+ private readonly logger;
10
+ private readonly jwtService;
11
+ private readonly userRepository;
12
+ private readonly accessTokenRepository;
13
+ private readonly refreshTokenRepository;
14
+ private readonly MCP_AUDIENCE;
15
+ private readonly ACCESS_TOKEN_EXPIRY_SECONDS;
16
+ private readonly REFRESH_TOKEN_EXPIRY_MS;
17
+ constructor(logger: Logger, jwtService: JwtService, userRepository: UserRepository, accessTokenRepository: AccessTokenRepository, refreshTokenRepository: RefreshTokenRepository);
18
+ generateTokenPair(userId: string, clientId: string): {
19
+ accessToken: string;
20
+ refreshToken: string;
21
+ };
22
+ saveTokenPair(accessToken: string, refreshToken: string, clientId: string, userId: string): Promise<void>;
23
+ validateAndRotateRefreshToken(refreshToken: string, clientId: string): Promise<OAuthTokens>;
24
+ verifyAccessToken(token: string): Promise<AuthInfo>;
25
+ verifyOAuthAccessToken(token: string): Promise<User | null>;
26
+ revokeAccessToken(token: string, clientId: string): Promise<boolean>;
27
+ revokeRefreshToken(token: string, clientId: string): Promise<boolean>;
28
+ }
@@ -0,0 +1,182 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.McpOAuthTokenService = void 0;
13
+ const backend_common_1 = require("@n8n/backend-common");
14
+ const constants_1 = require("@n8n/constants");
15
+ const db_1 = require("@n8n/db");
16
+ const di_1 = require("@n8n/di");
17
+ const typeorm_1 = require("@n8n/typeorm");
18
+ const node_crypto_1 = require("node:crypto");
19
+ const jwt_service_1 = require("../../services/jwt.service");
20
+ const oauth_access_token_entity_1 = require("./database/entities/oauth-access-token.entity");
21
+ const oauth_refresh_token_entity_1 = require("./database/entities/oauth-refresh-token.entity");
22
+ const oauth_access_token_repository_1 = require("./database/repositories/oauth-access-token.repository");
23
+ const oauth_refresh_token_repository_1 = require("./database/repositories/oauth-refresh-token.repository");
24
+ let McpOAuthTokenService = class McpOAuthTokenService {
25
+ constructor(logger, jwtService, userRepository, accessTokenRepository, refreshTokenRepository) {
26
+ this.logger = logger;
27
+ this.jwtService = jwtService;
28
+ this.userRepository = userRepository;
29
+ this.accessTokenRepository = accessTokenRepository;
30
+ this.refreshTokenRepository = refreshTokenRepository;
31
+ this.MCP_AUDIENCE = 'mcp-server-api';
32
+ this.ACCESS_TOKEN_EXPIRY_SECONDS = 1 * constants_1.Time.hours.toSeconds;
33
+ this.REFRESH_TOKEN_EXPIRY_MS = 30 * constants_1.Time.days.toMilliseconds;
34
+ }
35
+ generateTokenPair(userId, clientId) {
36
+ const accessToken = this.jwtService.sign({
37
+ sub: userId,
38
+ aud: this.MCP_AUDIENCE,
39
+ client_id: clientId,
40
+ jti: (0, node_crypto_1.randomUUID)(),
41
+ iat: Math.floor(Date.now() / 1000),
42
+ exp: Math.floor(Date.now() / 1000) + this.ACCESS_TOKEN_EXPIRY_SECONDS,
43
+ meta: {
44
+ isOAuth: true,
45
+ },
46
+ });
47
+ const refreshToken = (0, node_crypto_1.randomBytes)(32).toString('hex');
48
+ return { accessToken, refreshToken };
49
+ }
50
+ async saveTokenPair(accessToken, refreshToken, clientId, userId) {
51
+ await this.accessTokenRepository.manager.transaction(async (transactionManager) => {
52
+ await transactionManager.insert(this.accessTokenRepository.target, {
53
+ token: accessToken,
54
+ clientId,
55
+ userId,
56
+ });
57
+ await transactionManager.insert(this.refreshTokenRepository.target, {
58
+ token: refreshToken,
59
+ clientId,
60
+ userId,
61
+ expiresAt: Date.now() + this.REFRESH_TOKEN_EXPIRY_MS,
62
+ });
63
+ });
64
+ }
65
+ async validateAndRotateRefreshToken(refreshToken, clientId) {
66
+ return await (0, db_1.withTransaction)(this.refreshTokenRepository.manager, undefined, async (trx) => {
67
+ const now = Date.now();
68
+ const refreshTokenRecord = await trx.findOne(oauth_refresh_token_entity_1.RefreshToken, {
69
+ where: {
70
+ token: refreshToken,
71
+ clientId,
72
+ },
73
+ });
74
+ if (!refreshTokenRecord) {
75
+ throw new Error('Invalid refresh token');
76
+ }
77
+ const result = await trx.delete(oauth_refresh_token_entity_1.RefreshToken, {
78
+ token: refreshToken,
79
+ clientId,
80
+ expiresAt: (0, typeorm_1.MoreThanOrEqual)(now),
81
+ });
82
+ const numAffected = result.affected ?? 0;
83
+ if (numAffected < 1) {
84
+ throw new Error('Invalid refresh token');
85
+ }
86
+ const { accessToken, refreshToken: newRefreshToken } = this.generateTokenPair(refreshTokenRecord.userId, clientId);
87
+ await trx.insert(oauth_access_token_entity_1.AccessToken, {
88
+ token: accessToken,
89
+ clientId,
90
+ userId: refreshTokenRecord.userId,
91
+ });
92
+ await trx.insert(oauth_refresh_token_entity_1.RefreshToken, {
93
+ token: newRefreshToken,
94
+ clientId,
95
+ userId: refreshTokenRecord.userId,
96
+ expiresAt: now + this.REFRESH_TOKEN_EXPIRY_MS,
97
+ });
98
+ this.logger.info('Refresh token rotated and new access token issued', {
99
+ clientId,
100
+ userId: refreshTokenRecord.userId,
101
+ });
102
+ return {
103
+ access_token: accessToken,
104
+ token_type: 'Bearer',
105
+ expires_in: this.ACCESS_TOKEN_EXPIRY_SECONDS,
106
+ refresh_token: newRefreshToken,
107
+ };
108
+ });
109
+ }
110
+ async verifyAccessToken(token) {
111
+ let decoded;
112
+ try {
113
+ decoded = this.jwtService.verify(token, { audience: this.MCP_AUDIENCE });
114
+ }
115
+ catch (error) {
116
+ throw new Error('Invalid access token: JWT verification failed');
117
+ }
118
+ const accessTokenRecord = await this.accessTokenRepository.findOne({
119
+ where: { token },
120
+ });
121
+ if (!accessTokenRecord) {
122
+ throw new Error('Invalid access token: not found in database');
123
+ }
124
+ return {
125
+ token,
126
+ clientId: decoded.client_id,
127
+ scopes: [],
128
+ extra: {
129
+ userId: decoded.sub,
130
+ },
131
+ };
132
+ }
133
+ async verifyOAuthAccessToken(token) {
134
+ try {
135
+ const authInfo = await this.verifyAccessToken(token);
136
+ const userId = authInfo.extra?.userId;
137
+ if (!userId) {
138
+ return null;
139
+ }
140
+ const user = await this.userRepository.findOne({
141
+ where: { id: userId },
142
+ relations: ['role'],
143
+ });
144
+ return user;
145
+ }
146
+ catch (error) {
147
+ return null;
148
+ }
149
+ }
150
+ async revokeAccessToken(token, clientId) {
151
+ const result = await this.accessTokenRepository.delete({
152
+ token,
153
+ clientId,
154
+ });
155
+ const revoked = (result.affected ?? 0) > 0;
156
+ if (revoked) {
157
+ this.logger.info('Access token revoked', { clientId });
158
+ }
159
+ return revoked;
160
+ }
161
+ async revokeRefreshToken(token, clientId) {
162
+ const result = await this.refreshTokenRepository.delete({
163
+ token,
164
+ clientId,
165
+ });
166
+ const revoked = (result.affected ?? 0) > 0;
167
+ if (revoked) {
168
+ this.logger.info('Refresh token revoked', { clientId });
169
+ }
170
+ return revoked;
171
+ }
172
+ };
173
+ exports.McpOAuthTokenService = McpOAuthTokenService;
174
+ exports.McpOAuthTokenService = McpOAuthTokenService = __decorate([
175
+ (0, di_1.Service)(),
176
+ __metadata("design:paramtypes", [backend_common_1.Logger,
177
+ jwt_service_1.JwtService,
178
+ db_1.UserRepository,
179
+ oauth_access_token_repository_1.AccessTokenRepository,
180
+ oauth_refresh_token_repository_1.RefreshTokenRepository])
181
+ ], McpOAuthTokenService);
182
+ //# sourceMappingURL=mcp-oauth-token.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-oauth-token.service.js","sourceRoot":"","sources":["../../../src/modules/mcp/mcp-oauth-token.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,wDAA6C;AAC7C,8CAAsC;AACtC,gCAAgE;AAChE,gCAAkC;AAClC,0CAA+C;AAC/C,6CAAsD;AAEtD,wDAAoD;AAEpD,6FAA4E;AAC5E,+FAA8E;AAC9E,yGAA8F;AAC9F,2GAAgG;AAOzF,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAKhC,YACkB,MAAc,EACd,UAAsB,EACtB,cAA8B,EAC9B,qBAA4C,EAC5C,sBAA8C;QAJ9C,WAAM,GAAN,MAAM,CAAQ;QACd,eAAU,GAAV,UAAU,CAAY;QACtB,mBAAc,GAAd,cAAc,CAAgB;QAC9B,0BAAqB,GAArB,qBAAqB,CAAuB;QAC5C,2BAAsB,GAAtB,sBAAsB,CAAwB;QAT/C,iBAAY,GAAG,gBAAgB,CAAC;QAChC,gCAA2B,GAAG,CAAC,GAAG,gBAAI,CAAC,KAAK,CAAC,SAAS,CAAC;QACvD,4BAAuB,GAAG,EAAE,GAAG,gBAAI,CAAC,IAAI,CAAC,cAAc,CAAC;IAQtE,CAAC;IAEJ,iBAAiB,CAChB,MAAc,EACd,QAAgB;QAEhB,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YACxC,GAAG,EAAE,MAAM;YACX,GAAG,EAAE,IAAI,CAAC,YAAY;YACtB,SAAS,EAAE,QAAQ;YACnB,GAAG,EAAE,IAAA,wBAAU,GAAE;YACjB,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YAClC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,2BAA2B;YACrE,IAAI,EAAE;gBACL,OAAO,EAAE,IAAI;aACb;SACD,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,IAAA,yBAAW,EAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAErD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,aAAa,CAClB,WAAmB,EACnB,YAAoB,EACpB,QAAgB,EAChB,MAAc;QAEd,MAAM,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,kBAAkB,EAAE,EAAE;YACjF,MAAM,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,MAAM,EAAE;gBAClE,KAAK,EAAE,WAAW;gBAClB,QAAQ;gBACR,MAAM;aACN,CAAC,CAAC;YAEH,MAAM,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,MAAM,EAAE;gBACnE,KAAK,EAAE,YAAY;gBACnB,QAAQ;gBACR,MAAM;gBACN,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,uBAAuB;aACpD,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,6BAA6B,CAClC,YAAoB,EACpB,QAAgB;QAEhB,OAAO,MAAM,IAAA,oBAAe,EAAC,IAAI,CAAC,sBAAsB,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC1F,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAEvB,MAAM,kBAAkB,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,yCAAY,EAAE;gBAC1D,KAAK,EAAE;oBACN,KAAK,EAAE,YAAY;oBACnB,QAAQ;iBACR;aACD,CAAC,CAAC;YAEH,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAC1C,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,yCAAY,EAAE;gBAC7C,KAAK,EAAE,YAAY;gBACnB,QAAQ;gBACR,SAAS,EAAE,IAAA,yBAAe,EAAC,GAAG,CAAC;aAC/B,CAAC,CAAC;YAEH,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;YACzC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAC1C,CAAC;YAED,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC,iBAAiB,CAC5E,kBAAkB,CAAC,MAAM,EACzB,QAAQ,CACR,CAAC;YAEF,MAAM,GAAG,CAAC,MAAM,CAAC,uCAAW,EAAE;gBAC7B,KAAK,EAAE,WAAW;gBAClB,QAAQ;gBACR,MAAM,EAAE,kBAAkB,CAAC,MAAM;aACjC,CAAC,CAAC;YAEH,MAAM,GAAG,CAAC,MAAM,CAAC,yCAAY,EAAE;gBAC9B,KAAK,EAAE,eAAe;gBACtB,QAAQ;gBACR,MAAM,EAAE,kBAAkB,CAAC,MAAM;gBACjC,SAAS,EAAE,GAAG,GAAG,IAAI,CAAC,uBAAuB;aAC7C,CAAC,CAAC;YAEH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mDAAmD,EAAE;gBACrE,QAAQ;gBACR,MAAM,EAAE,kBAAkB,CAAC,MAAM;aACjC,CAAC,CAAC;YAEH,OAAO;gBACN,YAAY,EAAE,WAAW;gBACzB,UAAU,EAAE,QAAQ;gBACpB,UAAU,EAAE,IAAI,CAAC,2BAA2B;gBAC5C,aAAa,EAAE,eAAe;aAC9B,CAAC;QACH,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,KAAa;QACpC,IAAI,OAAO,CAAC;QAEZ,IAAI,CAAC;YACJ,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QAC1E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,iBAAiB,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC;YAClE,KAAK,EAAE,EAAE,KAAK,EAAE;SAChB,CAAC,CAAC;QAEH,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QAChE,CAAC;QAED,OAAO;YACN,KAAK;YACL,QAAQ,EAAE,OAAO,CAAC,SAAS;YAC3B,MAAM,EAAE,EAAE;YACV,KAAK,EAAE;gBACN,MAAM,EAAE,OAAO,CAAC,GAAG;aACnB;SACD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAC,KAAa;QACzC,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;YAErD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,MAAgB,CAAC;YAChD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACb,OAAO,IAAI,CAAC;YACb,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;gBAC9C,KAAK,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE;gBACrB,SAAS,EAAE,CAAC,MAAM,CAAC;aACnB,CAAC,CAAC;YAEH,OAAO,IAAI,CAAC;QACb,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC;QACb,CAAC;IACF,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,KAAa,EAAE,QAAgB;QACtD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC;YACtD,KAAK;YACL,QAAQ;SACR,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAE3C,IAAI,OAAO,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,OAAO,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,KAAa,EAAE,QAAgB;QACvD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC;YACvD,KAAK;YACL,QAAQ;SACR,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAE3C,IAAI,OAAO,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QACzD,CAAC;QAED,OAAO,OAAO,CAAC;IAChB,CAAC;CACD,CAAA;AAjMY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,YAAO,GAAE;qCAOiB,uBAAM;QACF,wBAAU;QACN,mBAAc;QACP,qDAAqB;QACpB,uDAAsB;GAVpD,oBAAoB,CAiMhC"}
@@ -0,0 +1,4 @@
1
+ export declare class McpOAuthHelpers {
2
+ static buildSuccessRedirectUrl(redirectUri: string, code: string, state: string | null): string;
3
+ static buildErrorRedirectUrl(redirectUri: string, error: string, errorDescription: string, state: string | null): string;
4
+ }