mcp-creatio 0.3.10 → 0.4.1
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 +117 -108
- package/dist/cli.d.ts +5 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +18 -11
- package/dist/cli.js.map +1 -1
- package/dist/creatio/auth/auth.d.ts +2 -0
- package/dist/creatio/auth/auth.d.ts.map +1 -1
- package/dist/creatio/auth/auth.js.map +1 -1
- package/dist/creatio/auth/providers/base-provider.d.ts +1 -0
- package/dist/creatio/auth/providers/base-provider.d.ts.map +1 -1
- package/dist/creatio/auth/providers/base-provider.js +3 -0
- package/dist/creatio/auth/providers/base-provider.js.map +1 -1
- package/dist/creatio/auth/providers/oauth2-code-provider.d.ts +3 -0
- package/dist/creatio/auth/providers/oauth2-code-provider.d.ts.map +1 -1
- package/dist/creatio/auth/providers/oauth2-code-provider.js +30 -24
- package/dist/creatio/auth/providers/oauth2-code-provider.js.map +1 -1
- package/dist/creatio/engines/admin-operation/admin-operation-engine.d.ts +13 -0
- package/dist/creatio/engines/admin-operation/admin-operation-engine.d.ts.map +1 -0
- package/dist/creatio/engines/admin-operation/admin-operation-engine.js +27 -0
- package/dist/creatio/engines/admin-operation/admin-operation-engine.js.map +1 -0
- package/dist/creatio/engines/configuration/configuration-engine.d.ts +10 -0
- package/dist/creatio/engines/configuration/configuration-engine.d.ts.map +1 -0
- package/dist/creatio/engines/configuration/configuration-engine.js +18 -0
- package/dist/creatio/engines/configuration/configuration-engine.js.map +1 -0
- package/dist/creatio/engines/engine-manager.d.ts +13 -1
- package/dist/creatio/engines/engine-manager.d.ts.map +1 -1
- package/dist/creatio/engines/engine-manager.js +17 -0
- package/dist/creatio/engines/engine-manager.js.map +1 -1
- package/dist/creatio/engines/engine-registry.d.ts +3 -0
- package/dist/creatio/engines/engine-registry.d.ts.map +1 -1
- package/dist/creatio/engines/engine-registry.js +3 -0
- package/dist/creatio/engines/engine-registry.js.map +1 -1
- package/dist/creatio/engines/feature/feature-engine.d.ts +10 -0
- package/dist/creatio/engines/feature/feature-engine.d.ts.map +1 -0
- package/dist/creatio/engines/feature/feature-engine.js +18 -0
- package/dist/creatio/engines/feature/feature-engine.js.map +1 -0
- package/dist/creatio/engines/index.d.ts +3 -0
- package/dist/creatio/engines/index.d.ts.map +1 -1
- package/dist/creatio/engines/index.js +3 -0
- package/dist/creatio/engines/index.js.map +1 -1
- package/dist/creatio/provider-context.d.ts +4 -1
- package/dist/creatio/provider-context.d.ts.map +1 -1
- package/dist/creatio/providers/admin-operation-provider.d.ts +27 -0
- package/dist/creatio/providers/admin-operation-provider.d.ts.map +1 -0
- package/dist/creatio/providers/admin-operation-provider.js +3 -0
- package/dist/creatio/providers/admin-operation-provider.js.map +1 -0
- package/dist/creatio/providers/configuration-provider.d.ts +19 -0
- package/dist/creatio/providers/configuration-provider.d.ts.map +1 -0
- package/dist/creatio/providers/configuration-provider.js +3 -0
- package/dist/creatio/providers/configuration-provider.js.map +1 -0
- package/dist/creatio/providers/feature-provider.d.ts +10 -0
- package/dist/creatio/providers/feature-provider.d.ts.map +1 -0
- package/dist/creatio/providers/feature-provider.js +3 -0
- package/dist/creatio/providers/feature-provider.js.map +1 -0
- package/dist/creatio/providers/index.d.ts +3 -0
- package/dist/creatio/providers/index.d.ts.map +1 -1
- package/dist/creatio/providers/index.js +3 -0
- package/dist/creatio/providers/index.js.map +1 -1
- package/dist/creatio/services/admin-operation-service-provider.d.ts +15 -0
- package/dist/creatio/services/admin-operation-service-provider.d.ts.map +1 -0
- package/dist/creatio/services/admin-operation-service-provider.js +69 -0
- package/dist/creatio/services/admin-operation-service-provider.js.map +1 -0
- package/dist/creatio/services/configuration-service-provider.d.ts +14 -0
- package/dist/creatio/services/configuration-service-provider.d.ts.map +1 -0
- package/dist/creatio/services/configuration-service-provider.js +90 -0
- package/dist/creatio/services/configuration-service-provider.js.map +1 -0
- package/dist/creatio/services/creatio-service-context.d.ts +4 -1
- package/dist/creatio/services/creatio-service-context.d.ts.map +1 -1
- package/dist/creatio/services/creatio-service-context.js +9 -0
- package/dist/creatio/services/creatio-service-context.js.map +1 -1
- package/dist/creatio/services/feature-service-provider.d.ts +10 -0
- package/dist/creatio/services/feature-service-provider.d.ts.map +1 -0
- package/dist/creatio/services/feature-service-provider.js +43 -0
- package/dist/creatio/services/feature-service-provider.js.map +1 -0
- package/dist/creatio/services/http-client.d.ts.map +1 -1
- package/dist/creatio/services/http-client.js +0 -1
- package/dist/creatio/services/http-client.js.map +1 -1
- package/dist/creatio/services/index.d.ts +3 -0
- package/dist/creatio/services/index.d.ts.map +1 -1
- package/dist/creatio/services/index.js +3 -0
- package/dist/creatio/services/index.js.map +1 -1
- package/dist/creatio/services/metadata-store.d.ts +5 -0
- package/dist/creatio/services/metadata-store.d.ts.map +1 -1
- package/dist/creatio/services/metadata-store.js +18 -6
- package/dist/creatio/services/metadata-store.js.map +1 -1
- package/dist/creatio/services/odata-crud-provider.d.ts +2 -0
- package/dist/creatio/services/odata-crud-provider.d.ts.map +1 -1
- package/dist/creatio/services/odata-crud-provider.js +10 -1
- package/dist/creatio/services/odata-crud-provider.js.map +1 -1
- package/dist/server/http/creatio-oauth-handlers.d.ts +0 -1
- package/dist/server/http/creatio-oauth-handlers.d.ts.map +1 -1
- package/dist/server/http/creatio-oauth-handlers.js +30 -23
- package/dist/server/http/creatio-oauth-handlers.js.map +1 -1
- package/dist/server/http/httpServer.d.ts +9 -0
- package/dist/server/http/httpServer.d.ts.map +1 -1
- package/dist/server/http/httpServer.js +34 -11
- package/dist/server/http/httpServer.js.map +1 -1
- package/dist/server/http/mcp-handlers.d.ts.map +1 -1
- package/dist/server/http/mcp-handlers.js +4 -1
- package/dist/server/http/mcp-handlers.js.map +1 -1
- package/dist/server/http/mcp-oauth-handlers.d.ts.map +1 -1
- package/dist/server/http/mcp-oauth-handlers.js +18 -6
- package/dist/server/http/mcp-oauth-handlers.js.map +1 -1
- package/dist/server/http/middleware.d.ts +7 -0
- package/dist/server/http/middleware.d.ts.map +1 -1
- package/dist/server/http/middleware.js +23 -0
- package/dist/server/http/middleware.js.map +1 -1
- package/dist/server/http/rate-limiter.d.ts +24 -0
- package/dist/server/http/rate-limiter.d.ts.map +1 -0
- package/dist/server/http/rate-limiter.js +42 -0
- package/dist/server/http/rate-limiter.js.map +1 -0
- package/dist/server/mcp/prompts-data.d.ts +58 -0
- package/dist/server/mcp/prompts-data.d.ts.map +1 -1
- package/dist/server/mcp/prompts-data.js +391 -1
- package/dist/server/mcp/prompts-data.js.map +1 -1
- package/dist/server/mcp/server.d.ts.map +1 -1
- package/dist/server/mcp/server.js +69 -0
- package/dist/server/mcp/server.js.map +1 -1
- package/dist/server/mcp/tools-data.d.ts +63 -0
- package/dist/server/mcp/tools-data.d.ts.map +1 -1
- package/dist/server/mcp/tools-data.js +110 -5
- package/dist/server/mcp/tools-data.js.map +1 -1
- package/dist/server/oauth/oauth-server.d.ts +0 -1
- package/dist/server/oauth/oauth-server.d.ts.map +1 -1
- package/dist/server/oauth/oauth-server.js +11 -21
- package/dist/server/oauth/oauth-server.js.map +1 -1
- package/dist/server/oauth/storage.d.ts +0 -2
- package/dist/server/oauth/storage.d.ts.map +1 -1
- package/dist/server/oauth/storage.js +0 -6
- package/dist/server/oauth/storage.js.map +1 -1
- package/dist/server/oauth/validators.d.ts +6 -0
- package/dist/server/oauth/validators.d.ts.map +1 -1
- package/dist/server/oauth/validators.js +28 -0
- package/dist/server/oauth/validators.js.map +1 -1
- package/dist/services/session-context.d.ts +8 -7
- package/dist/services/session-context.d.ts.map +1 -1
- package/dist/services/session-context.js +7 -27
- package/dist/services/session-context.js.map +1 -1
- package/package.json +19 -10
- package/.dockerignore +0 -12
- package/.editorconfig +0 -14
- package/.eslintrc.cjs +0 -18
- package/.gitattributes +0 -8
- package/.github/workflows/docker-publish.yml +0 -50
- package/.prettierignore +0 -3
- package/.prettierrc +0 -9
- package/.vscode/launch.json +0 -23
- package/.vscode/mcp.json +0 -13
- package/.vscode/settings.json +0 -16
- package/Agent.md +0 -187
- package/Debug.md +0 -32
- package/Dockerfile +0 -23
- package/docs/coding-style.md +0 -30
- package/eslint.config.cjs +0 -95
- package/src/cli.ts +0 -162
- package/src/config-builder.ts +0 -76
- package/src/consts.ts +0 -3
- package/src/creatio/auth/auth-manager.ts +0 -27
- package/src/creatio/auth/auth.ts +0 -31
- package/src/creatio/auth/index.ts +0 -3
- package/src/creatio/auth/providers/base-oauth2-provider.ts +0 -62
- package/src/creatio/auth/providers/base-provider.ts +0 -42
- package/src/creatio/auth/providers/index.ts +0 -4
- package/src/creatio/auth/providers/legacy-provider.ts +0 -70
- package/src/creatio/auth/providers/oauth2-code-provider.ts +0 -252
- package/src/creatio/auth/providers/oauth2-provider.ts +0 -91
- package/src/creatio/auth/providers/type.ts +0 -5
- package/src/creatio/client-config.ts +0 -34
- package/src/creatio/engines/crud/crud-engine.ts +0 -47
- package/src/creatio/engines/engine-manager.ts +0 -102
- package/src/creatio/engines/engine-registry.ts +0 -36
- package/src/creatio/engines/engine.ts +0 -3
- package/src/creatio/engines/index.ts +0 -7
- package/src/creatio/engines/process/process-engine.ts +0 -20
- package/src/creatio/engines/sys-settings/sys-settings-engine.ts +0 -41
- package/src/creatio/engines/user/user-engine.ts +0 -20
- package/src/creatio/index.ts +0 -6
- package/src/creatio/provider-context.ts +0 -10
- package/src/creatio/providers/crud-provider.ts +0 -45
- package/src/creatio/providers/index.ts +0 -4
- package/src/creatio/providers/process-provider.ts +0 -15
- package/src/creatio/providers/sys-settings-provider.ts +0 -63
- package/src/creatio/providers/user-provider.ts +0 -12
- package/src/creatio/services/creatio-service-context.ts +0 -38
- package/src/creatio/services/http-client.ts +0 -174
- package/src/creatio/services/index.ts +0 -7
- package/src/creatio/services/metadata-store.ts +0 -181
- package/src/creatio/services/odata-crud-provider.ts +0 -210
- package/src/creatio/services/process-service-provider.ts +0 -76
- package/src/creatio/services/sys-settings-service-provider.ts +0 -192
- package/src/creatio/services/user-info-provider.ts +0 -41
- package/src/index.ts +0 -44
- package/src/log.ts +0 -183
- package/src/server/http/creatio-oauth-handlers.ts +0 -146
- package/src/server/http/httpServer.ts +0 -150
- package/src/server/http/index.ts +0 -5
- package/src/server/http/mcp-handlers.ts +0 -92
- package/src/server/http/mcp-oauth-handlers.ts +0 -108
- package/src/server/http/middleware.ts +0 -91
- package/src/server/index.ts +0 -2
- package/src/server/mcp/filters.ts +0 -97
- package/src/server/mcp/index.ts +0 -1
- package/src/server/mcp/prompts-data.ts +0 -896
- package/src/server/mcp/server.ts +0 -331
- package/src/server/mcp/tools-data.ts +0 -592
- package/src/server/oauth/client-manager.ts +0 -47
- package/src/server/oauth/index.ts +0 -6
- package/src/server/oauth/oauth-server.ts +0 -185
- package/src/server/oauth/storage.ts +0 -106
- package/src/server/oauth/token-manager.ts +0 -80
- package/src/server/oauth/types.ts +0 -55
- package/src/server/oauth/validators.ts +0 -56
- package/src/services/index.ts +0 -2
- package/src/services/session-context.ts +0 -232
- package/src/services/token-refresh-scheduler.ts +0 -68
- package/src/types/index.ts +0 -1
- package/src/types/network.ts +0 -7
- package/src/utils/context.ts +0 -49
- package/src/utils/env.ts +0 -12
- package/src/utils/index.ts +0 -5
- package/src/utils/mcp.ts +0 -8
- package/src/utils/network.ts +0 -65
- package/src/utils/pkce.ts +0 -39
- package/src/version.ts +0 -15
- package/tsconfig.json +0 -28
package/src/log.ts
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
export type LogLevel = 'info' | 'warn' | 'error';
|
|
2
|
-
export type LogVerbosity = LogLevel | 'silent';
|
|
3
|
-
export type CreatioAuthKind = 'legacy' | 'oauth2' | 'oauth2_code';
|
|
4
|
-
|
|
5
|
-
export interface LogConfig {
|
|
6
|
-
level?: LogLevel;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
let _correlationId: string | undefined;
|
|
10
|
-
let _stderrOnly = false;
|
|
11
|
-
|
|
12
|
-
function resolveLogVerbosity(): LogVerbosity {
|
|
13
|
-
const raw = (process.env.MCP_CREATIO_LOG_LEVEL || 'silent').toLowerCase();
|
|
14
|
-
if (raw === 'info') {
|
|
15
|
-
return 'info';
|
|
16
|
-
}
|
|
17
|
-
if (raw === 'warn' || raw === 'warning') {
|
|
18
|
-
return 'warn';
|
|
19
|
-
}
|
|
20
|
-
if (raw === 'error') {
|
|
21
|
-
return 'error';
|
|
22
|
-
}
|
|
23
|
-
return 'silent';
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function shouldLog(level: LogLevel): boolean {
|
|
27
|
-
const verbosity = resolveLogVerbosity();
|
|
28
|
-
if (verbosity === 'silent') {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
if (verbosity === 'error') {
|
|
32
|
-
return level === 'error';
|
|
33
|
-
}
|
|
34
|
-
if (verbosity === 'warn') {
|
|
35
|
-
return level === 'warn' || level === 'error';
|
|
36
|
-
}
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function setCorrelationId(correlationId: string) {
|
|
41
|
-
_correlationId = correlationId;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function getCorrelationId(): string | undefined {
|
|
45
|
-
return _correlationId;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function clearCorrelationId() {
|
|
49
|
-
_correlationId = undefined;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function timestamp() {
|
|
53
|
-
return new Date().toISOString();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function output(level: LogLevel, msg: string, meta?: Record<string, any>) {
|
|
57
|
-
if (!shouldLog(level)) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
const entry: any = { ts: timestamp(), level, msg };
|
|
61
|
-
if (_correlationId) {
|
|
62
|
-
entry.correlationId = _correlationId;
|
|
63
|
-
}
|
|
64
|
-
if (meta && Object.keys(meta).length) {
|
|
65
|
-
entry.meta = meta;
|
|
66
|
-
}
|
|
67
|
-
const line = JSON.stringify(entry);
|
|
68
|
-
if (_stderrOnly) {
|
|
69
|
-
process.stderr.write(line + '\n');
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
if (level === 'error') {
|
|
73
|
-
console.error(line);
|
|
74
|
-
} else if (level === 'warn') {
|
|
75
|
-
console.warn(line);
|
|
76
|
-
} else {
|
|
77
|
-
console.log(line);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export function useStderrOnlyLogs() {
|
|
82
|
-
_stderrOnly = true;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function info(msg: string, meta?: Record<string, any>) {
|
|
86
|
-
output('info', msg, meta);
|
|
87
|
-
}
|
|
88
|
-
export function warn(msg: string, meta?: Record<string, any>) {
|
|
89
|
-
output('warn', msg, meta);
|
|
90
|
-
}
|
|
91
|
-
export function error(msg: string, meta?: Record<string, any>) {
|
|
92
|
-
output('error', msg, meta);
|
|
93
|
-
}
|
|
94
|
-
export function appStart(meta?: Record<string, any>) {
|
|
95
|
-
info('app.start', meta);
|
|
96
|
-
}
|
|
97
|
-
export function appStop(meta?: Record<string, any>) {
|
|
98
|
-
info('app.stop', meta);
|
|
99
|
-
}
|
|
100
|
-
export function serverStart(name?: string, version?: string, meta?: Record<string, any>) {
|
|
101
|
-
info('mcp.server.start', { name, version, ...meta });
|
|
102
|
-
}
|
|
103
|
-
export function serverStop(name?: string, version?: string, meta?: Record<string, any>) {
|
|
104
|
-
info('mcp.server.stop', { name, version, ...meta });
|
|
105
|
-
}
|
|
106
|
-
export function httpStart(port: number, meta?: Record<string, any>) {
|
|
107
|
-
info('http.server.start', { port, ...meta });
|
|
108
|
-
}
|
|
109
|
-
export function httpStop(port: number, meta?: Record<string, any>) {
|
|
110
|
-
info('http.server.stop', { port, ...meta });
|
|
111
|
-
}
|
|
112
|
-
export function sessionConnect(sessionId: string, ip?: string, meta?: Record<string, any>) {
|
|
113
|
-
info('session.connect', { sessionId, ip, ...meta });
|
|
114
|
-
}
|
|
115
|
-
export function sessionDisconnect(sessionId: string, ip?: string, meta?: Record<string, any>) {
|
|
116
|
-
info('session.disconnect', { sessionId, ip, ...meta });
|
|
117
|
-
}
|
|
118
|
-
export function creatioAuthStart(baseUrl: string, authKind?: CreatioAuthKind) {
|
|
119
|
-
info('creatio.auth.start', { baseUrl, authKind });
|
|
120
|
-
}
|
|
121
|
-
export function creatioAuthOk(baseUrl: string, authKind?: CreatioAuthKind) {
|
|
122
|
-
info('creatio.auth.ok', { baseUrl, authKind });
|
|
123
|
-
}
|
|
124
|
-
export function creatioAuthFailed(baseUrl: string, error: string, authKind?: CreatioAuthKind) {
|
|
125
|
-
warn('creatio.auth.failed', { baseUrl, error, authKind });
|
|
126
|
-
}
|
|
127
|
-
export function httpRequest(method: string, url: string, meta?: Record<string, any>) {
|
|
128
|
-
info('http.request', { method, url, ...meta });
|
|
129
|
-
}
|
|
130
|
-
export function httpResponse(
|
|
131
|
-
method: string,
|
|
132
|
-
url: string,
|
|
133
|
-
status: number,
|
|
134
|
-
duration?: number,
|
|
135
|
-
meta?: Record<string, any>,
|
|
136
|
-
) {
|
|
137
|
-
info('http.response', { method, url, status, duration, ...meta });
|
|
138
|
-
}
|
|
139
|
-
export function httpError(
|
|
140
|
-
method: string,
|
|
141
|
-
url: string,
|
|
142
|
-
errorMsg: string,
|
|
143
|
-
meta?: Record<string, any>,
|
|
144
|
-
) {
|
|
145
|
-
error('http.error', { method, url, error: errorMsg, ...meta });
|
|
146
|
-
}
|
|
147
|
-
export function logOperation(
|
|
148
|
-
operation: string,
|
|
149
|
-
duration: number,
|
|
150
|
-
success: boolean,
|
|
151
|
-
meta?: Record<string, any>,
|
|
152
|
-
) {
|
|
153
|
-
info(`operation.${success ? 'success' : 'failed'}`, {
|
|
154
|
-
operation,
|
|
155
|
-
duration,
|
|
156
|
-
...meta,
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
export default {
|
|
161
|
-
info,
|
|
162
|
-
warn,
|
|
163
|
-
error,
|
|
164
|
-
useStderrOnlyLogs,
|
|
165
|
-
appStart,
|
|
166
|
-
appStop,
|
|
167
|
-
serverStart,
|
|
168
|
-
serverStop,
|
|
169
|
-
httpStart,
|
|
170
|
-
httpStop,
|
|
171
|
-
sessionConnect,
|
|
172
|
-
sessionDisconnect,
|
|
173
|
-
creatioAuthStart,
|
|
174
|
-
creatioAuthOk,
|
|
175
|
-
creatioAuthFailed,
|
|
176
|
-
httpRequest,
|
|
177
|
-
httpResponse,
|
|
178
|
-
httpError,
|
|
179
|
-
logOperation,
|
|
180
|
-
setCorrelationId,
|
|
181
|
-
getCorrelationId,
|
|
182
|
-
clearCorrelationId,
|
|
183
|
-
};
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import log from '../../log';
|
|
2
|
-
import { SessionContext } from '../../services';
|
|
3
|
-
import { runWithContext } from '../../utils';
|
|
4
|
-
|
|
5
|
-
import type { Server } from '../mcp';
|
|
6
|
-
import type { OAuthServer } from '../oauth';
|
|
7
|
-
import type { Request, Response } from 'express';
|
|
8
|
-
|
|
9
|
-
export class CreatioOAuthHandlers {
|
|
10
|
-
private readonly _sessionContext = SessionContext.instance;
|
|
11
|
-
private readonly _server: Server;
|
|
12
|
-
private readonly _oauthServer: OAuthServer;
|
|
13
|
-
|
|
14
|
-
constructor(server: Server, oauthServer: OAuthServer) {
|
|
15
|
-
this._server = server;
|
|
16
|
-
this._oauthServer = oauthServer;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
private _mapAllSessionsToUser(userKey: string): void {
|
|
20
|
-
const sessions = this._sessionContext.getAllSessions();
|
|
21
|
-
const sessionIds = sessions.map((s) => s.id);
|
|
22
|
-
log.info('mapping_all_sessions', { userKey, sessionCount: sessionIds.length, sessionIds });
|
|
23
|
-
for (const sessionId of sessionIds) {
|
|
24
|
-
this._sessionContext.setSessionUserKey(sessionId, userKey);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
public async handleOAuthStart(req: Request, res: Response): Promise<void> {
|
|
29
|
-
try {
|
|
30
|
-
const userKey = req.query.userKey as string;
|
|
31
|
-
const authKey = req.query.authKey as string;
|
|
32
|
-
const effectiveUserKey = userKey || authKey;
|
|
33
|
-
if (!effectiveUserKey) {
|
|
34
|
-
res.status(400).send(
|
|
35
|
-
'Missing userKey parameter. Add ?userKey=your_user_key to URL',
|
|
36
|
-
);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
const state = this._sessionContext.createOAuthState(effectiveUserKey);
|
|
40
|
-
const url = await this._server.authProvider.getAuthorizeUrl(state);
|
|
41
|
-
const mcpParams = req.query as any;
|
|
42
|
-
if (mcpParams.client_id && mcpParams.redirect_uri) {
|
|
43
|
-
const urlObj = new URL(url);
|
|
44
|
-
const stateWithMcp = `${state}&client_id=${mcpParams.client_id}&redirect_uri=${encodeURIComponent(mcpParams.redirect_uri)}&code_challenge=${mcpParams.code_challenge}&code_challenge_method=${mcpParams.code_challenge_method}&mcp_state=${mcpParams.state || ''}`;
|
|
45
|
-
urlObj.searchParams.set('state', stateWithMcp);
|
|
46
|
-
return res.redirect(302, urlObj.toString());
|
|
47
|
-
}
|
|
48
|
-
res.redirect(302, url);
|
|
49
|
-
} catch (err: any) {
|
|
50
|
-
log.error('oauth.start.error', { error: String(err?.message ?? err) });
|
|
51
|
-
res.status(500).send('OAuth start failed');
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
public async handleOAuthCallback(req: Request, res: Response): Promise<void> {
|
|
56
|
-
try {
|
|
57
|
-
const code = String(req.query?.code ?? '') || String((req as any).body?.code ?? '');
|
|
58
|
-
const state = String(req.query?.state ?? '') || String((req as any).body?.state ?? '');
|
|
59
|
-
log.info('oauth.callback.start', {
|
|
60
|
-
code: code ? '***' + code.slice(-4) : 'missing',
|
|
61
|
-
state: state ? state.substring(0, 50) + '...' : 'missing',
|
|
62
|
-
fullState: state,
|
|
63
|
-
});
|
|
64
|
-
if (!code || !state) {
|
|
65
|
-
res.status(400).send('Missing code or state');
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
const stateParts = state.split('&');
|
|
69
|
-
const creatioState = stateParts[0];
|
|
70
|
-
log.info('oauth.callback.state_parse', {
|
|
71
|
-
originalState: state,
|
|
72
|
-
creatioState,
|
|
73
|
-
hasMcpParams: stateParts.length > 1,
|
|
74
|
-
});
|
|
75
|
-
if (!creatioState) {
|
|
76
|
-
log.error('oauth.callback.no_creatio_state', { originalState: state });
|
|
77
|
-
res.status(400).send('Invalid state format');
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
const userKey = this._sessionContext.validateAndConsumeOAuthState(creatioState);
|
|
81
|
-
if (!userKey) {
|
|
82
|
-
log.error('oauth.callback.creatio_state_invalid', { creatioState });
|
|
83
|
-
res.status(400).send('Unknown or expired state');
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
await runWithContext({ userKey }, async () =>
|
|
87
|
-
this._server.authProvider.finishAuthorization(code),
|
|
88
|
-
);
|
|
89
|
-
this._mapAllSessionsToUser(userKey);
|
|
90
|
-
const stateParams = new URLSearchParams(state);
|
|
91
|
-
const clientId = stateParams.get('client_id');
|
|
92
|
-
const redirectUri = stateParams.get('redirect_uri');
|
|
93
|
-
const codeChallenge = stateParams.get('code_challenge');
|
|
94
|
-
if (clientId && redirectUri && codeChallenge) {
|
|
95
|
-
const mcpState = stateParams.get('mcp_state');
|
|
96
|
-
log.info('oauth.callback.state_validation', {
|
|
97
|
-
mcpState,
|
|
98
|
-
clientId,
|
|
99
|
-
hasState: !!mcpState,
|
|
100
|
-
});
|
|
101
|
-
if (mcpState && !this._oauthServer.validateState(mcpState, clientId)) {
|
|
102
|
-
log.error('oauth.callback.state_invalid', { mcpState, clientId });
|
|
103
|
-
const errorUrl = new URL(redirectUri);
|
|
104
|
-
errorUrl.searchParams.set('error', 'invalid_request');
|
|
105
|
-
errorUrl.searchParams.set('error_description', 'Unknown or expired state');
|
|
106
|
-
if (mcpState) {
|
|
107
|
-
errorUrl.searchParams.set('state', mcpState);
|
|
108
|
-
}
|
|
109
|
-
return res.redirect(errorUrl.toString());
|
|
110
|
-
}
|
|
111
|
-
const authCode = this._oauthServer.generateAuthorizationCode(
|
|
112
|
-
clientId,
|
|
113
|
-
redirectUri,
|
|
114
|
-
codeChallenge,
|
|
115
|
-
stateParams.get('code_challenge_method') || 'S256',
|
|
116
|
-
userKey,
|
|
117
|
-
);
|
|
118
|
-
const redirectUrl = new URL(redirectUri);
|
|
119
|
-
redirectUrl.searchParams.set('code', authCode);
|
|
120
|
-
if (mcpState) {
|
|
121
|
-
redirectUrl.searchParams.set('state', mcpState);
|
|
122
|
-
}
|
|
123
|
-
return res.redirect(redirectUrl.toString());
|
|
124
|
-
}
|
|
125
|
-
res.status(200).send('Authorization successful. You can close this window.');
|
|
126
|
-
} catch (err: any) {
|
|
127
|
-
log.error('oauth.callback.error', { error: String(err?.message ?? err) });
|
|
128
|
-
res.status(500).send('OAuth callback failed');
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
public async handleOAuthRevoke(req: Request, res: Response): Promise<void> {
|
|
133
|
-
try {
|
|
134
|
-
const userKey = (req.query.userKey as string) || (req.body?.userKey as string);
|
|
135
|
-
if (!userKey) {
|
|
136
|
-
res.status(400).send('Missing userKey parameter');
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
await runWithContext({ userKey }, async () => this._server.authProvider.revoke());
|
|
140
|
-
res.status(200).send('Revoked');
|
|
141
|
-
} catch (err: any) {
|
|
142
|
-
log.error('oauth.revoke.error', { error: String(err?.message ?? err) });
|
|
143
|
-
res.status(500).send('OAuth revoke failed');
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import * as http from 'http';
|
|
2
|
-
import { Socket } from 'node:net';
|
|
3
|
-
|
|
4
|
-
import express from 'express';
|
|
5
|
-
|
|
6
|
-
import { AuthProviderType } from '../../creatio/';
|
|
7
|
-
import log from '../../log';
|
|
8
|
-
import { SessionContext } from '../../services';
|
|
9
|
-
import { OAuthServer } from '../oauth';
|
|
10
|
-
|
|
11
|
-
import { CreatioOAuthHandlers } from './creatio-oauth-handlers';
|
|
12
|
-
import { McpHandlers } from './mcp-handlers';
|
|
13
|
-
import { MCPOAuthHandlers } from './mcp-oauth-handlers';
|
|
14
|
-
import { HttpMiddleware } from './middleware';
|
|
15
|
-
|
|
16
|
-
import type { Server } from '../mcp';
|
|
17
|
-
|
|
18
|
-
export class HttpServer {
|
|
19
|
-
private readonly _server: Server;
|
|
20
|
-
private readonly _app = express();
|
|
21
|
-
private readonly _connections = new Set<Socket>();
|
|
22
|
-
private _srv!: http.Server;
|
|
23
|
-
private readonly _sessionContext = SessionContext.instance;
|
|
24
|
-
private readonly _oauthServer: OAuthServer;
|
|
25
|
-
private readonly _middleware: HttpMiddleware;
|
|
26
|
-
private readonly _mcpHandlers: McpHandlers;
|
|
27
|
-
private readonly _creatioOauthHandlers: CreatioOAuthHandlers;
|
|
28
|
-
private readonly _mcpOauthHandlers: MCPOAuthHandlers;
|
|
29
|
-
|
|
30
|
-
constructor(server: Server) {
|
|
31
|
-
this._server = server;
|
|
32
|
-
this._oauthServer = new OAuthServer();
|
|
33
|
-
this._middleware = new HttpMiddleware(this._oauthServer);
|
|
34
|
-
this._mcpHandlers = new McpHandlers(this._server);
|
|
35
|
-
this._creatioOauthHandlers = new CreatioOAuthHandlers(this._server, this._oauthServer);
|
|
36
|
-
this._mcpOauthHandlers = new MCPOAuthHandlers(this._oauthServer);
|
|
37
|
-
this._setupMiddleware();
|
|
38
|
-
this._setupRoutes();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
private _setupMiddleware(): void {
|
|
42
|
-
this._app.use(this._middleware.correlationId());
|
|
43
|
-
this._app.use(this._middleware.requestLogging());
|
|
44
|
-
this._app.use(express.json());
|
|
45
|
-
this._app.use(express.urlencoded({ extended: true }));
|
|
46
|
-
if (this._isNeedMCPOAuth()) {
|
|
47
|
-
this._app.use('/mcp', this._middleware.bearerAuth());
|
|
48
|
-
}
|
|
49
|
-
this._app.use(this._middleware.errorHandler());
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
private _setupRoutes(): void {
|
|
53
|
-
this._setupMCPEndpoints();
|
|
54
|
-
if (this._isNeedMCPOAuth()) {
|
|
55
|
-
this._setupCreatioOAuthEndpoints();
|
|
56
|
-
this._setupMCPOAuthEndpoints();
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
private _setupMCPEndpoints(): void {
|
|
61
|
-
this._app.post('/mcp', (req, res) => this._mcpHandlers.handleMcpPost(req, res));
|
|
62
|
-
this._app.get('/mcp', (req, res) => this._mcpHandlers.handleSessionRequest(req, res));
|
|
63
|
-
this._app.delete('/mcp', (req, res) => this._mcpHandlers.handleSessionRequest(req, res));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
private _isNeedMCPOAuth(): boolean {
|
|
67
|
-
return this._server.authProvider.type === AuthProviderType.OAuth2Code;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
private _setupCreatioOAuthEndpoints(): void {
|
|
71
|
-
this._app.get('/oauth/start', (req, res) =>
|
|
72
|
-
this._creatioOauthHandlers.handleOAuthStart(req, res),
|
|
73
|
-
);
|
|
74
|
-
this._app.get('/oauth/callback', (req, res) =>
|
|
75
|
-
this._creatioOauthHandlers.handleOAuthCallback(req, res),
|
|
76
|
-
);
|
|
77
|
-
this._app.post('/oauth/revoke', (req, res) =>
|
|
78
|
-
this._creatioOauthHandlers.handleOAuthRevoke(req, res),
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
private _setupMCPOAuthEndpoints(): void {
|
|
83
|
-
this._app.get('/.well-known/oauth-authorization-server', (req, res) =>
|
|
84
|
-
this._mcpOauthHandlers.handleMetadata(req, res),
|
|
85
|
-
);
|
|
86
|
-
this._app.post('/register', (req, res) =>
|
|
87
|
-
this._mcpOauthHandlers.handleClientRegistration(req, res),
|
|
88
|
-
);
|
|
89
|
-
this._app.get('/authorize', (req, res) =>
|
|
90
|
-
this._mcpOauthHandlers.handleAuthorization(req, res),
|
|
91
|
-
);
|
|
92
|
-
this._app.post('/token', (req, res) =>
|
|
93
|
-
this._mcpOauthHandlers.handleTokenExchange(req, res),
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
public start(port: number) {
|
|
98
|
-
return new Promise<void>((resolve, reject) => {
|
|
99
|
-
this._srv = this._app.listen(port, () => {
|
|
100
|
-
log.httpStart(port);
|
|
101
|
-
resolve();
|
|
102
|
-
});
|
|
103
|
-
this._srv.keepAliveTimeout = 5000;
|
|
104
|
-
this._srv.headersTimeout = Math.max(this._srv.keepAliveTimeout + 1000, 6000);
|
|
105
|
-
this._srv.on('error', (err) => {
|
|
106
|
-
log.error('http.start.error', { error: String(err), port });
|
|
107
|
-
reject(err);
|
|
108
|
-
});
|
|
109
|
-
this._srv.on('connection', (socket: Socket) => {
|
|
110
|
-
this._connections.add(socket);
|
|
111
|
-
socket.once('close', () => this._connections.delete(socket));
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
public async stop() {
|
|
117
|
-
try {
|
|
118
|
-
if (this._server.authProvider && 'cancelAllRefresh' in this._server.authProvider) {
|
|
119
|
-
(this._server.authProvider as any).cancelAllRefresh();
|
|
120
|
-
}
|
|
121
|
-
} catch (err) {
|
|
122
|
-
log.warn('token_refresh_cleanup_failed', { error: String(err) });
|
|
123
|
-
}
|
|
124
|
-
if (this._srv) {
|
|
125
|
-
try {
|
|
126
|
-
await this._server.stopMcp();
|
|
127
|
-
await new Promise<void>((resolve) => {
|
|
128
|
-
this._srv.close(() => resolve());
|
|
129
|
-
});
|
|
130
|
-
} catch (err) {
|
|
131
|
-
log.error('http.stop.error', { error: String(err) });
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
for (const socket of Array.from(this._connections)) {
|
|
135
|
-
try {
|
|
136
|
-
socket.destroy();
|
|
137
|
-
} catch {}
|
|
138
|
-
}
|
|
139
|
-
this._connections.clear();
|
|
140
|
-
const sessions = this._sessionContext.getAllSessions();
|
|
141
|
-
for (const session of sessions) {
|
|
142
|
-
try {
|
|
143
|
-
session.transport?.close();
|
|
144
|
-
} catch (err) {
|
|
145
|
-
log.warn('transport.close.failed', { sessionId: session.id, error: String(err) });
|
|
146
|
-
}
|
|
147
|
-
this._sessionContext.deleteSession(session.id);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
package/src/server/http/index.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
|
-
|
|
3
|
-
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
4
|
-
import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
-
|
|
6
|
-
import log from '../../log';
|
|
7
|
-
import { SessionContext } from '../../services';
|
|
8
|
-
import {
|
|
9
|
-
getClientIp,
|
|
10
|
-
getSessionIdFromRequest,
|
|
11
|
-
getUserKeyFromRequest,
|
|
12
|
-
runWithContext,
|
|
13
|
-
} from '../../utils';
|
|
14
|
-
|
|
15
|
-
import type { Server } from '../mcp';
|
|
16
|
-
import type { Request, Response } from 'express';
|
|
17
|
-
|
|
18
|
-
export class McpHandlers {
|
|
19
|
-
private readonly _sessionContext = SessionContext.instance;
|
|
20
|
-
private readonly _server: Server;
|
|
21
|
-
|
|
22
|
-
constructor(server: Server) {
|
|
23
|
-
this._server = server;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
public async handleMcpPost(req: Request, res: Response): Promise<void> {
|
|
27
|
-
const sessionId = getSessionIdFromRequest(req);
|
|
28
|
-
const bearerUserKey = (req as any).userKey;
|
|
29
|
-
let transport: StreamableHTTPServerTransport | undefined;
|
|
30
|
-
const remoteIp = getClientIp(req);
|
|
31
|
-
if (sessionId && this._sessionContext.hasSession(sessionId)) {
|
|
32
|
-
const session = this._sessionContext.getSession(sessionId);
|
|
33
|
-
transport = session?.transport;
|
|
34
|
-
if (session && !session.isLogged) {
|
|
35
|
-
this._sessionContext.markSessionAsLogged(sessionId);
|
|
36
|
-
log.sessionConnect(sessionId, String(remoteIp));
|
|
37
|
-
}
|
|
38
|
-
} else if (!sessionId && isInitializeRequest(req.body)) {
|
|
39
|
-
transport = new StreamableHTTPServerTransport({
|
|
40
|
-
sessionIdGenerator: () => randomUUID(),
|
|
41
|
-
onsessioninitialized: (sid) => {
|
|
42
|
-
if (transport) {
|
|
43
|
-
const session = this._sessionContext.createSession(
|
|
44
|
-
sid,
|
|
45
|
-
bearerUserKey,
|
|
46
|
-
remoteIp,
|
|
47
|
-
);
|
|
48
|
-
this._sessionContext.setSessionTransport(sid, transport);
|
|
49
|
-
this._sessionContext.markSessionAsLogged(sid);
|
|
50
|
-
log.sessionConnect(sid, String(remoteIp));
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
});
|
|
54
|
-
transport.onclose = () => {
|
|
55
|
-
if (transport?.sessionId) {
|
|
56
|
-
log.sessionDisconnect(transport.sessionId, String(remoteIp));
|
|
57
|
-
this._sessionContext.deleteSession(transport.sessionId);
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
const mcp = await this._server.startMcp();
|
|
61
|
-
await mcp.connect(transport as any);
|
|
62
|
-
} else {
|
|
63
|
-
res.status(400).json({
|
|
64
|
-
jsonrpc: '2.0',
|
|
65
|
-
error: { code: -32000, message: 'Bad Request: No valid session ID provided' },
|
|
66
|
-
id: null,
|
|
67
|
-
});
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
const session = this._sessionContext.getSession(sessionId);
|
|
71
|
-
const userKey = bearerUserKey || session?.userKey;
|
|
72
|
-
await runWithContext({ userKey, sessionId }, async () =>
|
|
73
|
-
transport!.handleRequest(req, res, req.body),
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
public async handleSessionRequest(req: Request, res: Response): Promise<void> {
|
|
78
|
-
const sessionId = req.headers['mcp-session-id'] as string | undefined;
|
|
79
|
-
if (!sessionId || !this._sessionContext.hasSession(sessionId)) {
|
|
80
|
-
res.status(400).send('Invalid or missing session ID');
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
const session = this._sessionContext.getSession(sessionId);
|
|
84
|
-
const transport = session?.transport;
|
|
85
|
-
if (!transport) {
|
|
86
|
-
res.status(400).send('Session has no transport');
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
const userKey = getUserKeyFromRequest(req as any);
|
|
90
|
-
await runWithContext({ userKey, sessionId }, async () => transport.handleRequest(req, res));
|
|
91
|
-
}
|
|
92
|
-
}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
|
-
|
|
3
|
-
import log from '../../log';
|
|
4
|
-
import { OAuthValidators } from '../oauth/validators';
|
|
5
|
-
|
|
6
|
-
import type { OAuthServer } from '../oauth';
|
|
7
|
-
import type { Request, Response } from 'express';
|
|
8
|
-
|
|
9
|
-
export class MCPOAuthHandlers {
|
|
10
|
-
private readonly _oauthServer: OAuthServer;
|
|
11
|
-
|
|
12
|
-
constructor(oauthServer: OAuthServer) {
|
|
13
|
-
this._oauthServer = oauthServer;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
public handleMetadata(req: Request, res: Response): void {
|
|
17
|
-
const metadata = this._oauthServer.getAuthorizationServerMetadata();
|
|
18
|
-
res.json(metadata);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
public handleClientRegistration(req: Request, res: Response): Response | void {
|
|
22
|
-
try {
|
|
23
|
-
const { redirect_uris } = req.body;
|
|
24
|
-
const validationError = OAuthValidators.validateClientRegistration(redirect_uris);
|
|
25
|
-
if (validationError) {
|
|
26
|
-
return res.status(400).json({
|
|
27
|
-
error: 'invalid_request',
|
|
28
|
-
error_description: validationError,
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
const client = this._oauthServer.registerClient(redirect_uris);
|
|
32
|
-
res.status(201).json(client);
|
|
33
|
-
} catch (error) {
|
|
34
|
-
log.error('oauth.register.error', { error: String(error) });
|
|
35
|
-
res.status(500).json({
|
|
36
|
-
error: 'server_error',
|
|
37
|
-
error_description: 'Failed to register client',
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
public async handleAuthorization(req: Request, res: Response): Promise<void> {
|
|
43
|
-
try {
|
|
44
|
-
const params = {
|
|
45
|
-
client_id: req.query.client_id as string,
|
|
46
|
-
redirect_uri: req.query.redirect_uri as string,
|
|
47
|
-
response_type: req.query.response_type as string,
|
|
48
|
-
state: req.query.state as string,
|
|
49
|
-
code_challenge: req.query.code_challenge as string,
|
|
50
|
-
code_challenge_method: req.query.code_challenge_method as string,
|
|
51
|
-
scope: req.query.scope as string,
|
|
52
|
-
};
|
|
53
|
-
const validationError = this._oauthServer.validateAuthorizationRequest(params);
|
|
54
|
-
if (validationError) {
|
|
55
|
-
const errorUrl = new URL(params.redirect_uri);
|
|
56
|
-
errorUrl.searchParams.set('error', validationError.error);
|
|
57
|
-
if (validationError.error_description) {
|
|
58
|
-
errorUrl.searchParams.set(
|
|
59
|
-
'error_description',
|
|
60
|
-
validationError.error_description,
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
if (params.state) {
|
|
64
|
-
errorUrl.searchParams.set('state', params.state);
|
|
65
|
-
}
|
|
66
|
-
return res.redirect(errorUrl.toString());
|
|
67
|
-
}
|
|
68
|
-
if (params.state) {
|
|
69
|
-
this._oauthServer.storeState(params.state, params.client_id);
|
|
70
|
-
}
|
|
71
|
-
const authKey = randomUUID();
|
|
72
|
-
const creatioAuthUrl = `/oauth/start?authKey=${authKey}&client_id=${params.client_id}&redirect_uri=${encodeURIComponent(params.redirect_uri)}&code_challenge=${params.code_challenge}&code_challenge_method=${params.code_challenge_method}&state=${params.state || ''}`;
|
|
73
|
-
res.redirect(creatioAuthUrl);
|
|
74
|
-
} catch (error) {
|
|
75
|
-
log.error('oauth.authorize.error', { error: String(error) });
|
|
76
|
-
res.status(500).send('Authorization failed');
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
public async handleTokenExchange(req: Request, res: Response): Promise<Response | void> {
|
|
81
|
-
try {
|
|
82
|
-
const tokenParams = req.body || {};
|
|
83
|
-
log.info('oauth.token.request', {
|
|
84
|
-
contentType: req.headers['content-type'],
|
|
85
|
-
hasBody: !!req.body,
|
|
86
|
-
bodyKeys: req.body ? Object.keys(req.body) : [],
|
|
87
|
-
params: {
|
|
88
|
-
grant_type: tokenParams.grant_type,
|
|
89
|
-
code: tokenParams.code ? '***' + tokenParams.code.slice(-4) : 'missing',
|
|
90
|
-
client_id: tokenParams.client_id,
|
|
91
|
-
redirect_uri: tokenParams.redirect_uri,
|
|
92
|
-
has_code_verifier: !!tokenParams.code_verifier,
|
|
93
|
-
},
|
|
94
|
-
});
|
|
95
|
-
const result = await this._oauthServer.exchangeCodeForToken(tokenParams);
|
|
96
|
-
if ('error' in result) {
|
|
97
|
-
return res.status(400).json(result);
|
|
98
|
-
}
|
|
99
|
-
res.json(result);
|
|
100
|
-
} catch (error) {
|
|
101
|
-
log.error('oauth.token.error', { error: String(error) });
|
|
102
|
-
res.status(500).json({
|
|
103
|
-
error: 'server_error',
|
|
104
|
-
error_description: 'Failed to exchange token',
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|