arc-1 0.7.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +27 -4
  2. package/dist/adt/btp.d.ts +14 -3
  3. package/dist/adt/btp.d.ts.map +1 -1
  4. package/dist/adt/btp.js +18 -3
  5. package/dist/adt/btp.js.map +1 -1
  6. package/dist/adt/diagnostics.d.ts +5 -1
  7. package/dist/adt/diagnostics.d.ts.map +1 -1
  8. package/dist/adt/diagnostics.js +20 -3
  9. package/dist/adt/diagnostics.js.map +1 -1
  10. package/dist/adt/errors.d.ts +1 -1
  11. package/dist/adt/errors.d.ts.map +1 -1
  12. package/dist/adt/errors.js +46 -2
  13. package/dist/adt/errors.js.map +1 -1
  14. package/dist/handlers/intent.js +2 -2
  15. package/dist/handlers/intent.js.map +1 -1
  16. package/dist/server/audit.d.ts +41 -1
  17. package/dist/server/audit.d.ts.map +1 -1
  18. package/dist/server/audit.js.map +1 -1
  19. package/dist/server/config.d.ts.map +1 -1
  20. package/dist/server/config.js +32 -0
  21. package/dist/server/config.js.map +1 -1
  22. package/dist/server/http.d.ts +25 -0
  23. package/dist/server/http.d.ts.map +1 -1
  24. package/dist/server/http.js +149 -7
  25. package/dist/server/http.js.map +1 -1
  26. package/dist/server/server.d.ts +1 -1
  27. package/dist/server/server.js +1 -1
  28. package/dist/server/stateless-client-store.d.ts +97 -0
  29. package/dist/server/stateless-client-store.d.ts.map +1 -0
  30. package/dist/server/stateless-client-store.js +334 -0
  31. package/dist/server/stateless-client-store.js.map +1 -0
  32. package/dist/server/types.d.ts +12 -0
  33. package/dist/server/types.d.ts.map +1 -1
  34. package/dist/server/types.js +2 -0
  35. package/dist/server/types.js.map +1 -1
  36. package/dist/server/xsuaa.d.ts +11 -43
  37. package/dist/server/xsuaa.d.ts.map +1 -1
  38. package/dist/server/xsuaa.js +12 -177
  39. package/dist/server/xsuaa.js.map +1 -1
  40. package/package.json +8 -2
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Stateless OAuth Dynamic Client Registration store.
3
+ *
4
+ * MCP clients (Claude Desktop, Cursor, Copilot CLI…) register dynamically
5
+ * via RFC 7591 and cache the returned `client_id` locally. With an
6
+ * in-memory or local-disk store, every CF push / restart wipes the
7
+ * server-side registry — the cached `client_id` then fails with
8
+ * `invalid_client` and the user has to clear their MCP client's OAuth
9
+ * cache to recover.
10
+ *
11
+ * This store eliminates the storage problem entirely. Each `client_id`
12
+ * is a self-validating token: it carries the registration payload
13
+ * (redirect_uris, grant_types, …) plus an HMAC-SHA256 signature derived
14
+ * from a server-held key. `getClient` re-derives the payload by
15
+ * verifying the signature; no persistence is needed. Any process with
16
+ * the same signing key can validate any client_id ever issued.
17
+ *
18
+ * Tradeoffs vs the persisted in-memory store:
19
+ * + Survives `cf push`, `cf restart`, cell moves, multi-instance scale-out
20
+ * + No external dependency, no service binding, no native module
21
+ * - Per-client revocation is impossible (only TTL or full key rotation)
22
+ * - Rotating the signing key invalidates every outstanding registration
23
+ *
24
+ * The signing key is derived (via HKDF-style HMAC) from the XSUAA
25
+ * `clientsecret`, so it's already as stable as the service binding —
26
+ * service rebinding rotates both at once, which is the right boundary.
27
+ */
28
+ import type { OAuthRegisteredClientsStore } from '@modelcontextprotocol/sdk/server/auth/clients.js';
29
+ import type { OAuthClientInformationFull } from '@modelcontextprotocol/sdk/shared/auth.js';
30
+ export interface StatelessDcrClientStoreOptions {
31
+ /**
32
+ * How long an issued client_id remains valid, in seconds. After this
33
+ * window `getClient()` returns undefined and clients re-register via
34
+ * `/register`. Default: 30 days. Lower values bound the blast radius if
35
+ * the signing key leaks; higher values reduce re-auth churn.
36
+ */
37
+ ttlSeconds?: number;
38
+ /** Clock injection point for tests. Default: `Date.now`. */
39
+ now?: () => number;
40
+ }
41
+ export declare class StatelessDcrClientStore implements OAuthRegisteredClientsStore {
42
+ private readonly xsuaaClient;
43
+ private readonly hmacKey;
44
+ private readonly ttlSeconds;
45
+ private readonly now;
46
+ constructor(xsuaaClientId: string, xsuaaClientSecret: string, signingSecret: string, options?: StatelessDcrClientStoreOptions);
47
+ getClient(clientId: string): Promise<OAuthClientInformationFull | undefined>;
48
+ registerClient(client: Omit<OAuthClientInformationFull, 'client_id' | 'client_id_issued_at'>): Promise<OAuthClientInformationFull>;
49
+ /**
50
+ * Called by the MCP SDK before redirect_uri validation on `/authorize`.
51
+ *
52
+ * For the pre-registered XSUAA client we mutate the in-memory list (XSUAA
53
+ * itself is the authoritative validator via `xs-security.json` wildcards,
54
+ * so the SDK's local list is decorative). The mutation is replayed on
55
+ * every `/authorize`, so it doesn't need to persist.
56
+ *
57
+ * For DCR (`arc1-…`) clients we are stateless by design: there's nothing
58
+ * to mutate. The previous in-memory store implemented a percent-encoding
59
+ * loose-match (BAS/Theia registers `?x=1` then authorizes with `%3Fx=1`).
60
+ * Reproducing that statelessly would require either bundling every
61
+ * encoding variant in the signed payload or keeping a per-process scratch
62
+ * map, both of which undermine the "no state" goal. We accept the
63
+ * regression: affected clients re-register on encoding-variant mismatch,
64
+ * which is exactly what they did under the old store after every restart.
65
+ */
66
+ ensureRedirectUri(clientId: string, uri: string): void;
67
+ private payloadToClientInfo;
68
+ private encode;
69
+ /**
70
+ * Decode and verify a `client_id`. Returns either the parsed payload or a
71
+ * structured failure reason — the caller emits the failure as an audit
72
+ * event with the right reason code (so probing attempts are observable).
73
+ */
74
+ private decodeAndVerify;
75
+ private verifySignature;
76
+ private sign;
77
+ /**
78
+ * The client_secret is derived deterministically from the client_id, so
79
+ * any instance with the same signing key can validate it. This is the
80
+ * core reason DCR survives container restarts and scales out horizontally
81
+ * with no shared state.
82
+ */
83
+ private deriveSecret;
84
+ private emitLookupFailed;
85
+ }
86
+ /**
87
+ * Validate a redirect URI against the allowed scheme/host policy.
88
+ *
89
+ * Allowed: `https://*`, `http://` to localhost / 127.0.0.1 / [::1], and known
90
+ * MCP-client custom schemes (`claude:`, `cursor:`, `vscode:`,
91
+ * `vscode-insiders:`).
92
+ *
93
+ * Rejected: `javascript:`, `data:`, `file:`, `ftp:`, and any `http://` to
94
+ * non-loopback hosts.
95
+ */
96
+ export declare function validateRedirectUri(uri: string): void;
97
+ //# sourceMappingURL=stateless-client-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateless-client-store.d.ts","sourceRoot":"","sources":["../../src/server/stateless-client-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,kDAAkD,CAAC;AACpG,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0CAA0C,CAAC;AAyE3F,MAAM,WAAW,8BAA8B;IAC7C;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,4DAA4D;IAC5D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAuBD,qBAAa,uBAAwB,YAAW,2BAA2B;IACzE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6B;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;gBAGjC,aAAa,EAAE,MAAM,EACrB,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,8BAAmC;IAgBxC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC;IA0B5E,cAAc,CAClB,MAAM,EAAE,IAAI,CAAC,0BAA0B,EAAE,WAAW,GAAG,qBAAqB,CAAC,GAC5E,OAAO,CAAC,0BAA0B,CAAC;IA8CtC;;;;;;;;;;;;;;;;OAgBG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAiBtD,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,MAAM;IAMd;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAsBvB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,IAAI;IAMZ;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,gBAAgB;CAczB;AAoBD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CA6BrD"}
@@ -0,0 +1,334 @@
1
+ /**
2
+ * Stateless OAuth Dynamic Client Registration store.
3
+ *
4
+ * MCP clients (Claude Desktop, Cursor, Copilot CLI…) register dynamically
5
+ * via RFC 7591 and cache the returned `client_id` locally. With an
6
+ * in-memory or local-disk store, every CF push / restart wipes the
7
+ * server-side registry — the cached `client_id` then fails with
8
+ * `invalid_client` and the user has to clear their MCP client's OAuth
9
+ * cache to recover.
10
+ *
11
+ * This store eliminates the storage problem entirely. Each `client_id`
12
+ * is a self-validating token: it carries the registration payload
13
+ * (redirect_uris, grant_types, …) plus an HMAC-SHA256 signature derived
14
+ * from a server-held key. `getClient` re-derives the payload by
15
+ * verifying the signature; no persistence is needed. Any process with
16
+ * the same signing key can validate any client_id ever issued.
17
+ *
18
+ * Tradeoffs vs the persisted in-memory store:
19
+ * + Survives `cf push`, `cf restart`, cell moves, multi-instance scale-out
20
+ * + No external dependency, no service binding, no native module
21
+ * - Per-client revocation is impossible (only TTL or full key rotation)
22
+ * - Rotating the signing key invalidates every outstanding registration
23
+ *
24
+ * The signing key is derived (via HKDF-style HMAC) from the XSUAA
25
+ * `clientsecret`, so it's already as stable as the service binding —
26
+ * service rebinding rotates both at once, which is the right boundary.
27
+ */
28
+ import crypto from 'node:crypto';
29
+ import { logger } from './logger.js';
30
+ // ─── Constants ────────────────────────────────────────────────────────
31
+ /** All DCR-issued client_ids start with this prefix. */
32
+ const ID_PREFIX = 'arc1-';
33
+ /**
34
+ * Domain-separation label bound into the HMAC key derivation. Bumping the
35
+ * suffix ("v1" → "v2") invalidates every previously-issued client_id without
36
+ * requiring a service-binding rotation, which is a useful escape hatch.
37
+ */
38
+ const KDF_LABEL = 'arc1-dcr/v1';
39
+ /** Schema version of the JSON payload embedded in the signed client_id. */
40
+ const PAYLOAD_VERSION = 1;
41
+ /**
42
+ * Truncated HMAC-SHA256 length in bytes. 16 bytes = 128 bits, which is well
43
+ * above the practical forgery threshold for opaque IDs (NIST SP 800-107
44
+ * acceptable for non-replayable identifiers).
45
+ */
46
+ const SIG_BYTES = 16;
47
+ /**
48
+ * Default lifetime of a DCR registration. Tunable via `ttlSeconds` so deployments
49
+ * with stricter compromise-window requirements can shorten it. 30 days matches
50
+ * typical OAuth refresh-token lifetimes — long enough that users don't see
51
+ * spurious "re-authenticate" prompts during normal use.
52
+ */
53
+ const DEFAULT_TTL_SECONDS = 30 * 24 * 60 * 60;
54
+ // Defaults applied when a registration omits these fields.
55
+ const DEFAULT_GRANT_TYPES = ['authorization_code', 'refresh_token'];
56
+ const DEFAULT_RESPONSE_TYPES = ['code'];
57
+ const DEFAULT_TOKEN_AUTH_METHOD = 'client_secret_post';
58
+ /**
59
+ * Built-in redirect_uris for the pre-registered XSUAA client. These cover the
60
+ * common MCP clients out of the box; additional URIs can be added at
61
+ * `/authorize` time via `ensureRedirectUri()`. The list MUST also be registered
62
+ * in `xs-security.json` — XSUAA is the authoritative validator for this client.
63
+ */
64
+ const XSUAA_DEFAULT_REDIRECT_URIS = [
65
+ 'http://localhost:6274/oauth/callback', // MCP Inspector
66
+ 'http://localhost:3000/oauth/callback', // Local dev
67
+ 'https://claude.ai/api/mcp/auth_callback', // Claude Desktop
68
+ 'cursor://anysphere.cursor-retrieval/oauth/callback', // Cursor
69
+ 'vscode://vscode.microsoft-authentication/callback', // VS Code
70
+ ];
71
+ // ─── Default XSUAA client ─────────────────────────────────────────────
72
+ /**
73
+ * Pre-registered XSUAA client config. MCP clients that hit the XSUAA
74
+ * `clientid` directly (Manual mode in Copilot Studio, etc.) resolve through
75
+ * this entry instead of going through DCR.
76
+ */
77
+ function buildXsuaaDefaultClient(clientId, clientSecret) {
78
+ return {
79
+ client_id: clientId,
80
+ client_secret: clientSecret,
81
+ redirect_uris: [...XSUAA_DEFAULT_REDIRECT_URIS],
82
+ grant_types: [...DEFAULT_GRANT_TYPES],
83
+ response_types: [...DEFAULT_RESPONSE_TYPES],
84
+ token_endpoint_auth_method: DEFAULT_TOKEN_AUTH_METHOD,
85
+ client_name: 'ARC-1 XSUAA Default Client',
86
+ };
87
+ }
88
+ // ─── Store ────────────────────────────────────────────────────────────
89
+ export class StatelessDcrClientStore {
90
+ xsuaaClient;
91
+ hmacKey;
92
+ ttlSeconds;
93
+ now;
94
+ constructor(xsuaaClientId, xsuaaClientSecret, signingSecret, options = {}) {
95
+ if (!signingSecret) {
96
+ throw new Error('StatelessDcrClientStore requires a non-empty signingSecret');
97
+ }
98
+ // Derive a dedicated HMAC key so the raw service-binding secret is never
99
+ // used directly to sign client_ids. The KDF_LABEL doubles as a domain
100
+ // separator (see comment on the constant).
101
+ this.hmacKey = crypto.createHmac('sha256', signingSecret).update(KDF_LABEL).digest();
102
+ this.xsuaaClient = buildXsuaaDefaultClient(xsuaaClientId, xsuaaClientSecret);
103
+ this.ttlSeconds = options.ttlSeconds ?? DEFAULT_TTL_SECONDS;
104
+ this.now = options.now ?? (() => Date.now());
105
+ }
106
+ // ── OAuthRegisteredClientsStore implementation ──
107
+ async getClient(clientId) {
108
+ if (clientId === this.xsuaaClient.client_id) {
109
+ return this.xsuaaClient;
110
+ }
111
+ if (!clientId.startsWith(ID_PREFIX)) {
112
+ this.emitLookupFailed(clientId, 'unknown_prefix');
113
+ return undefined;
114
+ }
115
+ const decoded = this.decodeAndVerify(clientId);
116
+ if (decoded.kind === 'error') {
117
+ this.emitLookupFailed(clientId, decoded.reason);
118
+ return undefined;
119
+ }
120
+ const ageSec = Math.floor(this.now() / 1000) - decoded.payload.iat;
121
+ if (ageSec > this.ttlSeconds) {
122
+ this.emitLookupFailed(clientId, 'expired');
123
+ logger.debug('OAuth client expired (TTL)', { clientId, ageSec, ttlSeconds: this.ttlSeconds });
124
+ return undefined;
125
+ }
126
+ return this.payloadToClientInfo(clientId, decoded.payload);
127
+ }
128
+ async registerClient(client) {
129
+ if (client.redirect_uris) {
130
+ for (const uri of client.redirect_uris) {
131
+ validateRedirectUri(uri);
132
+ }
133
+ }
134
+ const issuedAt = Math.floor(this.now() / 1000);
135
+ const payload = {
136
+ v: PAYLOAD_VERSION,
137
+ iat: issuedAt,
138
+ ru: client.redirect_uris ?? [],
139
+ };
140
+ if (client.grant_types)
141
+ payload.gt = client.grant_types;
142
+ if (client.response_types)
143
+ payload.rt = client.response_types;
144
+ if (client.token_endpoint_auth_method)
145
+ payload.am = client.token_endpoint_auth_method;
146
+ if (client.client_name)
147
+ payload.cn = client.client_name;
148
+ const clientId = this.encode(payload);
149
+ const clientSecret = this.deriveSecret(clientId);
150
+ logger.debug('OAuth client registered (stateless)', {
151
+ clientId,
152
+ clientName: client.client_name,
153
+ idBytes: clientId.length,
154
+ });
155
+ logger.emitAudit({
156
+ timestamp: new Date().toISOString(),
157
+ level: 'info',
158
+ event: 'oauth_client_registered',
159
+ registeredClientId: clientId,
160
+ clientName: client.client_name,
161
+ redirectUriCount: payload.ru.length,
162
+ idBytes: clientId.length,
163
+ });
164
+ return {
165
+ ...client,
166
+ client_id: clientId,
167
+ client_secret: clientSecret,
168
+ client_id_issued_at: issuedAt,
169
+ };
170
+ }
171
+ // ── SDK redirect_uri hook ──
172
+ /**
173
+ * Called by the MCP SDK before redirect_uri validation on `/authorize`.
174
+ *
175
+ * For the pre-registered XSUAA client we mutate the in-memory list (XSUAA
176
+ * itself is the authoritative validator via `xs-security.json` wildcards,
177
+ * so the SDK's local list is decorative). The mutation is replayed on
178
+ * every `/authorize`, so it doesn't need to persist.
179
+ *
180
+ * For DCR (`arc1-…`) clients we are stateless by design: there's nothing
181
+ * to mutate. The previous in-memory store implemented a percent-encoding
182
+ * loose-match (BAS/Theia registers `?x=1` then authorizes with `%3Fx=1`).
183
+ * Reproducing that statelessly would require either bundling every
184
+ * encoding variant in the signed payload or keeping a per-process scratch
185
+ * map, both of which undermine the "no state" goal. We accept the
186
+ * regression: affected clients re-register on encoding-variant mismatch,
187
+ * which is exactly what they did under the old store after every restart.
188
+ */
189
+ ensureRedirectUri(clientId, uri) {
190
+ if (clientId !== this.xsuaaClient.client_id)
191
+ return;
192
+ if (this.xsuaaClient.redirect_uris.includes(uri))
193
+ return;
194
+ this.xsuaaClient.redirect_uris.push(uri);
195
+ logger.debug('Dynamic redirect_uri registered for XSUAA client', { clientId, uri });
196
+ logger.emitAudit({
197
+ timestamp: new Date().toISOString(),
198
+ level: 'info',
199
+ event: 'oauth_redirect_uri_registered',
200
+ registeredClientId: clientId,
201
+ redirectUri: uri,
202
+ });
203
+ }
204
+ // ── Internals: encode / decode / sign / verify ──
205
+ payloadToClientInfo(clientId, payload) {
206
+ return {
207
+ client_id: clientId,
208
+ client_secret: this.deriveSecret(clientId),
209
+ client_id_issued_at: payload.iat,
210
+ redirect_uris: payload.ru,
211
+ grant_types: payload.gt ?? [...DEFAULT_GRANT_TYPES],
212
+ response_types: payload.rt ?? [...DEFAULT_RESPONSE_TYPES],
213
+ token_endpoint_auth_method: payload.am ?? DEFAULT_TOKEN_AUTH_METHOD,
214
+ client_name: payload.cn,
215
+ };
216
+ }
217
+ encode(payload) {
218
+ const payloadB64 = Buffer.from(JSON.stringify(payload), 'utf8').toString('base64url');
219
+ const sig = this.sign(payloadB64);
220
+ return `${ID_PREFIX}${payloadB64}.${sig}`;
221
+ }
222
+ /**
223
+ * Decode and verify a `client_id`. Returns either the parsed payload or a
224
+ * structured failure reason — the caller emits the failure as an audit
225
+ * event with the right reason code (so probing attempts are observable).
226
+ */
227
+ decodeAndVerify(clientId) {
228
+ const stripped = clientId.slice(ID_PREFIX.length);
229
+ const dot = stripped.lastIndexOf('.');
230
+ if (dot < 0)
231
+ return { kind: 'error', reason: 'malformed' };
232
+ const payloadB64 = stripped.slice(0, dot);
233
+ const sigB64 = stripped.slice(dot + 1);
234
+ if (!this.verifySignature(payloadB64, sigB64)) {
235
+ return { kind: 'error', reason: 'bad_signature' };
236
+ }
237
+ const payload = parsePayload(payloadB64);
238
+ if (!payload)
239
+ return { kind: 'error', reason: 'invalid_payload' };
240
+ return { kind: 'ok', payload };
241
+ }
242
+ verifySignature(payloadB64, sigB64) {
243
+ const expected = Buffer.from(this.sign(payloadB64), 'base64url');
244
+ const actual = Buffer.from(sigB64, 'base64url');
245
+ if (actual.length !== expected.length || actual.length !== SIG_BYTES)
246
+ return false;
247
+ return crypto.timingSafeEqual(actual, expected);
248
+ }
249
+ sign(payloadB64) {
250
+ const fullDigest = crypto.createHmac('sha256', this.hmacKey).update(payloadB64).digest();
251
+ // Truncate to SIG_BYTES — see the comment on the constant for rationale.
252
+ return fullDigest.subarray(0, SIG_BYTES).toString('base64url');
253
+ }
254
+ /**
255
+ * The client_secret is derived deterministically from the client_id, so
256
+ * any instance with the same signing key can validate it. This is the
257
+ * core reason DCR survives container restarts and scales out horizontally
258
+ * with no shared state.
259
+ */
260
+ deriveSecret(clientId) {
261
+ return crypto.createHmac('sha256', this.hmacKey).update(`secret:${clientId}`).digest('base64url');
262
+ }
263
+ emitLookupFailed(clientId, reason) {
264
+ logger.debug('OAuth client lookup failed', { clientId, reason });
265
+ logger.emitAudit({
266
+ timestamp: new Date().toISOString(),
267
+ // 'expired' is normal-ish (TTL eviction); the rest are probing/forgery signals.
268
+ level: reason === 'expired' ? 'info' : 'warn',
269
+ event: 'oauth_client_lookup_failed',
270
+ registeredClientId: clientId,
271
+ reason,
272
+ });
273
+ }
274
+ }
275
+ // ─── Module-level helpers ─────────────────────────────────────────────
276
+ /**
277
+ * Parse a base64url-encoded payload back into a typed `SignedPayload`. Returns
278
+ * `undefined` on any failure (decode error, JSON parse error, schema mismatch).
279
+ */
280
+ function parsePayload(payloadB64) {
281
+ try {
282
+ const json = Buffer.from(payloadB64, 'base64url').toString('utf8');
283
+ const parsed = JSON.parse(json);
284
+ if (parsed.v !== PAYLOAD_VERSION)
285
+ return undefined;
286
+ if (typeof parsed.iat !== 'number' || !Array.isArray(parsed.ru))
287
+ return undefined;
288
+ return parsed;
289
+ }
290
+ catch {
291
+ return undefined;
292
+ }
293
+ }
294
+ /**
295
+ * Validate a redirect URI against the allowed scheme/host policy.
296
+ *
297
+ * Allowed: `https://*`, `http://` to localhost / 127.0.0.1 / [::1], and known
298
+ * MCP-client custom schemes (`claude:`, `cursor:`, `vscode:`,
299
+ * `vscode-insiders:`).
300
+ *
301
+ * Rejected: `javascript:`, `data:`, `file:`, `ftp:`, and any `http://` to
302
+ * non-loopback hosts.
303
+ */
304
+ export function validateRedirectUri(uri) {
305
+ const ALLOWED_CUSTOM_SCHEMES = ['claude:', 'cursor:', 'vscode:', 'vscode-insiders:'];
306
+ const BLOCKED_SCHEMES = ['javascript:', 'data:', 'file:', 'ftp:'];
307
+ for (const scheme of BLOCKED_SCHEMES) {
308
+ if (uri.toLowerCase().startsWith(scheme)) {
309
+ throw new Error(`Redirect URI rejected: '${scheme}' scheme is not allowed. Use https:// or a registered custom scheme.`);
310
+ }
311
+ }
312
+ for (const scheme of ALLOWED_CUSTOM_SCHEMES) {
313
+ if (uri.toLowerCase().startsWith(scheme))
314
+ return;
315
+ }
316
+ try {
317
+ const parsed = new URL(uri);
318
+ if (parsed.protocol === 'https:')
319
+ return;
320
+ if (parsed.protocol === 'http:') {
321
+ const host = parsed.hostname.toLowerCase();
322
+ if (host === 'localhost' || host === '127.0.0.1' || host === '[::1]' || host === '::1')
323
+ return;
324
+ throw new Error(`Redirect URI rejected: http:// is only allowed for localhost/127.0.0.1. Got: '${uri}'`);
325
+ }
326
+ return;
327
+ }
328
+ catch (err) {
329
+ if (err instanceof Error && err.message.startsWith('Redirect URI rejected'))
330
+ throw err;
331
+ // URL parsing failed for some other reason (unknown protocol etc.) — allow.
332
+ }
333
+ }
334
+ //# sourceMappingURL=stateless-client-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateless-client-store.js","sourceRoot":"","sources":["../../src/server/stateless-client-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,MAAM,MAAM,aAAa,CAAC;AAGjC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,yEAAyE;AAEzE,wDAAwD;AACxD,MAAM,SAAS,GAAG,OAAO,CAAC;AAE1B;;;;GAIG;AACH,MAAM,SAAS,GAAG,aAAa,CAAC;AAEhC,2EAA2E;AAC3E,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B;;;;GAIG;AACH,MAAM,SAAS,GAAG,EAAE,CAAC;AAErB;;;;;GAKG;AACH,MAAM,mBAAmB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAE9C,2DAA2D;AAC3D,MAAM,mBAAmB,GAAG,CAAC,oBAAoB,EAAE,eAAe,CAAU,CAAC;AAC7E,MAAM,sBAAsB,GAAG,CAAC,MAAM,CAAU,CAAC;AACjD,MAAM,yBAAyB,GAAG,oBAAoB,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,2BAA2B,GAAG;IAClC,sCAAsC,EAAE,gBAAgB;IACxD,sCAAsC,EAAE,YAAY;IACpD,yCAAyC,EAAE,iBAAiB;IAC5D,oDAAoD,EAAE,SAAS;IAC/D,mDAAmD,EAAE,UAAU;CACvD,CAAC;AAoCX,yEAAyE;AAEzE;;;;GAIG;AACH,SAAS,uBAAuB,CAAC,QAAgB,EAAE,YAAoB;IACrE,OAAO;QACL,SAAS,EAAE,QAAQ;QACnB,aAAa,EAAE,YAAY;QAC3B,aAAa,EAAE,CAAC,GAAG,2BAA2B,CAAC;QAC/C,WAAW,EAAE,CAAC,GAAG,mBAAmB,CAAC;QACrC,cAAc,EAAE,CAAC,GAAG,sBAAsB,CAAC;QAC3C,0BAA0B,EAAE,yBAAyB;QACrD,WAAW,EAAE,4BAA4B;KAC1C,CAAC;AACJ,CAAC;AAED,yEAAyE;AAEzE,MAAM,OAAO,uBAAuB;IACjB,WAAW,CAA6B;IACxC,OAAO,CAAS;IAChB,UAAU,CAAS;IACnB,GAAG,CAAe;IAEnC,YACE,aAAqB,EACrB,iBAAyB,EACzB,aAAqB,EACrB,UAA0C,EAAE;QAE5C,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAChF,CAAC;QACD,yEAAyE;QACzE,sEAAsE;QACtE,2CAA2C;QAC3C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,CAAC;QACrF,IAAI,CAAC,WAAW,GAAG,uBAAuB,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;QAC7E,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC;QAC5D,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,mDAAmD;IAEnD,KAAK,CAAC,SAAS,CAAC,QAAgB;QAC9B,IAAI,QAAQ,KAAK,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC,WAAW,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;YAClD,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YAChD,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC;QACnE,IAAI,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YAC7B,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YAC3C,MAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YAC9F,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,OAAO,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,MAA6E;QAE7E,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;YACzB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;gBACvC,mBAAmB,CAAC,GAAG,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAkB;YAC7B,CAAC,EAAE,eAAe;YAClB,GAAG,EAAE,QAAQ;YACb,EAAE,EAAE,MAAM,CAAC,aAAa,IAAI,EAAE;SAC/B,CAAC;QACF,IAAI,MAAM,CAAC,WAAW;YAAE,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC;QACxD,IAAI,MAAM,CAAC,cAAc;YAAE,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC,cAAc,CAAC;QAC9D,IAAI,MAAM,CAAC,0BAA0B;YAAE,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC,0BAA0B,CAAC;QACtF,IAAI,MAAM,CAAC,WAAW;YAAE,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC;QAExD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAEjD,MAAM,CAAC,KAAK,CAAC,qCAAqC,EAAE;YAClD,QAAQ;YACR,UAAU,EAAE,MAAM,CAAC,WAAW;YAC9B,OAAO,EAAE,QAAQ,CAAC,MAAM;SACzB,CAAC,CAAC;QACH,MAAM,CAAC,SAAS,CAAC;YACf,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,KAAK,EAAE,MAAM;YACb,KAAK,EAAE,yBAAyB;YAChC,kBAAkB,EAAE,QAAQ;YAC5B,UAAU,EAAE,MAAM,CAAC,WAAW;YAC9B,gBAAgB,EAAE,OAAO,CAAC,EAAE,CAAC,MAAM;YACnC,OAAO,EAAE,QAAQ,CAAC,MAAM;SACzB,CAAC,CAAC;QAEH,OAAO;YACL,GAAG,MAAM;YACT,SAAS,EAAE,QAAQ;YACnB,aAAa,EAAE,YAAY;YAC3B,mBAAmB,EAAE,QAAQ;SAC9B,CAAC;IACJ,CAAC;IAED,8BAA8B;IAE9B;;;;;;;;;;;;;;;;OAgBG;IACH,iBAAiB,CAAC,QAAgB,EAAE,GAAW;QAC7C,IAAI,QAAQ,KAAK,IAAI,CAAC,WAAW,CAAC,SAAS;YAAE,OAAO;QACpD,IAAI,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO;QAEzD,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,kDAAkD,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;QACpF,MAAM,CAAC,SAAS,CAAC;YACf,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,KAAK,EAAE,MAAM;YACb,KAAK,EAAE,+BAA+B;YACtC,kBAAkB,EAAE,QAAQ;YAC5B,WAAW,EAAE,GAAG;SACjB,CAAC,CAAC;IACL,CAAC;IAED,mDAAmD;IAE3C,mBAAmB,CAAC,QAAgB,EAAE,OAAsB;QAClE,OAAO;YACL,SAAS,EAAE,QAAQ;YACnB,aAAa,EAAE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;YAC1C,mBAAmB,EAAE,OAAO,CAAC,GAAG;YAChC,aAAa,EAAE,OAAO,CAAC,EAAE;YACzB,WAAW,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,GAAG,mBAAmB,CAAC;YACnD,cAAc,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,GAAG,sBAAsB,CAAC;YACzD,0BAA0B,EAAE,OAAO,CAAC,EAAE,IAAI,yBAAyB;YACnE,WAAW,EAAE,OAAO,CAAC,EAAE;SACxB,CAAC;IACJ,CAAC;IAEO,MAAM,CAAC,OAAsB;QACnC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QACtF,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClC,OAAO,GAAG,SAAS,GAAG,UAAU,IAAI,GAAG,EAAE,CAAC;IAC5C,CAAC;IAED;;;;OAIG;IACK,eAAe,CACrB,QAAgB;QAIhB,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACtC,IAAI,GAAG,GAAG,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QAE3D,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAEvC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,CAAC;YAC9C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;QACpD,CAAC;QAED,MAAM,OAAO,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;QAElE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACjC,CAAC;IAEO,eAAe,CAAC,UAAkB,EAAE,MAAc;QACxD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,WAAW,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAChD,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QACnF,OAAO,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClD,CAAC;IAEO,IAAI,CAAC,UAAkB;QAC7B,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE,CAAC;QACzF,yEAAyE;QACzE,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACjE,CAAC;IAED;;;;;OAKG;IACK,YAAY,CAAC,QAAgB;QACnC,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,UAAU,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACpG,CAAC;IAEO,gBAAgB,CACtB,QAAgB,EAChB,MAAwF;QAExF,MAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QACjE,MAAM,CAAC,SAAS,CAAC;YACf,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,gFAAgF;YAChF,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;YAC7C,KAAK,EAAE,4BAA4B;YACnC,kBAAkB,EAAE,QAAQ;YAC5B,MAAM;SACP,CAAC,CAAC;IACL,CAAC;CACF;AAED,yEAAyE;AAEzE;;;GAGG;AACH,SAAS,YAAY,CAAC,UAAkB;IACtC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAkB,CAAC;QACjD,IAAI,MAAM,CAAC,CAAC,KAAK,eAAe;YAAE,OAAO,SAAS,CAAC;QACnD,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAAE,OAAO,SAAS,CAAC;QAClF,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,MAAM,sBAAsB,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC;IACrF,MAAM,eAAe,GAAG,CAAC,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAElE,KAAK,MAAM,MAAM,IAAI,eAAe,EAAE,CAAC;QACrC,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CACb,2BAA2B,MAAM,sEAAsE,CACxG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,MAAM,MAAM,IAAI,sBAAsB,EAAE,CAAC;QAC5C,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,OAAO;IACnD,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ;YAAE,OAAO;QACzC,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;YAC3C,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,KAAK;gBAAE,OAAO;YAC/F,MAAM,IAAI,KAAK,CAAC,iFAAiF,GAAG,GAAG,CAAC,CAAC;QAC3G,CAAC;QACD,OAAO;IACT,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,uBAAuB,CAAC;YAAE,MAAM,GAAG,CAAC;QACvF,4EAA4E;IAC9E,CAAC;AACH,CAAC"}
@@ -61,6 +61,13 @@ export interface ServerConfig {
61
61
  /** Clock tolerance in seconds for JWT exp/nbf validation (default: 0 — no tolerance) */
62
62
  oidcClockTolerance?: number;
63
63
  xsuaaAuth: boolean;
64
+ /**
65
+ * Lifetime of an OAuth DCR registration (`client_id`) in seconds. Default:
66
+ * 30 days. Lower values bound the blast radius if the signing key leaks;
67
+ * higher values reduce re-auth churn. Hard-capped at 90 days — longer-lived
68
+ * credentials should use the pre-registered XSUAA client instead of DCR.
69
+ * Only consulted when XSUAA OAuth proxy mode is active. */
70
+ oauthDcrTtlSeconds: number;
64
71
  btpServiceKey?: string;
65
72
  btpServiceKeyFile?: string;
66
73
  btpOAuthCallbackPort: number;
@@ -99,6 +106,11 @@ export interface ServerConfig {
99
106
  cacheWarmupPackages: string;
100
107
  /** Maximum concurrent SAP HTTP requests (default: 10). Prevents work process exhaustion. */
101
108
  maxConcurrent: number;
109
+ /** Exact-match CORS allowlist. Empty array (the default) disables CORS entirely so that
110
+ * browser-originated cross-origin requests are blocked. Native MCP clients
111
+ * (Claude Desktop / Cursor / VS Code Copilot / Copilot Studio) do not need this — they
112
+ * use native HTTP, not the browser fetch API, and never trigger CORS. */
113
+ allowedOrigins: string[];
102
114
  verbose: boolean;
103
115
  }
104
116
  /** Default configuration values — restrictive by default. */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"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"}
@@ -36,6 +36,7 @@ export const DEFAULT_CONFIG = {
36
36
  featureFlp: 'auto',
37
37
  systemType: 'auto',
38
38
  xsuaaAuth: false,
39
+ oauthDcrTtlSeconds: 30 * 24 * 60 * 60, // 30 days
39
40
  btpOAuthCallbackPort: 0,
40
41
  ppEnabled: false,
41
42
  ppStrict: false,
@@ -49,6 +50,7 @@ export const DEFAULT_CONFIG = {
49
50
  cacheWarmup: false,
50
51
  cacheWarmupPackages: '',
51
52
  maxConcurrent: 10,
53
+ allowedOrigins: [],
52
54
  logLevel: 'info',
53
55
  logFormat: 'text',
54
56
  verbose: false,
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA0HH,6DAA6D;AAC7D,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C,GAAG,EAAE,EAAE;IACP,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,EAAE;IACZ,MAAM,EAAE,KAAK;IACb,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE,OAAO;IAClB,QAAQ,EAAE,cAAc;IACxB,WAAW,EAAE,KAAK;IAClB,gBAAgB,EAAE,KAAK;IACvB,YAAY,EAAE,KAAK;IACnB,oBAAoB,EAAE,KAAK;IAC3B,cAAc,EAAE,KAAK;IACrB,eAAe,EAAE,CAAC,MAAM,CAAC;IACzB,iBAAiB,EAAE,EAAE;IACrB,WAAW,EAAE,EAAE;IACf,cAAc,EAAE,MAAM;IACtB,WAAW,EAAE,MAAM;IACnB,UAAU,EAAE,MAAM;IAClB,WAAW,EAAE,MAAM;IACnB,UAAU,EAAE,MAAM;IAClB,gBAAgB,EAAE,MAAM;IACxB,WAAW,EAAE,MAAM;IACnB,cAAc,EAAE,MAAM;IACtB,UAAU,EAAE,MAAM;IAClB,UAAU,EAAE,MAAM;IAClB,SAAS,EAAE,KAAK;IAChB,oBAAoB,EAAE,CAAC;IACvB,SAAS,EAAE,KAAK;IAChB,QAAQ,EAAE,KAAK;IACf,oBAAoB,EAAE,KAAK;IAC3B,YAAY,EAAE,KAAK;IACnB,QAAQ,EAAE,UAAU;IACpB,eAAe,EAAE,IAAI;IACrB,gBAAgB,EAAE,KAAK;IACvB,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,gBAAgB;IAC3B,WAAW,EAAE,KAAK;IAClB,mBAAmB,EAAE,EAAE;IACvB,aAAa,EAAE,EAAE;IACjB,QAAQ,EAAE,MAAM;IAChB,SAAS,EAAE,MAAM;IACjB,OAAO,EAAE,KAAK;CACf,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAyIH,6DAA6D;AAC7D,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C,GAAG,EAAE,EAAE;IACP,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,EAAE;IACZ,MAAM,EAAE,KAAK;IACb,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE,OAAO;IAClB,QAAQ,EAAE,cAAc;IACxB,WAAW,EAAE,KAAK;IAClB,gBAAgB,EAAE,KAAK;IACvB,YAAY,EAAE,KAAK;IACnB,oBAAoB,EAAE,KAAK;IAC3B,cAAc,EAAE,KAAK;IACrB,eAAe,EAAE,CAAC,MAAM,CAAC;IACzB,iBAAiB,EAAE,EAAE;IACrB,WAAW,EAAE,EAAE;IACf,cAAc,EAAE,MAAM;IACtB,WAAW,EAAE,MAAM;IACnB,UAAU,EAAE,MAAM;IAClB,WAAW,EAAE,MAAM;IACnB,UAAU,EAAE,MAAM;IAClB,gBAAgB,EAAE,MAAM;IACxB,WAAW,EAAE,MAAM;IACnB,cAAc,EAAE,MAAM;IACtB,UAAU,EAAE,MAAM;IAClB,UAAU,EAAE,MAAM;IAClB,SAAS,EAAE,KAAK;IAChB,kBAAkB,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,UAAU;IACjD,oBAAoB,EAAE,CAAC;IACvB,SAAS,EAAE,KAAK;IAChB,QAAQ,EAAE,KAAK;IACf,oBAAoB,EAAE,KAAK;IAC3B,YAAY,EAAE,KAAK;IACnB,QAAQ,EAAE,UAAU;IACpB,eAAe,EAAE,IAAI;IACrB,gBAAgB,EAAE,KAAK;IACvB,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,gBAAgB;IAC3B,WAAW,EAAE,KAAK;IAClB,mBAAmB,EAAE,EAAE;IACvB,aAAa,EAAE,EAAE;IACjB,cAAc,EAAE,EAAE;IAClB,QAAQ,EAAE,MAAM;IAChB,SAAS,EAAE,MAAM;IACjB,OAAO,EAAE,KAAK;CACf,CAAC"}
@@ -15,19 +15,19 @@
15
15
  * - Offline validation with automatic JWKS caching
16
16
  * - checkLocalScope() for scope enforcement
17
17
  *
18
- * 2. In-memory client store for dynamic registration:
18
+ * 2. Stateless DCR client store (StatelessDcrClientStore):
19
19
  * - MCP clients (Claude Desktop, Cursor) register dynamically via RFC 7591
20
- * - Registrations are lost on restart clients re-register on reconnect
20
+ * - client_ids are HMAC-signed by the XSUAA clientsecret, so they
21
+ * survive restarts / pushes / cell moves without any backing store
21
22
  * - XSUAA clientId is pre-registered as the default client
22
23
  *
23
24
  * 3. Chained token verifier:
24
25
  * - Tries XSUAA → Entra ID OIDC → API key in order
25
26
  * - All three auth modes coexist on the same /mcp endpoint
26
27
  */
27
- import type { OAuthRegisteredClientsStore } from '@modelcontextprotocol/sdk/server/auth/clients.js';
28
28
  import { ProxyOAuthServerProvider } from '@modelcontextprotocol/sdk/server/auth/providers/proxyProvider.js';
29
29
  import type { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';
30
- import type { OAuthClientInformationFull } from '@modelcontextprotocol/sdk/shared/auth.js';
30
+ import { StatelessDcrClientStore } from './stateless-client-store.js';
31
31
  /** XSUAA credentials from VCAP_SERVICES */
32
32
  export interface XsuaaCredentials {
33
33
  url: string;
@@ -37,43 +37,6 @@ export interface XsuaaCredentials {
37
37
  uaadomain: string;
38
38
  verificationkey?: string;
39
39
  }
40
- /**
41
- * In-memory store for OAuth client registrations.
42
- *
43
- * MCP clients dynamically register via RFC 7591. The XSUAA service binding
44
- * clientId is pre-registered as the default client so that clients can
45
- * use it directly without registration.
46
- */
47
- export declare class InMemoryClientStore implements OAuthRegisteredClientsStore {
48
- private clients;
49
- constructor(xsuaaClientId: string, xsuaaClientSecret: string);
50
- /**
51
- * Dynamically add a redirect URI to a client's allow list.
52
- *
53
- * The MCP SDK validates redirect_uri with byte-exact matching for
54
- * non-loopback HTTPS URIs, but two classes of clients need relaxation:
55
- *
56
- * 1. Pre-registered XSUAA client: XSUAA itself is the authoritative
57
- * redirect-URI validator (via xs-security.json wildcard patterns),
58
- * so any URI is accepted here and forwarded.
59
- *
60
- * 2. DCR clients (arc1-*): only accept URIs that are semantically
61
- * equivalent to one the client registered. This handles clients that
62
- * use different percent-encoding at /register vs /authorize — notably
63
- * BAS/Cline via Theia's OAuth proxy, which registers `/callback?x=1`
64
- * but requests with `/callback%3Fx=1`. Security: hostname, port, and
65
- * decoded path/query must all match a previously-registered URI.
66
- */
67
- ensureRedirectUri(clientId: string, uri: string): void;
68
- getClient(clientId: string): Promise<OAuthClientInformationFull | undefined>;
69
- registerClient(client: Omit<OAuthClientInformationFull, 'client_id' | 'client_id_issued_at'>): Promise<OAuthClientInformationFull>;
70
- /**
71
- * Validate a redirect URI against allowed scheme/host policy.
72
- * Allowed: https://* , http://localhost or 127.0.0.1 or [::1], custom MCP client schemes.
73
- * Rejected: javascript:, data:, file:, ftp:, and any http:// to non-loopback hosts.
74
- */
75
- private validateRedirectUri;
76
- }
77
40
  /**
78
41
  * Verify a JWT token using @sap/xssec.
79
42
  *
@@ -97,8 +60,13 @@ export declare function createChainedTokenVerifier(config: {
97
60
  oidcIssuer?: string;
98
61
  oidcAudience?: string;
99
62
  }, xsuaaVerifier?: (token: string) => Promise<AuthInfo>, oidcVerifier?: (token: string) => Promise<AuthInfo>): (token: string) => Promise<AuthInfo>;
100
- export declare function createXsuaaOAuthProvider(credentials: XsuaaCredentials, appUrl: string): {
63
+ export interface CreateXsuaaOAuthProviderOptions {
64
+ /** Lifetime of issued DCR client_ids in seconds. Falls back to the store's
65
+ * built-in default (30 days) when omitted. */
66
+ dcrTtlSeconds?: number;
67
+ }
68
+ export declare function createXsuaaOAuthProvider(credentials: XsuaaCredentials, appUrl: string, options?: CreateXsuaaOAuthProviderOptions): {
101
69
  provider: ProxyOAuthServerProvider;
102
- clientStore: InMemoryClientStore;
70
+ clientStore: StatelessDcrClientStore;
103
71
  };
104
72
  //# sourceMappingURL=xsuaa.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"xsuaa.d.ts","sourceRoot":"","sources":["../../src/server/xsuaa.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,kDAAkD,CAAC;AAEpG,OAAO,EAAE,wBAAwB,EAAE,MAAM,kEAAkE,CAAC;AAC5G,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAC/E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0CAA0C,CAAC;AAiB3F,2CAA2C;AAC3C,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAuBD;;;;;;GAMG;AACH,qBAAa,mBAAoB,YAAW,2BAA2B;IACrE,OAAO,CAAC,OAAO,CAAiD;gBAEpD,aAAa,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM;IAsB5D;;;;;;;;;;;;;;;;OAgBG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAwBhD,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC;IAoB5E,cAAc,CAClB,MAAM,EAAE,IAAI,CAAC,0BAA0B,EAAE,WAAW,GAAG,qBAAqB,CAAC,GAC5E,OAAO,CAAC,0BAA0B,CAAC;IA4BtC;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;CAgC5B;AAID;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,gBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CA6C5G;AA2BD;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE;IACN,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,EACD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,EACpD,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,GAClD,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAuDtC;AAiPD,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,gBAAgB,EAC7B,MAAM,EAAE,MAAM,GACb;IAAE,QAAQ,EAAE,wBAAwB,CAAC;IAAC,WAAW,EAAE,mBAAmB,CAAA;CAAE,CAa1E"}
1
+ {"version":3,"file":"xsuaa.d.ts","sourceRoot":"","sources":["../../src/server/xsuaa.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAAE,wBAAwB,EAAE,MAAM,kEAAkE,CAAC;AAC5G,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAM/E,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAatE,2CAA2C;AAC3C,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAID;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,gBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CA6C5G;AA2BD;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE;IACN,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,EACD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,EACpD,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,GAClD,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAuDtC;AAiPD,MAAM,WAAW,+BAA+B;IAC9C;mDAC+C;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,gBAAgB,EAC7B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,+BAAoC,GAC5C;IAAE,QAAQ,EAAE,wBAAwB,CAAC;IAAC,WAAW,EAAE,uBAAuB,CAAA;CAAE,CAuB9E"}