mcp-creatio 0.6.1 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +236 -149
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +22 -10
- package/dist/cli.js.map +1 -1
- package/dist/config-builder.d.ts +8 -0
- package/dist/config-builder.d.ts.map +1 -1
- package/dist/config-builder.js +147 -43
- package/dist/config-builder.js.map +1 -1
- package/dist/consts.d.ts.map +1 -1
- package/dist/consts.js +2 -1
- package/dist/consts.js.map +1 -1
- package/dist/creatio/auth/auth-manager.d.ts.map +1 -1
- package/dist/creatio/auth/auth-manager.js +5 -2
- package/dist/creatio/auth/auth-manager.js.map +1 -1
- package/dist/creatio/auth/auth.d.ts +4 -31
- package/dist/creatio/auth/auth.d.ts.map +1 -1
- package/dist/creatio/auth/auth.js +20 -26
- package/dist/creatio/auth/auth.js.map +1 -1
- package/dist/creatio/auth/constants.d.ts +14 -0
- package/dist/creatio/auth/constants.d.ts.map +1 -0
- package/dist/creatio/auth/constants.js +20 -0
- package/dist/creatio/auth/constants.js.map +1 -0
- package/dist/creatio/auth/contracts.d.ts +15 -0
- package/dist/creatio/auth/contracts.d.ts.map +1 -0
- package/dist/creatio/auth/contracts.js +3 -0
- package/dist/creatio/auth/contracts.js.map +1 -0
- package/dist/creatio/auth/headers.d.ts +3 -0
- package/dist/creatio/auth/headers.d.ts.map +1 -0
- package/dist/creatio/auth/headers.js +15 -0
- package/dist/creatio/auth/headers.js.map +1 -0
- package/dist/creatio/auth/identity.d.ts +8 -0
- package/dist/creatio/auth/identity.d.ts.map +1 -0
- package/dist/creatio/auth/identity.js +18 -0
- package/dist/creatio/auth/identity.js.map +1 -0
- package/dist/creatio/auth/index.d.ts +4 -3
- package/dist/creatio/auth/index.d.ts.map +1 -1
- package/dist/creatio/auth/index.js +5 -3
- package/dist/creatio/auth/index.js.map +1 -1
- package/dist/creatio/auth/providers/base-oauth2-provider.d.ts +13 -7
- package/dist/creatio/auth/providers/base-oauth2-provider.d.ts.map +1 -1
- package/dist/creatio/auth/providers/base-oauth2-provider.js +29 -19
- package/dist/creatio/auth/providers/base-oauth2-provider.js.map +1 -1
- package/dist/creatio/auth/providers/base-provider.js +1 -1
- package/dist/creatio/auth/providers/base-provider.js.map +1 -1
- package/dist/creatio/auth/providers/broker-provider.d.ts +20 -0
- package/dist/creatio/auth/providers/broker-provider.d.ts.map +1 -0
- package/dist/creatio/auth/providers/broker-provider.js +72 -0
- package/dist/creatio/auth/providers/broker-provider.js.map +1 -0
- package/dist/creatio/auth/providers/creatio-oauth-client.d.ts +27 -0
- package/dist/creatio/auth/providers/creatio-oauth-client.d.ts.map +1 -0
- package/dist/creatio/auth/providers/creatio-oauth-client.js +122 -0
- package/dist/creatio/auth/providers/creatio-oauth-client.js.map +1 -0
- package/dist/creatio/auth/providers/index.d.ts +3 -1
- package/dist/creatio/auth/providers/index.d.ts.map +1 -1
- package/dist/creatio/auth/providers/index.js +3 -1
- package/dist/creatio/auth/providers/index.js.map +1 -1
- package/dist/creatio/auth/providers/oauth2-bearer-provider.d.ts +17 -0
- package/dist/creatio/auth/providers/oauth2-bearer-provider.d.ts.map +1 -0
- package/dist/creatio/auth/providers/oauth2-bearer-provider.js +33 -0
- package/dist/creatio/auth/providers/oauth2-bearer-provider.js.map +1 -0
- package/dist/creatio/auth/providers/oauth2-provider.d.ts +2 -2
- package/dist/creatio/auth/providers/oauth2-provider.d.ts.map +1 -1
- package/dist/creatio/auth/providers/oauth2-provider.js +4 -9
- package/dist/creatio/auth/providers/oauth2-provider.js.map +1 -1
- package/dist/creatio/auth/providers/type.d.ts +20 -1
- package/dist/creatio/auth/providers/type.d.ts.map +1 -1
- package/dist/creatio/auth/providers/type.js +22 -2
- package/dist/creatio/auth/providers/type.js.map +1 -1
- package/dist/creatio/client-config.d.ts +26 -5
- package/dist/creatio/client-config.d.ts.map +1 -1
- package/dist/creatio/engines/admin-operation-engine.d.ts +1 -1
- package/dist/creatio/engines/admin-operation-engine.d.ts.map +1 -1
- package/dist/creatio/engines/admin-operation-engine.js +3 -3
- package/dist/creatio/engines/admin-operation-engine.js.map +1 -1
- package/dist/creatio/engines/configuration-engine.d.ts +1 -1
- package/dist/creatio/engines/configuration-engine.d.ts.map +1 -1
- package/dist/creatio/engines/configuration-engine.js +3 -3
- package/dist/creatio/engines/configuration-engine.js.map +1 -1
- package/dist/creatio/engines/crud-engine.d.ts +1 -1
- package/dist/creatio/engines/crud-engine.d.ts.map +1 -1
- package/dist/creatio/engines/crud-engine.js +4 -4
- package/dist/creatio/engines/crud-engine.js.map +1 -1
- package/dist/creatio/engines/engine-manager.d.ts +1 -2
- package/dist/creatio/engines/engine-manager.d.ts.map +1 -1
- package/dist/creatio/engines/engine-manager.js +4 -10
- package/dist/creatio/engines/engine-manager.js.map +1 -1
- package/dist/creatio/engines/engine.d.ts.map +1 -1
- package/dist/creatio/engines/engine.js +12 -1
- package/dist/creatio/engines/engine.js.map +1 -1
- package/dist/creatio/engines/feature-engine.d.ts +1 -1
- package/dist/creatio/engines/feature-engine.d.ts.map +1 -1
- package/dist/creatio/engines/feature-engine.js +3 -3
- package/dist/creatio/engines/feature-engine.js.map +1 -1
- package/dist/creatio/engines/process-engine.d.ts +1 -1
- package/dist/creatio/engines/process-engine.d.ts.map +1 -1
- package/dist/creatio/engines/process-engine.js +3 -3
- package/dist/creatio/engines/process-engine.js.map +1 -1
- package/dist/creatio/engines/sys-settings-engine.d.ts +1 -1
- package/dist/creatio/engines/sys-settings-engine.d.ts.map +1 -1
- package/dist/creatio/engines/sys-settings-engine.js +3 -3
- package/dist/creatio/engines/sys-settings-engine.js.map +1 -1
- package/dist/creatio/engines/user-engine.d.ts +1 -1
- package/dist/creatio/engines/user-engine.d.ts.map +1 -1
- package/dist/creatio/engines/user-engine.js +3 -3
- package/dist/creatio/engines/user-engine.js.map +1 -1
- package/dist/creatio/services/creatio-service-context.d.ts +1 -1
- package/dist/creatio/services/creatio-service-context.d.ts.map +1 -1
- package/dist/creatio/services/crud-provider-factory.d.ts.map +1 -1
- package/dist/creatio/services/crud-provider-factory.js.map +1 -1
- package/dist/creatio/services/dataservice/data-service-column-values.d.ts.map +1 -1
- package/dist/creatio/services/dataservice/data-service-crud-provider.d.ts +3 -3
- package/dist/creatio/services/dataservice/data-service-crud-provider.d.ts.map +1 -1
- package/dist/creatio/services/dataservice/data-service-crud-provider.js +5 -5
- package/dist/creatio/services/dataservice/data-service-crud-provider.js.map +1 -1
- package/dist/creatio/services/dataservice/data-service-filter-translator.d.ts.map +1 -1
- package/dist/creatio/services/dataservice/data-service-filter-translator.js +7 -2
- package/dist/creatio/services/dataservice/data-service-filter-translator.js.map +1 -1
- package/dist/creatio/services/dataservice/data-service-query-builder.d.ts.map +1 -1
- package/dist/creatio/services/dataservice/data-service-query-builder.js.map +1 -1
- package/dist/creatio/services/dataservice/data-service-schema.d.ts +3 -3
- package/dist/creatio/services/dataservice/data-service-schema.d.ts.map +1 -1
- package/dist/creatio/services/dataservice/data-service-schema.js +19 -17
- package/dist/creatio/services/dataservice/data-service-schema.js.map +1 -1
- package/dist/creatio/services/dataservice/data-service-transport.d.ts +1 -1
- package/dist/creatio/services/dataservice/data-service-transport.d.ts.map +1 -1
- package/dist/creatio/services/dataservice/data-service-transport.js +3 -3
- package/dist/creatio/services/dataservice/data-service-transport.js.map +1 -1
- package/dist/creatio/services/dataservice/data-service-types.d.ts +0 -19
- package/dist/creatio/services/dataservice/data-service-types.d.ts.map +1 -1
- package/dist/creatio/services/dataservice/data-service-value-type.d.ts +2 -1
- package/dist/creatio/services/dataservice/data-service-value-type.d.ts.map +1 -1
- package/dist/creatio/services/dataservice/data-service-value-type.js +20 -16
- package/dist/creatio/services/dataservice/data-service-value-type.js.map +1 -1
- package/dist/creatio/services/http-client.d.ts +13 -0
- package/dist/creatio/services/http-client.d.ts.map +1 -1
- package/dist/creatio/services/http-client.js +26 -2
- package/dist/creatio/services/http-client.js.map +1 -1
- package/dist/creatio/services/identifiers.d.ts +10 -0
- package/dist/creatio/services/identifiers.d.ts.map +1 -0
- package/dist/creatio/services/identifiers.js +20 -0
- package/dist/creatio/services/identifiers.js.map +1 -0
- package/dist/creatio/services/odata/metadata-store.d.ts +6 -2
- package/dist/creatio/services/odata/metadata-store.d.ts.map +1 -1
- package/dist/creatio/services/odata/metadata-store.js +30 -34
- package/dist/creatio/services/odata/metadata-store.js.map +1 -1
- package/dist/creatio/services/odata/odata-crud-provider.d.ts.map +1 -1
- package/dist/creatio/services/odata/odata-crud-provider.js +10 -25
- package/dist/creatio/services/odata/odata-crud-provider.js.map +1 -1
- package/dist/creatio/services/odata/odata-query-translator.d.ts +4 -5
- package/dist/creatio/services/odata/odata-query-translator.d.ts.map +1 -1
- package/dist/creatio/services/odata/odata-query-translator.js +32 -20
- package/dist/creatio/services/odata/odata-query-translator.js.map +1 -1
- package/dist/creatio/services/user-info-provider.d.ts.map +1 -1
- package/dist/creatio/services/user-info-provider.js +2 -2
- package/dist/creatio/services/user-info-provider.js.map +1 -1
- package/dist/index.js +30 -4
- package/dist/index.js.map +1 -1
- package/dist/log.d.ts +1 -1
- package/dist/log.d.ts.map +1 -1
- package/dist/log.js +2 -1
- package/dist/log.js.map +1 -1
- package/dist/server/bearer/base-url-guard.d.ts +20 -0
- package/dist/server/bearer/base-url-guard.d.ts.map +1 -0
- package/dist/server/bearer/base-url-guard.js +55 -0
- package/dist/server/bearer/base-url-guard.js.map +1 -0
- package/dist/server/bearer/bearer-edge.d.ts +42 -0
- package/dist/server/bearer/bearer-edge.d.ts.map +1 -0
- package/dist/server/bearer/bearer-edge.js +122 -0
- package/dist/server/bearer/bearer-edge.js.map +1 -0
- package/dist/server/bearer/bearer-token.d.ts +27 -0
- package/dist/server/bearer/bearer-token.d.ts.map +1 -0
- package/dist/server/bearer/bearer-token.js +50 -0
- package/dist/server/bearer/bearer-token.js.map +1 -0
- package/dist/server/bearer/index.d.ts +3 -0
- package/dist/server/bearer/index.d.ts.map +1 -0
- package/dist/server/bearer/index.js +19 -0
- package/dist/server/bearer/index.js.map +1 -0
- package/dist/server/http/auth-edge.d.ts +26 -0
- package/dist/server/http/auth-edge.d.ts.map +1 -0
- package/dist/server/http/auth-edge.js +75 -0
- package/dist/server/http/auth-edge.js.map +1 -0
- package/dist/server/http/broker-handlers.d.ts +45 -0
- package/dist/server/http/broker-handlers.d.ts.map +1 -0
- package/dist/server/http/broker-handlers.js +224 -0
- package/dist/server/http/broker-handlers.js.map +1 -0
- package/dist/server/http/{httpServer.d.ts → http-server.d.ts} +5 -13
- package/dist/server/http/http-server.d.ts.map +1 -0
- package/dist/server/http/{httpServer.js → http-server.js} +19 -53
- package/dist/server/http/http-server.js.map +1 -0
- package/dist/server/http/index.d.ts +1 -3
- package/dist/server/http/index.d.ts.map +1 -1
- package/dist/server/http/index.js +1 -3
- package/dist/server/http/index.js.map +1 -1
- package/dist/server/http/mcp-handlers.d.ts.map +1 -1
- package/dist/server/http/mcp-handlers.js +16 -3
- package/dist/server/http/mcp-handlers.js.map +1 -1
- package/dist/server/http/middleware.d.ts +3 -4
- package/dist/server/http/middleware.d.ts.map +1 -1
- package/dist/server/http/middleware.js +33 -23
- package/dist/server/http/middleware.js.map +1 -1
- package/dist/server/http/public-origin.d.ts +10 -0
- package/dist/server/http/public-origin.d.ts.map +1 -0
- package/dist/server/http/public-origin.js +19 -0
- package/dist/server/http/public-origin.js.map +1 -0
- package/dist/server/http/rate-limiter.d.ts +1 -1
- package/dist/server/http/rate-limiter.d.ts.map +1 -1
- package/dist/server/http/rate-limiter.js +11 -11
- package/dist/server/http/rate-limiter.js.map +1 -1
- package/dist/server/http-agent.d.ts +9 -0
- package/dist/server/http-agent.d.ts.map +1 -0
- package/dist/server/http-agent.js +35 -0
- package/dist/server/http-agent.js.map +1 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/keepalive.d.ts +26 -0
- package/dist/server/keepalive.d.ts.map +1 -0
- package/dist/server/keepalive.js +64 -0
- package/dist/server/keepalive.js.map +1 -0
- package/dist/server/mcp/creatio-rest.d.ts +6 -0
- package/dist/server/mcp/creatio-rest.d.ts.map +1 -1
- package/dist/server/mcp/creatio-rest.js +21 -3
- package/dist/server/mcp/creatio-rest.js.map +1 -1
- package/dist/server/mcp/crtmcp/crt-mcp-client.d.ts +1 -1
- package/dist/server/mcp/crtmcp/crt-mcp-client.d.ts.map +1 -1
- package/dist/server/mcp/crtmcp/crt-mcp-client.js +16 -13
- package/dist/server/mcp/crtmcp/crt-mcp-client.js.map +1 -1
- package/dist/server/mcp/crtmcp/crt-mcp-tool-preparer.d.ts +2 -2
- package/dist/server/mcp/crtmcp/crt-mcp-tool-preparer.d.ts.map +1 -1
- package/dist/server/mcp/crtmcp/crt-mcp-tool-preparer.js +17 -17
- package/dist/server/mcp/crtmcp/crt-mcp-tool-preparer.js.map +1 -1
- package/dist/server/mcp/dataforge/dataforge-client.d.ts +12 -12
- package/dist/server/mcp/dataforge/dataforge-client.d.ts.map +1 -1
- package/dist/server/mcp/dataforge/dataforge-client.js +40 -47
- package/dist/server/mcp/dataforge/dataforge-client.js.map +1 -1
- package/dist/server/mcp/dataforge/dataforge-tool-preparer.d.ts +2 -2
- package/dist/server/mcp/dataforge/dataforge-tool-preparer.d.ts.map +1 -1
- package/dist/server/mcp/dataforge/dataforge-tool-preparer.js +9 -9
- package/dist/server/mcp/dataforge/dataforge-tool-preparer.js.map +1 -1
- package/dist/server/mcp/filters.d.ts.map +1 -1
- package/dist/server/mcp/filters.js +4 -1
- package/dist/server/mcp/filters.js.map +1 -1
- package/dist/server/mcp/globalsearch/globalsearch-client.d.ts +4 -4
- package/dist/server/mcp/globalsearch/globalsearch-client.d.ts.map +1 -1
- package/dist/server/mcp/globalsearch/globalsearch-client.js +39 -50
- package/dist/server/mcp/globalsearch/globalsearch-client.js.map +1 -1
- package/dist/server/mcp/globalsearch/globalsearch-tool-preparer.d.ts +1 -1
- package/dist/server/mcp/globalsearch/globalsearch-tool-preparer.d.ts.map +1 -1
- package/dist/server/mcp/globalsearch/globalsearch-tool-preparer.js +1 -1
- package/dist/server/mcp/globalsearch/globalsearch-tool-preparer.js.map +1 -1
- package/dist/server/mcp/server.d.ts +35 -8
- package/dist/server/mcp/server.d.ts.map +1 -1
- package/dist/server/mcp/server.js +104 -44
- package/dist/server/mcp/server.js.map +1 -1
- package/dist/server/mcp/tools-data.d.ts +2 -2
- package/dist/server/mcp/tools-data.d.ts.map +1 -1
- package/dist/server/mcp/tools-data.js +1 -1
- package/dist/server/mcp/tools-data.js.map +1 -1
- package/dist/server/oauth/oauth-server.d.ts +41 -10
- package/dist/server/oauth/oauth-server.d.ts.map +1 -1
- package/dist/server/oauth/oauth-server.js +82 -48
- package/dist/server/oauth/oauth-server.js.map +1 -1
- package/dist/server/oauth/storage.d.ts +42 -5
- package/dist/server/oauth/storage.d.ts.map +1 -1
- package/dist/server/oauth/storage.js +81 -18
- package/dist/server/oauth/storage.js.map +1 -1
- package/dist/server/oauth/token-manager.d.ts +21 -4
- package/dist/server/oauth/token-manager.d.ts.map +1 -1
- package/dist/server/oauth/token-manager.js +18 -19
- package/dist/server/oauth/token-manager.js.map +1 -1
- package/dist/server/oauth/types.d.ts +0 -12
- package/dist/server/oauth/types.d.ts.map +1 -1
- package/dist/server/oauth/validators.d.ts.map +1 -1
- package/dist/server/oauth/validators.js +14 -5
- package/dist/server/oauth/validators.js.map +1 -1
- package/dist/sessions/index.d.ts +1 -1
- package/dist/sessions/index.d.ts.map +1 -1
- package/dist/sessions/index.js +1 -1
- package/dist/sessions/index.js.map +1 -1
- package/dist/sessions/redis-token-store.d.ts +22 -0
- package/dist/sessions/redis-token-store.d.ts.map +1 -0
- package/dist/sessions/redis-token-store.js +70 -0
- package/dist/sessions/redis-token-store.js.map +1 -0
- package/dist/sessions/session-context.d.ts +21 -40
- package/dist/sessions/session-context.d.ts.map +1 -1
- package/dist/sessions/session-context.js +25 -105
- package/dist/sessions/session-context.js.map +1 -1
- package/dist/sessions/token-crypto.d.ts +8 -0
- package/dist/sessions/token-crypto.d.ts.map +1 -0
- package/dist/sessions/token-crypto.js +43 -0
- package/dist/sessions/token-crypto.js.map +1 -0
- package/dist/sessions/token-store.d.ts +42 -0
- package/dist/sessions/token-store.d.ts.map +1 -0
- package/dist/sessions/token-store.js +66 -0
- package/dist/sessions/token-store.js.map +1 -0
- package/dist/utils/context.d.ts +12 -0
- package/dist/utils/context.d.ts.map +1 -1
- package/dist/utils/context.js +16 -0
- package/dist/utils/context.js.map +1 -1
- package/dist/utils/env-aliases.d.ts +9 -0
- package/dist/utils/env-aliases.d.ts.map +1 -0
- package/dist/utils/env-aliases.js +61 -0
- package/dist/utils/env-aliases.js.map +1 -0
- package/dist/utils/env.d.ts +5 -0
- package/dist/utils/env.d.ts.map +1 -1
- package/dist/utils/env.js +10 -1
- package/dist/utils/env.js.map +1 -1
- package/package.json +78 -74
- package/dist/creatio/auth/providers/oauth2-code-provider.d.ts +0 -21
- package/dist/creatio/auth/providers/oauth2-code-provider.d.ts.map +0 -1
- package/dist/creatio/auth/providers/oauth2-code-provider.js +0 -251
- package/dist/creatio/auth/providers/oauth2-code-provider.js.map +0 -1
- package/dist/server/http/creatio-oauth-handlers.d.ts +0 -13
- package/dist/server/http/creatio-oauth-handlers.d.ts.map +0 -1
- package/dist/server/http/creatio-oauth-handlers.js +0 -160
- package/dist/server/http/creatio-oauth-handlers.js.map +0 -1
- package/dist/server/http/httpServer.d.ts.map +0 -1
- package/dist/server/http/httpServer.js.map +0 -1
- package/dist/server/http/mcp-oauth-handlers.d.ts +0 -11
- package/dist/server/http/mcp-oauth-handlers.d.ts.map +0 -1
- package/dist/server/http/mcp-oauth-handlers.js +0 -118
- package/dist/server/http/mcp-oauth-handlers.js.map +0 -1
- package/dist/sessions/token-refresh-scheduler.d.ts +0 -16
- package/dist/sessions/token-refresh-scheduler.d.ts.map +0 -1
- package/dist/sessions/token-refresh-scheduler.js +0 -66
- package/dist/sessions/token-refresh-scheduler.js.map +0 -1
package/dist/log.js
CHANGED
|
@@ -23,10 +23,11 @@ exports.httpResponse = httpResponse;
|
|
|
23
23
|
exports.httpError = httpError;
|
|
24
24
|
exports.logOperation = logOperation;
|
|
25
25
|
exports.audit = audit;
|
|
26
|
+
const env_1 = require("./utils/env");
|
|
26
27
|
let _correlationId;
|
|
27
28
|
let _stderrOnly = false;
|
|
28
29
|
function resolveLogVerbosity() {
|
|
29
|
-
const raw = (
|
|
30
|
+
const raw = ((0, env_1.env)('CREATIO_MCP_LOG_LEVEL') || 'silent').toLowerCase();
|
|
30
31
|
if (raw === 'info') {
|
|
31
32
|
return 'info';
|
|
32
33
|
}
|
package/dist/log.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":";;AAyCA,4CAEC;AAED,4CAEC;AAED,gDAEC;AA+BD,8CAEC;AAED,oBAEC;AACD,oBAEC;AACD,sBAEC;AACD,4BAEC;AACD,0BAEC;AACD,kCAEC;AACD,gCAEC;AACD,8BAEC;AACD,4BAEC;AACD,wCAEC;AACD,8CAEC;AACD,4CAEC;AACD,sCAEC;AACD,8CAEC;AACD,kCAEC;AACD,oCAQC;AACD,8BAOC;AACD,oCAWC;AAID,sBAEC;AArKD,qCAAkC;AAUlC,IAAI,cAAkC,CAAC;AACvC,IAAI,WAAW,GAAG,KAAK,CAAC;AAExB,SAAS,mBAAmB;IAC3B,MAAM,GAAG,GAAG,CAAC,IAAA,SAAG,EAAC,uBAAuB,CAAC,IAAI,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACrE,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,MAAM,CAAC;IACf,CAAC;IACD,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACzC,OAAO,MAAM,CAAC;IACf,CAAC;IACD,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC;IAChB,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED,SAAS,SAAS,CAAC,KAAe;IACjC,MAAM,SAAS,GAAG,mBAAmB,EAAE,CAAC;IACxC,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC;IACd,CAAC;IACD,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,KAAK,KAAK,OAAO,CAAC;IAC1B,CAAC;IACD,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QAC1B,OAAO,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,OAAO,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,SAAgB,gBAAgB,CAAC,aAAqB;IACrD,cAAc,GAAG,aAAa,CAAC;AAChC,CAAC;AAED,SAAgB,gBAAgB;IAC/B,OAAO,cAAc,CAAC;AACvB,CAAC;AAED,SAAgB,kBAAkB;IACjC,cAAc,GAAG,SAAS,CAAC;AAC5B,CAAC;AAED,SAAS,SAAS;IACjB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AACjC,CAAC;AAED,SAAS,MAAM,CAAC,KAAe,EAAE,GAAW,EAAE,IAA0B;IACvE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO;IACR,CAAC;IACD,MAAM,KAAK,GAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IACnD,IAAI,cAAc,EAAE,CAAC;QACpB,KAAK,CAAC,aAAa,GAAG,cAAc,CAAC;IACtC,CAAC;IACD,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,WAAW,EAAE,CAAC;QACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QAClC,OAAO;IACR,CAAC;IACD,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;SAAM,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;SAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;AACF,CAAC;AAED,SAAgB,iBAAiB;IAChC,WAAW,GAAG,IAAI,CAAC;AACpB,CAAC;AAED,SAAgB,IAAI,CAAC,GAAW,EAAE,IAA0B;IAC3D,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;AAC3B,CAAC;AACD,SAAgB,IAAI,CAAC,GAAW,EAAE,IAA0B;IAC3D,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;AAC3B,CAAC;AACD,SAAgB,KAAK,CAAC,GAAW,EAAE,IAA0B;IAC5D,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;AAC5B,CAAC;AACD,SAAgB,QAAQ,CAAC,IAA0B;IAClD,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;AACzB,CAAC;AACD,SAAgB,OAAO,CAAC,IAA0B;IACjD,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AACxB,CAAC;AACD,SAAgB,WAAW,CAAC,IAAa,EAAE,OAAgB,EAAE,IAA0B;IACtF,IAAI,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;AACtD,CAAC;AACD,SAAgB,UAAU,CAAC,IAAa,EAAE,OAAgB,EAAE,IAA0B;IACrF,IAAI,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;AACrD,CAAC;AACD,SAAgB,SAAS,CAAC,IAAY,EAAE,IAA0B;IACjE,IAAI,CAAC,mBAAmB,EAAE,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;AAC9C,CAAC;AACD,SAAgB,QAAQ,CAAC,IAAY,EAAE,IAA0B;IAChE,IAAI,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;AAC7C,CAAC;AACD,SAAgB,cAAc,CAAC,SAAiB,EAAE,EAAW,EAAE,IAA0B;IACxF,IAAI,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;AACrD,CAAC;AACD,SAAgB,iBAAiB,CAAC,SAAiB,EAAE,EAAW,EAAE,IAA0B;IAC3F,IAAI,CAAC,oBAAoB,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;AACxD,CAAC;AACD,SAAgB,gBAAgB,CAAC,OAAe,EAAE,QAA0B;IAC3E,IAAI,CAAC,oBAAoB,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;AACnD,CAAC;AACD,SAAgB,aAAa,CAAC,OAAe,EAAE,QAA0B;IACxE,IAAI,CAAC,iBAAiB,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;AAChD,CAAC;AACD,SAAgB,iBAAiB,CAAC,OAAe,EAAE,KAAa,EAAE,QAA0B;IAC3F,IAAI,CAAC,qBAAqB,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC3D,CAAC;AACD,SAAgB,WAAW,CAAC,MAAc,EAAE,GAAW,EAAE,IAA0B;IAClF,IAAI,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;AAChD,CAAC;AACD,SAAgB,YAAY,CAC3B,MAAc,EACd,GAAW,EACX,MAAc,EACd,QAAiB,EACjB,IAA0B;IAE1B,IAAI,CAAC,eAAe,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;AACnE,CAAC;AACD,SAAgB,SAAS,CACxB,MAAc,EACd,GAAW,EACX,QAAgB,EAChB,IAA0B;IAE1B,KAAK,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;AAChE,CAAC;AACD,SAAgB,YAAY,CAC3B,SAAiB,EACjB,QAAgB,EAChB,OAAgB,EAChB,IAA0B;IAE1B,IAAI,CAAC,aAAa,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE;QACnD,SAAS;QACT,QAAQ;QACR,GAAG,IAAI;KACP,CAAC,CAAC;AACJ,CAAC;AACD;;wDAEwD;AACxD,SAAgB,KAAK,CAAC,MAAc,EAAE,IAA0B;IAC/D,IAAI,CAAC,eAAe,EAAE,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED,kBAAe;IACd,IAAI;IACJ,IAAI;IACJ,KAAK;IACL,iBAAiB;IACjB,QAAQ;IACR,OAAO;IACP,WAAW;IACX,UAAU;IACV,SAAS;IACT,QAAQ;IACR,cAAc;IACd,iBAAiB;IACjB,gBAAgB;IAChB,aAAa;IACb,iBAAiB;IACjB,WAAW;IACX,YAAY;IACZ,SAAS;IACT,YAAY;IACZ,KAAK;IACL,gBAAgB;IAChB,gBAAgB;IAChB,kBAAkB;CAClB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guards the gateway-only `X-Creatio-Base-Url` override. The override decides where each request's
|
|
3
|
+
* Bearer token is sent, so an unvalidated value is an SSRF / token-redirection lever (CWE-918):
|
|
4
|
+
* a compromised or misconfigured gateway could redirect the authenticated token to an attacker host
|
|
5
|
+
* or pivot to internal metadata endpoints.
|
|
6
|
+
*
|
|
7
|
+
* The real production control is an allowlist (`CREATIO_MCP_ALLOWED_BASE_URLS`). When it is set, the
|
|
8
|
+
* override MUST fall under an allowed origin. When it is NOT set, we keep the trusted-gateway posture
|
|
9
|
+
* (any http/https host is accepted) but ALWAYS block the cloud-metadata link-local address, since it
|
|
10
|
+
* is never a legitimate Creatio target and is the classic SSRF prize. On-prem private ranges are NOT
|
|
11
|
+
* blocked by default — legitimate tenants live there — so use the allowlist to lock things down.
|
|
12
|
+
*/
|
|
13
|
+
/** Parse the comma/space-separated `CREATIO_MCP_ALLOWED_BASE_URLS` into normalized origins. */
|
|
14
|
+
export declare function parseAllowedBaseUrls(raw: string | undefined): string[];
|
|
15
|
+
/**
|
|
16
|
+
* Whether `raw` is an acceptable base-URL override. `allowlist` is the parsed
|
|
17
|
+
* {@link parseAllowedBaseUrls} list ([] = none configured).
|
|
18
|
+
*/
|
|
19
|
+
export declare function isAllowedBaseUrl(raw: string, allowlist: string[]): boolean;
|
|
20
|
+
//# sourceMappingURL=base-url-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-url-guard.d.ts","sourceRoot":"","sources":["../../../src/server/bearer/base-url-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,+FAA+F;AAC/F,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAQtE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAsB1E"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Guards the gateway-only `X-Creatio-Base-Url` override. The override decides where each request's
|
|
4
|
+
* Bearer token is sent, so an unvalidated value is an SSRF / token-redirection lever (CWE-918):
|
|
5
|
+
* a compromised or misconfigured gateway could redirect the authenticated token to an attacker host
|
|
6
|
+
* or pivot to internal metadata endpoints.
|
|
7
|
+
*
|
|
8
|
+
* The real production control is an allowlist (`CREATIO_MCP_ALLOWED_BASE_URLS`). When it is set, the
|
|
9
|
+
* override MUST fall under an allowed origin. When it is NOT set, we keep the trusted-gateway posture
|
|
10
|
+
* (any http/https host is accepted) but ALWAYS block the cloud-metadata link-local address, since it
|
|
11
|
+
* is never a legitimate Creatio target and is the classic SSRF prize. On-prem private ranges are NOT
|
|
12
|
+
* blocked by default — legitimate tenants live there — so use the allowlist to lock things down.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.parseAllowedBaseUrls = parseAllowedBaseUrls;
|
|
16
|
+
exports.isAllowedBaseUrl = isAllowedBaseUrl;
|
|
17
|
+
/** Cloud instance-metadata endpoints (AWS/GCP/Azure IMDS) — never a Creatio base, always blocked. */
|
|
18
|
+
const BLOCKED_HOSTS = new Set(['169.254.169.254', 'fd00:ec2::254', '[fd00:ec2::254]']);
|
|
19
|
+
/** Parse the comma/space-separated `CREATIO_MCP_ALLOWED_BASE_URLS` into normalized origins. */
|
|
20
|
+
function parseAllowedBaseUrls(raw) {
|
|
21
|
+
if (!raw) {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
return raw
|
|
25
|
+
.split(/[\s,]+/)
|
|
26
|
+
.map((s) => s.trim().replace(/\/+$/, '').toLowerCase())
|
|
27
|
+
.filter(Boolean);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Whether `raw` is an acceptable base-URL override. `allowlist` is the parsed
|
|
31
|
+
* {@link parseAllowedBaseUrls} list ([] = none configured).
|
|
32
|
+
*/
|
|
33
|
+
function isAllowedBaseUrl(raw, allowlist) {
|
|
34
|
+
let url;
|
|
35
|
+
try {
|
|
36
|
+
url = new URL(raw);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
const scheme = url.protocol.toLowerCase();
|
|
42
|
+
if (scheme !== 'http:' && scheme !== 'https:') {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
const host = url.hostname.toLowerCase();
|
|
46
|
+
if (BLOCKED_HOSTS.has(host) || host.startsWith('169.254.')) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
if (allowlist.length === 0) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
const normalized = raw.replace(/\/+$/, '').toLowerCase();
|
|
53
|
+
return allowlist.some((allowed) => normalized === allowed || normalized.startsWith(allowed + '/'));
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=base-url-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-url-guard.js","sourceRoot":"","sources":["../../../src/server/bearer/base-url-guard.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;AAMH,oDAQC;AAMD,4CAsBC;AAxCD,qGAAqG;AACrG,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,iBAAiB,EAAE,eAAe,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAEvF,+FAA+F;AAC/F,SAAgB,oBAAoB,CAAC,GAAuB;IAC3D,IAAI,CAAC,GAAG,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;IACX,CAAC;IACD,OAAO,GAAG;SACR,KAAK,CAAC,QAAQ,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;SACtD,MAAM,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,GAAW,EAAE,SAAmB;IAChE,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACJ,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAC1C,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/C,OAAO,KAAK,CAAC;IACd,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IACxC,IAAI,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5D,OAAO,KAAK,CAAC;IACd,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC;IACb,CAAC;IACD,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACzD,OAAO,SAAS,CAAC,IAAI,CACpB,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,KAAK,OAAO,IAAI,UAAU,CAAC,UAAU,CAAC,OAAO,GAAG,GAAG,CAAC,CAC3E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { BearerAuthConfig } from '../../creatio';
|
|
2
|
+
import type { Express, NextFunction, Request, Response } from 'express';
|
|
3
|
+
/** RFC 9728 Protected Resource Metadata, advertising Creatio Identity as the authorization server. */
|
|
4
|
+
export declare function buildProtectedResourceMetadata(resource: string, identityBase: string): {
|
|
5
|
+
resource: string;
|
|
6
|
+
authorization_servers: string[];
|
|
7
|
+
scopes_supported: string[];
|
|
8
|
+
bearer_methods_supported: string[];
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* The HTTP "edge" for the stateless per-request Bearer model — the only place the two modes differ.
|
|
12
|
+
*
|
|
13
|
+
* - **gateway**: a trusted Control-Plane injects the Bearer (+ optional `X-Creatio-Base-Url` for
|
|
14
|
+
* multi-tenant routing); the MCP trusts it and passes it through.
|
|
15
|
+
* - **delegated**: the client obtained the token directly from Creatio Identity; the MCP advertises
|
|
16
|
+
* that authorization server via RFC 9728, challenges unauthenticated requests, and fails fast on
|
|
17
|
+
* an obviously-expired JWT.
|
|
18
|
+
*
|
|
19
|
+
* Both modes are FULLY-TRUSTED-ENVIRONMENT deployments: gateway trusts the Control-Plane in front of
|
|
20
|
+
* it; delegated trusts the client + the network it runs on. The MCP does NOT cryptographically
|
|
21
|
+
* verify the Bearer here — Creatio remains the ultimate authority and independently rejects invalid
|
|
22
|
+
* tokens on the API call — so the runtime is a straight token passthrough; only discovery/trust
|
|
23
|
+
* differ. The `userKey` derived from the token is therefore an UNVERIFIED, session/logging-only
|
|
24
|
+
* identity, not an authenticated principal. For an untrusted, direct external client that needs the
|
|
25
|
+
* MCP itself to verify identity, use `broker` mode (the MCP is its own audience-bound OAuth 2.1 AS).
|
|
26
|
+
*/
|
|
27
|
+
export declare class BearerEdge {
|
|
28
|
+
private readonly _config;
|
|
29
|
+
private readonly _baseUrl;
|
|
30
|
+
private readonly _allowedBaseUrls;
|
|
31
|
+
private get _isDelegated();
|
|
32
|
+
/** Identity Service base advertised to clients. */
|
|
33
|
+
private get _identityBase();
|
|
34
|
+
constructor(config: BearerAuthConfig, baseUrl: string);
|
|
35
|
+
private _accept;
|
|
36
|
+
private _challenge;
|
|
37
|
+
/** Delegated mode publishes RFC 9728 metadata so clients can discover the authorization server. */
|
|
38
|
+
registerRoutes(app: Express): void;
|
|
39
|
+
/** Express middleware guarding `/mcp`. Sets `req.bearerToken` / `req.userKey` / `req.baseUrlOverride`. */
|
|
40
|
+
mcpAuth(): (req: Request, res: Response, next: NextFunction) => void;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=bearer-edge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bearer-edge.d.ts","sourceRoot":"","sources":["../../../src/server/bearer/bearer-edge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAkB,MAAM,eAAe,CAAC;AAQjE,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAKxE,sGAAsG;AACtG,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;;;;;EAOpF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,UAAU;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAW;IAE5C,OAAO,KAAK,YAAY,GAEvB;IAED,mDAAmD;IACnD,OAAO,KAAK,aAAa,GAExB;gBAEW,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM;IAMrD,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,UAAU;IAiBlB,mGAAmG;IAC5F,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAUzC,0GAA0G;IACnG,OAAO,KACL,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI;CAkC/D"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.BearerEdge = void 0;
|
|
7
|
+
exports.buildProtectedResourceMetadata = buildProtectedResourceMetadata;
|
|
8
|
+
const creatio_1 = require("../../creatio");
|
|
9
|
+
const log_1 = __importDefault(require("../../log"));
|
|
10
|
+
const utils_1 = require("../../utils");
|
|
11
|
+
const public_origin_1 = require("../http/public-origin");
|
|
12
|
+
const base_url_guard_1 = require("./base-url-guard");
|
|
13
|
+
const bearer_token_1 = require("./bearer-token");
|
|
14
|
+
const PROTECTED_RESOURCE_METADATA_PATH = '/.well-known/oauth-protected-resource';
|
|
15
|
+
const BASE_URL_OVERRIDE_HEADER = 'x-creatio-base-url';
|
|
16
|
+
/** RFC 9728 Protected Resource Metadata, advertising Creatio Identity as the authorization server. */
|
|
17
|
+
function buildProtectedResourceMetadata(resource, identityBase) {
|
|
18
|
+
return {
|
|
19
|
+
resource,
|
|
20
|
+
authorization_servers: [identityBase],
|
|
21
|
+
scopes_supported: ['offline_access'],
|
|
22
|
+
bearer_methods_supported: ['header'],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The HTTP "edge" for the stateless per-request Bearer model — the only place the two modes differ.
|
|
27
|
+
*
|
|
28
|
+
* - **gateway**: a trusted Control-Plane injects the Bearer (+ optional `X-Creatio-Base-Url` for
|
|
29
|
+
* multi-tenant routing); the MCP trusts it and passes it through.
|
|
30
|
+
* - **delegated**: the client obtained the token directly from Creatio Identity; the MCP advertises
|
|
31
|
+
* that authorization server via RFC 9728, challenges unauthenticated requests, and fails fast on
|
|
32
|
+
* an obviously-expired JWT.
|
|
33
|
+
*
|
|
34
|
+
* Both modes are FULLY-TRUSTED-ENVIRONMENT deployments: gateway trusts the Control-Plane in front of
|
|
35
|
+
* it; delegated trusts the client + the network it runs on. The MCP does NOT cryptographically
|
|
36
|
+
* verify the Bearer here — Creatio remains the ultimate authority and independently rejects invalid
|
|
37
|
+
* tokens on the API call — so the runtime is a straight token passthrough; only discovery/trust
|
|
38
|
+
* differ. The `userKey` derived from the token is therefore an UNVERIFIED, session/logging-only
|
|
39
|
+
* identity, not an authenticated principal. For an untrusted, direct external client that needs the
|
|
40
|
+
* MCP itself to verify identity, use `broker` mode (the MCP is its own audience-bound OAuth 2.1 AS).
|
|
41
|
+
*/
|
|
42
|
+
class BearerEdge {
|
|
43
|
+
_config;
|
|
44
|
+
_baseUrl;
|
|
45
|
+
_allowedBaseUrls;
|
|
46
|
+
get _isDelegated() {
|
|
47
|
+
return this._config.mode === creatio_1.BearerAuthMode.Delegated;
|
|
48
|
+
}
|
|
49
|
+
/** Identity Service base advertised to clients. */
|
|
50
|
+
get _identityBase() {
|
|
51
|
+
return this._config.idBaseUrl ?? `${this._baseUrl.replace(/\/$/, '')}/0`;
|
|
52
|
+
}
|
|
53
|
+
constructor(config, baseUrl) {
|
|
54
|
+
this._config = config;
|
|
55
|
+
this._baseUrl = baseUrl;
|
|
56
|
+
this._allowedBaseUrls = (0, base_url_guard_1.parseAllowedBaseUrls)((0, utils_1.env)('CREATIO_MCP_ALLOWED_BASE_URLS'));
|
|
57
|
+
}
|
|
58
|
+
_accept(req, token, next, userKey) {
|
|
59
|
+
const r = req;
|
|
60
|
+
r.userKey = userKey ?? (0, bearer_token_1.inspectBearer)(token).userKey;
|
|
61
|
+
r.bearerToken = token;
|
|
62
|
+
next();
|
|
63
|
+
}
|
|
64
|
+
_challenge(req, res, reason) {
|
|
65
|
+
if (this._isDelegated) {
|
|
66
|
+
const resourceMetadata = `${(0, public_origin_1.resolvePublicOrigin)(req)}${PROTECTED_RESOURCE_METADATA_PATH}`;
|
|
67
|
+
res.setHeader('WWW-Authenticate', `Bearer resource_metadata="${resourceMetadata}", error="${reason}"`);
|
|
68
|
+
}
|
|
69
|
+
res.status(401).json({
|
|
70
|
+
error: 'unauthorized',
|
|
71
|
+
error_description: reason === 'missing_token'
|
|
72
|
+
? 'A Creatio access token is required in the Authorization header.'
|
|
73
|
+
: `Bearer token rejected: ${reason}.`,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/** Delegated mode publishes RFC 9728 metadata so clients can discover the authorization server. */
|
|
77
|
+
registerRoutes(app) {
|
|
78
|
+
if (!this._isDelegated) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
app.get(PROTECTED_RESOURCE_METADATA_PATH, (req, res) => {
|
|
82
|
+
const resource = `${(0, public_origin_1.resolvePublicOrigin)(req)}/mcp`;
|
|
83
|
+
res.json(buildProtectedResourceMetadata(resource, this._identityBase));
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/** Express middleware guarding `/mcp`. Sets `req.bearerToken` / `req.userKey` / `req.baseUrlOverride`. */
|
|
87
|
+
mcpAuth() {
|
|
88
|
+
return (req, res, next) => {
|
|
89
|
+
const header = req.headers.authorization;
|
|
90
|
+
if (!header || !header.startsWith('Bearer ')) {
|
|
91
|
+
return this._challenge(req, res, 'missing_token');
|
|
92
|
+
}
|
|
93
|
+
const token = header.slice(7);
|
|
94
|
+
if (!this._isDelegated) {
|
|
95
|
+
// gateway: a per-request instance override is honored only here (from the trusted
|
|
96
|
+
// gateway). Still validate it — the override decides where the Bearer is sent, so a
|
|
97
|
+
// bad value is an SSRF / token-redirection lever even from a trusted source (CWE-918).
|
|
98
|
+
const baseOverride = req.headers[BASE_URL_OVERRIDE_HEADER];
|
|
99
|
+
if (typeof baseOverride === 'string' && baseOverride) {
|
|
100
|
+
if (!(0, base_url_guard_1.isAllowedBaseUrl)(baseOverride, this._allowedBaseUrls)) {
|
|
101
|
+
log_1.default.warn('bearer.base_url_override.rejected', { override: baseOverride });
|
|
102
|
+
res.status(400).json({
|
|
103
|
+
error: 'invalid_request',
|
|
104
|
+
error_description: 'Disallowed X-Creatio-Base-Url override.',
|
|
105
|
+
});
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
req.baseUrlOverride = baseOverride;
|
|
109
|
+
}
|
|
110
|
+
return this._accept(req, token, next);
|
|
111
|
+
}
|
|
112
|
+
// delegated: fail fast on an obviously-expired JWT; Creatio validates the rest on the call.
|
|
113
|
+
const decoded = (0, bearer_token_1.inspectBearer)(token);
|
|
114
|
+
if (decoded.isJwt && (0, bearer_token_1.isExpired)(decoded)) {
|
|
115
|
+
return this._challenge(req, res, 'token_expired');
|
|
116
|
+
}
|
|
117
|
+
return this._accept(req, token, next, decoded.userKey);
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
exports.BearerEdge = BearerEdge;
|
|
122
|
+
//# sourceMappingURL=bearer-edge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bearer-edge.js","sourceRoot":"","sources":["../../../src/server/bearer/bearer-edge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight, crypto-free inspection of an incoming Bearer token.
|
|
3
|
+
*
|
|
4
|
+
* In the stateless per-request model (delegated/gateway — both fully-trusted deployments) the Bearer
|
|
5
|
+
* is a Creatio access token. Creatio remains the cryptographic authority: it rejects bad/expired
|
|
6
|
+
* tokens with 401 on the actual API call. The MCP does NOT verify the signature here — it only needs
|
|
7
|
+
* a stable per-request identity (for session mapping / logging) and a cheap obviously-expired guard.
|
|
8
|
+
*
|
|
9
|
+
* SECURITY NOTE: the `userKey` returned here is therefore UNVERIFIED — it is read from an unsigned
|
|
10
|
+
* decode of a token the MCP does not trust. Use it only as a session/logging key, never as proof of
|
|
11
|
+
* an authenticated principal. (An untrusted direct client that needs the MCP to verify identity must
|
|
12
|
+
* use `broker` mode, where the MCP issues and verifies its own audience-bound tokens.)
|
|
13
|
+
*/
|
|
14
|
+
export interface DecodedBearer {
|
|
15
|
+
/** An UNVERIFIED stable identity for the token: `sub` claim when present, else a short
|
|
16
|
+
* fingerprint. Suitable for session keying/logging only — not an authenticated principal. */
|
|
17
|
+
userKey: string;
|
|
18
|
+
/** Expiry (epoch seconds) if the token is a JWT with `exp`. */
|
|
19
|
+
expSeconds?: number;
|
|
20
|
+
/** Whether the token parsed as a JWT (vs an opaque/reference token). */
|
|
21
|
+
isJwt: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** Extracts a stable userKey + optional expiry from a Bearer token without verifying its signature. */
|
|
24
|
+
export declare function inspectBearer(token: string): DecodedBearer;
|
|
25
|
+
/** True when a JWT's `exp` is in the past (with a small skew), so we can fail fast before calling Creatio. */
|
|
26
|
+
export declare function isExpired(decoded: DecodedBearer, nowMs?: number, skewSeconds?: number): boolean;
|
|
27
|
+
//# sourceMappingURL=bearer-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bearer-token.d.ts","sourceRoot":"","sources":["../../../src/server/bearer/bearer-token.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,aAAa;IAC7B;kGAC8F;IAC9F,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,KAAK,EAAE,OAAO,CAAC;CACf;AAED,uGAAuG;AACvG,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAY1D;AAED,8GAA8G;AAC9G,wBAAgB,SAAS,CACxB,OAAO,EAAE,aAAa,EACtB,KAAK,GAAE,MAAmB,EAC1B,WAAW,SAAK,GACd,OAAO,CAKT"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.inspectBearer = inspectBearer;
|
|
7
|
+
exports.isExpired = isExpired;
|
|
8
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
9
|
+
/** Extracts a stable userKey + optional expiry from a Bearer token without verifying its signature. */
|
|
10
|
+
function inspectBearer(token) {
|
|
11
|
+
const decoded = safeDecode(token);
|
|
12
|
+
if (decoded && typeof decoded === 'object') {
|
|
13
|
+
const sub = typeof decoded.sub === 'string' ? decoded.sub : undefined;
|
|
14
|
+
const exp = typeof decoded.exp === 'number' ? decoded.exp : undefined;
|
|
15
|
+
return {
|
|
16
|
+
userKey: sub ?? fingerprint(token),
|
|
17
|
+
...(exp !== undefined ? { expSeconds: exp } : {}),
|
|
18
|
+
isJwt: true,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return { userKey: fingerprint(token), isJwt: false };
|
|
22
|
+
}
|
|
23
|
+
/** True when a JWT's `exp` is in the past (with a small skew), so we can fail fast before calling Creatio. */
|
|
24
|
+
function isExpired(decoded, nowMs = Date.now(), skewSeconds = 30) {
|
|
25
|
+
if (decoded.expSeconds === undefined) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
return nowMs / 1000 > decoded.expSeconds + skewSeconds;
|
|
29
|
+
}
|
|
30
|
+
function safeDecode(token) {
|
|
31
|
+
try {
|
|
32
|
+
const decoded = jsonwebtoken_1.default.decode(token);
|
|
33
|
+
return decoded && typeof decoded === 'object' ? decoded : null;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A short, non-reversible fingerprint of an opaque token, used only as a per-request session key.
|
|
41
|
+
* Not security-sensitive (the token itself is the credential); it just needs to be stable + opaque.
|
|
42
|
+
*/
|
|
43
|
+
function fingerprint(token) {
|
|
44
|
+
let hash = 0;
|
|
45
|
+
for (let i = 0; i < token.length; i++) {
|
|
46
|
+
hash = (hash * 31 + token.charCodeAt(i)) | 0;
|
|
47
|
+
}
|
|
48
|
+
return `tok_${(hash >>> 0).toString(36)}`;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=bearer-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bearer-token.js","sourceRoot":"","sources":["../../../src/server/bearer/bearer-token.ts"],"names":[],"mappings":";;;;;AA0BA,sCAYC;AAGD,8BASC;AAlDD,gEAA+B;AAyB/B,uGAAuG;AACvG,SAAgB,aAAa,CAAC,KAAa;IAC1C,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC5C,MAAM,GAAG,GAAG,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;QACtE,MAAM,GAAG,GAAG,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;QACtE,OAAO;YACN,OAAO,EAAE,GAAG,IAAI,WAAW,CAAC,KAAK,CAAC;YAClC,GAAG,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjD,KAAK,EAAE,IAAI;SACX,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AACtD,CAAC;AAED,8GAA8G;AAC9G,SAAgB,SAAS,CACxB,OAAsB,EACtB,QAAgB,IAAI,CAAC,GAAG,EAAE,EAC1B,WAAW,GAAG,EAAE;IAEhB,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,GAAG,WAAW,CAAC;AACxD,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAChC,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,sBAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClC,OAAO,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAE,OAA0B,CAAC,CAAC,CAAC,IAAI,CAAC;IACpF,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED;;;GAGG;AACH,SAAS,WAAW,CAAC,KAAa;IACjC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,IAAI,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/bearer/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./bearer-token"), exports);
|
|
18
|
+
__exportStar(require("./bearer-edge"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/bearer/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA+B;AAC/B,gDAA8B"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SessionContext } from '../../sessions';
|
|
2
|
+
import type { CreatioClientConfig } from '../../creatio';
|
|
3
|
+
import type { Express, RequestHandler } from 'express';
|
|
4
|
+
export interface RateLimitOptions {
|
|
5
|
+
windowMs: number;
|
|
6
|
+
max: number;
|
|
7
|
+
}
|
|
8
|
+
export type RateLimitFactory = (options: RateLimitOptions) => RequestHandler;
|
|
9
|
+
/**
|
|
10
|
+
* The HTTP auth strategy for the `/mcp` surface: a guard middleware, the mode-specific discovery /
|
|
11
|
+
* OAuth routes, and optional periodic cleanup. Extracting this keeps {@link HttpServer} from
|
|
12
|
+
* branching on `auth.kind` (and from owning the `config!`/`as` casts) — it just consumes a strategy.
|
|
13
|
+
*/
|
|
14
|
+
export interface AuthEdge {
|
|
15
|
+
mcpAuth(): RequestHandler;
|
|
16
|
+
registerRoutes(app: Express, rateLimit: RateLimitFactory): void;
|
|
17
|
+
/** Periodic maintenance (e.g. evict expired broker codes/tokens); omitted when there is none. */
|
|
18
|
+
cleanup?(): void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Build the auth edge for the configured mode, or `undefined` when no `/mcp` auth applies
|
|
22
|
+
* (e.g. a single-identity stdio-style config served over HTTP). The one place that maps an auth
|
|
23
|
+
* config to its HTTP strategy.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createAuthEdge(config: CreatioClientConfig | undefined, session: SessionContext): AuthEdge | undefined;
|
|
26
|
+
//# sourceMappingURL=auth-edge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-edge.d.ts","sourceRoot":"","sources":["../../../src/server/http/auth-edge.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAMhD,OAAO,KAAK,EAAsC,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC7F,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEvD,MAAM,WAAW,gBAAgB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACZ;AACD,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,cAAc,CAAC;AAE7E;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACxB,OAAO,IAAI,cAAc,CAAC;IAC1B,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAChE,iGAAiG;IACjG,OAAO,CAAC,IAAI,IAAI,CAAC;CACjB;AA0DD;;;;GAIG;AACH,wBAAgB,cAAc,CAC7B,MAAM,EAAE,mBAAmB,GAAG,SAAS,EACvC,OAAO,EAAE,cAAc,GACrB,QAAQ,GAAG,SAAS,CAmBtB"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAuthEdge = createAuthEdge;
|
|
4
|
+
const creatio_1 = require("../../creatio");
|
|
5
|
+
const bearer_1 = require("../bearer");
|
|
6
|
+
const oauth_1 = require("../oauth");
|
|
7
|
+
const broker_handlers_1 = require("./broker-handlers");
|
|
8
|
+
/** Stateless per-request Bearer edge (delegated / gateway). */
|
|
9
|
+
class BearerAuthEdge {
|
|
10
|
+
_edge;
|
|
11
|
+
constructor(_edge) {
|
|
12
|
+
this._edge = _edge;
|
|
13
|
+
}
|
|
14
|
+
mcpAuth() {
|
|
15
|
+
return this._edge.mcpAuth();
|
|
16
|
+
}
|
|
17
|
+
registerRoutes(app) {
|
|
18
|
+
this._edge.registerRoutes(app);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Broker edge: the MCP's own OAuth 2.1 AS + the brokered Creatio login. */
|
|
22
|
+
class BrokerAuthEdge {
|
|
23
|
+
_handlers;
|
|
24
|
+
_oauth;
|
|
25
|
+
_session;
|
|
26
|
+
// Per-route fixed-window limits (per IP) for the unauthenticated broker OAuth surface.
|
|
27
|
+
static RL_AUTH_FLOW = { windowMs: 60_000, max: 60 };
|
|
28
|
+
static RL_TOKEN = { windowMs: 60_000, max: 30 };
|
|
29
|
+
static RL_REGISTER = { windowMs: 60_000, max: 10 };
|
|
30
|
+
constructor(_handlers, _oauth, _session) {
|
|
31
|
+
this._handlers = _handlers;
|
|
32
|
+
this._oauth = _oauth;
|
|
33
|
+
this._session = _session;
|
|
34
|
+
}
|
|
35
|
+
mcpAuth() {
|
|
36
|
+
return this._handlers.mcpAuth();
|
|
37
|
+
}
|
|
38
|
+
registerRoutes(app, rateLimit) {
|
|
39
|
+
const h = this._handlers;
|
|
40
|
+
app.get('/.well-known/oauth-authorization-server', (q, s) => h.handleMetadata(q, s));
|
|
41
|
+
app.get('/.well-known/oauth-protected-resource', (q, s) => h.handleProtectedResourceMetadata(q, s));
|
|
42
|
+
app.post('/register', rateLimit(BrokerAuthEdge.RL_REGISTER), (q, s) => h.handleRegister(q, s));
|
|
43
|
+
app.get('/authorize', rateLimit(BrokerAuthEdge.RL_AUTH_FLOW), (q, s) => h.handleAuthorize(q, s));
|
|
44
|
+
app.get('/oauth/callback', rateLimit(BrokerAuthEdge.RL_AUTH_FLOW), (q, s) => h.handleCallback(q, s));
|
|
45
|
+
app.post('/token', rateLimit(BrokerAuthEdge.RL_TOKEN), (q, s) => h.handleToken(q, s));
|
|
46
|
+
app.post('/revoke', rateLimit(BrokerAuthEdge.RL_TOKEN), (q, s) => h.handleRevoke(q, s));
|
|
47
|
+
}
|
|
48
|
+
cleanup() {
|
|
49
|
+
// Broker keeps transient state (codes, pending auths, user tokens) — keep the maps bounded.
|
|
50
|
+
this._oauth.cleanup();
|
|
51
|
+
void this._session.evictStaleTokens();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build the auth edge for the configured mode, or `undefined` when no `/mcp` auth applies
|
|
56
|
+
* (e.g. a single-identity stdio-style config served over HTTP). The one place that maps an auth
|
|
57
|
+
* config to its HTTP strategy.
|
|
58
|
+
*/
|
|
59
|
+
function createAuthEdge(config, session) {
|
|
60
|
+
const auth = config?.auth;
|
|
61
|
+
if (!auth || !config) {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
if (auth.kind === creatio_1.AuthProviderType.OAuth2Bearer) {
|
|
65
|
+
return new BearerAuthEdge(new bearer_1.BearerEdge(auth, config.baseUrl));
|
|
66
|
+
}
|
|
67
|
+
if (auth.kind === creatio_1.AuthProviderType.Broker) {
|
|
68
|
+
const brokerAuth = auth;
|
|
69
|
+
const oauth = new oauth_1.OAuthServer(brokerAuth.jwtSecret);
|
|
70
|
+
const handlers = new broker_handlers_1.BrokerHandlers(oauth, new creatio_1.CreatioOAuthClient(config.baseUrl, brokerAuth), session);
|
|
71
|
+
return new BrokerAuthEdge(handlers, oauth, session);
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=auth-edge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-edge.js","sourceRoot":"","sources":["../../../src/server/http/auth-edge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { CreatioOAuthClient } from '../../creatio';
|
|
2
|
+
import { SessionContext } from '../../sessions';
|
|
3
|
+
import { OAuthServer } from '../oauth';
|
|
4
|
+
import type { NextFunction, Request, Response } from 'express';
|
|
5
|
+
/**
|
|
6
|
+
* Broker mode HTTP handlers: the MCP is its own OAuth 2.1 authorization server for clients and
|
|
7
|
+
* brokers the user login to Creatio (authorization_code + PKCE). The MCP-client PKCE and our own
|
|
8
|
+
* Creatio-leg PKCE are kept in separate fields (server-side {@link OAuthServer.createPendingAuthorization})
|
|
9
|
+
* — nothing is embedded in the Creatio `state`, so the two never collide.
|
|
10
|
+
*/
|
|
11
|
+
export declare class BrokerHandlers {
|
|
12
|
+
private readonly _oauth;
|
|
13
|
+
private readonly _creatio;
|
|
14
|
+
private readonly _session;
|
|
15
|
+
private readonly _callbackPath;
|
|
16
|
+
constructor(_oauth: OAuthServer, _creatio: CreatioOAuthClient, _session: SessionContext);
|
|
17
|
+
private _callbackUrl;
|
|
18
|
+
/** RFC 6750 `401` challenge pointing at our protected-resource metadata. `invalid_token` tells a
|
|
19
|
+
* client holding a now-unusable token to re-authenticate (vs. a plain "no credentials" prompt). */
|
|
20
|
+
private _challenge;
|
|
21
|
+
private _redirectError;
|
|
22
|
+
handleMetadata(req: Request, res: Response): void;
|
|
23
|
+
/** RFC 9728: in broker mode WE are the authorization server, so it points back at this origin. */
|
|
24
|
+
handleProtectedResourceMetadata(req: Request, res: Response): void;
|
|
25
|
+
/**
|
|
26
|
+
* Guards `/mcp`: validates the token THIS server issued, confirms we still hold the user's
|
|
27
|
+
* brokered Creatio tokens, and exposes the `userKey`. The Creatio tokens are kept in memory and
|
|
28
|
+
* are therefore lost on restart, while the token we issued (a stateless JWT) survives — so a
|
|
29
|
+
* reconnecting client looks authenticated but every Creatio call would fail. When the tokens are
|
|
30
|
+
* gone we answer `401` with `error="invalid_token"` so the client transparently re-runs OAuth.
|
|
31
|
+
*/
|
|
32
|
+
mcpAuth(): (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
33
|
+
handleRegister(req: Request, res: Response): void;
|
|
34
|
+
handleAuthorize(req: Request, res: Response): Promise<void>;
|
|
35
|
+
handleCallback(req: Request, res: Response): Promise<void>;
|
|
36
|
+
handleToken(req: Request, res: Response): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* RFC 7009 token revocation / logout: invalidate the user's brokered session. Resolve the user
|
|
39
|
+
* from the presented token, revoke their Creatio token upstream (best-effort), and purge the
|
|
40
|
+
* server-side Creatio tokens + our issued refresh tokens. Always answers 200 — even for an
|
|
41
|
+
* unknown token — so it is not a token-validity oracle.
|
|
42
|
+
*/
|
|
43
|
+
handleRevoke(req: Request, res: Response): Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=broker-handlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broker-handlers.d.ts","sourceRoot":"","sources":["../../../src/server/http/broker-handlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGhD,OAAO,EAAE,WAAW,EAAmB,MAAM,UAAU,CAAC;AAIxD,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAiC/D;;;;;GAKG;AACH,qBAAa,cAAc;IAIzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAL1B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;gBAGjC,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,kBAAkB,EAC5B,QAAQ,EAAE,cAAc;IAG1C,OAAO,CAAC,YAAY;IAIpB;wGACoG;IACpG,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,cAAc;IAiBf,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI;IAIxD,kGAAkG;IAC3F,+BAA+B,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI;IAKzE;;;;;;OAMG;IACI,OAAO,KACC,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC;IA2BvE,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI;IAU3C,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAyC3D,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAuC1D,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBpE;;;;;OAKG;IACU,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAgBrE"}
|