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.
- package/dist/auth/auth.service.js +1 -0
- package/dist/auth/auth.service.js.map +1 -1
- package/dist/build.tsbuildinfo +1 -1
- package/dist/controller.registry.d.ts +1 -0
- package/dist/controller.registry.js +37 -12
- package/dist/controller.registry.js.map +1 -1
- package/dist/controllers/auth.controller.js +3 -1
- package/dist/controllers/auth.controller.js.map +1 -1
- package/dist/events/maps/relay.event-map.d.ts +1 -1
- package/dist/middlewares/list-query/dtos/workflow.filter.dto.d.ts +1 -1
- package/dist/middlewares/list-query/dtos/workflow.filter.dto.js +1 -1
- package/dist/middlewares/list-query/dtos/workflow.filter.dto.js.map +1 -1
- package/dist/middlewares/list-query/dtos/workflow.select.dto.js +1 -0
- package/dist/middlewares/list-query/dtos/workflow.select.dto.js.map +1 -1
- package/dist/modules/breaking-changes/breaking-changes.controller.d.ts +7 -3
- package/dist/modules/breaking-changes/breaking-changes.controller.js +39 -6
- package/dist/modules/breaking-changes/breaking-changes.controller.js.map +1 -1
- package/dist/modules/breaking-changes/breaking-changes.service.d.ts +9 -6
- package/dist/modules/breaking-changes/breaking-changes.service.js +67 -38
- package/dist/modules/breaking-changes/breaking-changes.service.js.map +1 -1
- package/dist/modules/breaking-changes/rules/v2/file-access.rule.d.ts +5 -4
- package/dist/modules/breaking-changes/rules/v2/file-access.rule.js +4 -3
- package/dist/modules/breaking-changes/rules/v2/file-access.rule.js.map +1 -1
- package/dist/modules/breaking-changes/rules/v2/process-env-access.rule.d.ts +5 -4
- package/dist/modules/breaking-changes/rules/v2/process-env-access.rule.js +11 -13
- package/dist/modules/breaking-changes/rules/v2/process-env-access.rule.js.map +1 -1
- package/dist/modules/breaking-changes/rules/v2/removed-nodes.rule.d.ts +5 -4
- package/dist/modules/breaking-changes/rules/v2/removed-nodes.rule.js +4 -3
- package/dist/modules/breaking-changes/rules/v2/removed-nodes.rule.js.map +1 -1
- package/dist/modules/breaking-changes/types/detection.types.d.ts +9 -10
- package/dist/modules/breaking-changes/types/rule.types.d.ts +9 -48
- package/dist/modules/breaking-changes/types/rule.types.js +1 -14
- package/dist/modules/breaking-changes/types/rule.types.js.map +1 -1
- package/dist/modules/insights/database/repositories/insights-by-period-query.helper.d.ts +9 -2
- package/dist/modules/insights/database/repositories/insights-by-period-query.helper.js +28 -64
- package/dist/modules/insights/database/repositories/insights-by-period-query.helper.js.map +1 -1
- package/dist/modules/insights/insights.controller.js +1 -1
- package/dist/modules/mcp/database/entities/oauth-access-token.entity.d.ts +9 -0
- package/dist/modules/mcp/database/entities/oauth-access-token.entity.js +44 -0
- package/dist/modules/mcp/database/entities/oauth-access-token.entity.js.map +1 -0
- package/dist/modules/mcp/database/entities/oauth-authorization-code.entity.d.ts +15 -0
- package/dist/modules/mcp/database/entities/oauth-authorization-code.entity.js +69 -0
- package/dist/modules/mcp/database/entities/oauth-authorization-code.entity.js.map +1 -0
- package/dist/modules/mcp/database/entities/oauth-client.entity.d.ts +18 -0
- package/dist/modules/mcp/database/entities/oauth-client.entity.js +65 -0
- package/dist/modules/mcp/database/entities/oauth-client.entity.js.map +1 -0
- package/dist/modules/mcp/database/entities/oauth-refresh-token.entity.d.ts +10 -0
- package/dist/modules/mcp/database/entities/oauth-refresh-token.entity.js +49 -0
- package/dist/modules/mcp/database/entities/oauth-refresh-token.entity.js.map +1 -0
- package/dist/modules/mcp/database/entities/oauth-user-consent.entity.d.ts +10 -0
- package/dist/modules/mcp/database/entities/oauth-user-consent.entity.js +49 -0
- package/dist/modules/mcp/database/entities/oauth-user-consent.entity.js.map +1 -0
- package/dist/modules/mcp/database/repositories/oauth-access-token.repository.d.ts +5 -0
- package/dist/modules/mcp/database/repositories/oauth-access-token.repository.js +26 -0
- package/dist/modules/mcp/database/repositories/oauth-access-token.repository.js.map +1 -0
- package/dist/modules/mcp/database/repositories/oauth-authorization-code.repository.d.ts +5 -0
- package/dist/modules/mcp/database/repositories/oauth-authorization-code.repository.js +26 -0
- package/dist/modules/mcp/database/repositories/oauth-authorization-code.repository.js.map +1 -0
- package/dist/modules/mcp/database/repositories/oauth-client.repository.d.ts +5 -0
- package/dist/modules/mcp/database/repositories/oauth-client.repository.js +26 -0
- package/dist/modules/mcp/database/repositories/oauth-client.repository.js.map +1 -0
- package/dist/modules/mcp/database/repositories/oauth-refresh-token.repository.d.ts +5 -0
- package/dist/modules/mcp/database/repositories/oauth-refresh-token.repository.js +26 -0
- package/dist/modules/mcp/database/repositories/oauth-refresh-token.repository.js.map +1 -0
- package/dist/modules/mcp/database/repositories/oauth-user-consent.repository.d.ts +6 -0
- package/dist/modules/mcp/database/repositories/oauth-user-consent.repository.js +33 -0
- package/dist/modules/mcp/database/repositories/oauth-user-consent.repository.js.map +1 -0
- package/dist/modules/mcp/dto/approve-consent-request.dto.d.ts +8 -0
- package/dist/modules/mcp/dto/approve-consent-request.dto.js +11 -0
- package/dist/modules/mcp/dto/approve-consent-request.dto.js.map +1 -0
- package/dist/modules/mcp/mcp-api-key.service.d.ts +6 -9
- package/dist/modules/mcp/mcp-api-key.service.js +32 -61
- package/dist/modules/mcp/mcp-api-key.service.js.map +1 -1
- package/dist/modules/mcp/mcp-oauth-authorization-code.service.d.ts +11 -0
- package/dist/modules/mcp/mcp-oauth-authorization-code.service.js +76 -0
- package/dist/modules/mcp/mcp-oauth-authorization-code.service.js.map +1 -0
- package/dist/modules/mcp/mcp-oauth-consent.service.d.ts +20 -0
- package/dist/modules/mcp/mcp-oauth-consent.service.js +87 -0
- package/dist/modules/mcp/mcp-oauth-consent.service.js.map +1 -0
- package/dist/modules/mcp/mcp-oauth-service.d.ts +31 -0
- package/dist/modules/mcp/mcp-oauth-service.js +164 -0
- package/dist/modules/mcp/mcp-oauth-service.js.map +1 -0
- package/dist/modules/mcp/mcp-oauth-token.service.d.ts +28 -0
- package/dist/modules/mcp/mcp-oauth-token.service.js +182 -0
- package/dist/modules/mcp/mcp-oauth-token.service.js.map +1 -0
- package/dist/modules/mcp/mcp-oauth.helpers.d.ts +4 -0
- package/dist/modules/mcp/mcp-oauth.helpers.js +24 -0
- package/dist/modules/mcp/mcp-oauth.helpers.js.map +1 -0
- package/dist/modules/mcp/mcp-server-middleware.service.d.ts +18 -0
- package/dist/modules/mcp/mcp-server-middleware.service.js +94 -0
- package/dist/modules/mcp/mcp-server-middleware.service.js.map +1 -0
- package/dist/modules/mcp/mcp.auth.consent.controller.d.ts +17 -0
- package/dist/modules/mcp/mcp.auth.consent.controller.js +120 -0
- package/dist/modules/mcp/mcp.auth.consent.controller.js.map +1 -0
- package/dist/modules/mcp/mcp.controller.d.ts +2 -1
- package/dist/modules/mcp/mcp.controller.js +11 -3
- package/dist/modules/mcp/mcp.controller.js.map +1 -1
- package/dist/modules/mcp/mcp.module.d.ts +1 -0
- package/dist/modules/mcp/mcp.module.js +11 -0
- package/dist/modules/mcp/mcp.module.js.map +1 -1
- package/dist/modules/mcp/mcp.oauth-clients.controller.d.ts +12 -0
- package/dist/modules/mcp/mcp.oauth-clients.controller.js +93 -0
- package/dist/modules/mcp/mcp.oauth-clients.controller.js.map +1 -0
- package/dist/modules/mcp/mcp.oauth.controller.d.ts +13 -0
- package/dist/modules/mcp/mcp.oauth.controller.js +124 -0
- package/dist/modules/mcp/mcp.oauth.controller.js.map +1 -0
- package/dist/modules/mcp/mcp.types.d.ts +1 -2
- package/dist/modules/mcp/oauth-session.service.d.ts +16 -0
- package/dist/modules/mcp/oauth-session.service.js +48 -0
- package/dist/modules/mcp/oauth-session.service.js.map +1 -0
- package/dist/modules/mcp/tools/search-workflows.tool.d.ts +2 -3
- package/dist/modules/mcp/tools/search-workflows.tool.js +11 -10
- package/dist/modules/mcp/tools/search-workflows.tool.js.map +1 -1
- package/dist/modules/provisioning.ee/provisioning.service.ee.d.ts +4 -2
- package/dist/modules/provisioning.ee/provisioning.service.ee.js +20 -1
- package/dist/modules/provisioning.ee/provisioning.service.ee.js.map +1 -1
- package/dist/public-api/v1/handlers/users/users.service.ee.d.ts +6 -2
- package/dist/public-api/v1/handlers/users/users.service.ee.js +10 -3
- package/dist/public-api/v1/handlers/users/users.service.ee.js.map +1 -1
- package/dist/public-api/v1/openapi.yml +1 -1
- package/dist/services/import.service.js +0 -5
- package/dist/services/import.service.js.map +1 -1
- package/dist/services/jwt.service.d.ts +1 -1
- package/dist/services/jwt.service.js.map +1 -1
- package/dist/sso.ee/oidc/oidc.service.ee.js +6 -4
- package/dist/sso.ee/oidc/oidc.service.ee.js.map +1 -1
- package/dist/sso.ee/saml/routes/saml.controller.ee.d.ts +2 -10
- package/dist/sso.ee/saml/routes/saml.controller.ee.js +2 -9
- package/dist/sso.ee/saml/routes/saml.controller.ee.js.map +1 -1
- package/dist/sso.ee/saml/saml-helpers.d.ts +4 -1
- package/dist/sso.ee/saml/saml-helpers.js +10 -3
- package/dist/sso.ee/saml/saml-helpers.js.map +1 -1
- package/dist/sso.ee/saml/saml.service.ee.d.ts +4 -1
- package/dist/sso.ee/saml/saml.service.ee.js +20 -12
- package/dist/sso.ee/saml/saml.service.ee.js.map +1 -1
- package/dist/sso.ee/saml/types.d.ts +2 -2
- package/dist/telemetry/index.js +17 -3
- package/dist/telemetry/index.js.map +1 -1
- package/dist/utils/validate-database-type.d.ts +3 -1
- package/dist/utils/validate-database-type.js +26 -4
- package/dist/utils/validate-database-type.js.map +1 -1
- package/dist/workflows/workflow-finder.service.d.ts +1 -0
- package/dist/workflows/workflow.request.d.ts +1 -0
- package/dist/workflows/workflow.service.d.ts +2 -1
- package/dist/workflows/workflow.service.js +1 -0
- package/dist/workflows/workflow.service.js.map +1 -1
- package/dist/workflows/workflows.controller.d.ts +4 -0
- 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"}
|