@n24q02m/mcp-core 1.18.0-beta.2 → 1.18.0-beta.21

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 (55) hide show
  1. package/build/auth/credential-form.d.ts.map +1 -1
  2. package/build/auth/credential-form.js +9 -6
  3. package/build/auth/credential-form.js.map +1 -1
  4. package/build/auth/delegated-oauth-app.d.ts.map +1 -1
  5. package/build/auth/delegated-oauth-app.js +26 -10
  6. package/build/auth/delegated-oauth-app.js.map +1 -1
  7. package/build/auth/local-oauth-app.d.ts.map +1 -1
  8. package/build/auth/local-oauth-app.js +27 -11
  9. package/build/auth/local-oauth-app.js.map +1 -1
  10. package/build/auth/relay-login.d.ts.map +1 -1
  11. package/build/auth/relay-login.js +24 -22
  12. package/build/auth/relay-login.js.map +1 -1
  13. package/build/auth/well-known.d.ts.map +1 -1
  14. package/build/auth/well-known.js +1 -0
  15. package/build/auth/well-known.js.map +1 -1
  16. package/build/crypto/index.d.ts +1 -1
  17. package/build/crypto/index.d.ts.map +1 -1
  18. package/build/crypto/index.js +1 -1
  19. package/build/crypto/index.js.map +1 -1
  20. package/build/crypto/kdf.d.ts +13 -0
  21. package/build/crypto/kdf.d.ts.map +1 -1
  22. package/build/crypto/kdf.js +18 -0
  23. package/build/crypto/kdf.js.map +1 -1
  24. package/build/oauth/jwt-issuer.d.ts +58 -25
  25. package/build/oauth/jwt-issuer.d.ts.map +1 -1
  26. package/build/oauth/jwt-issuer.js +100 -31
  27. package/build/oauth/jwt-issuer.js.map +1 -1
  28. package/build/storage/backends.d.ts +56 -0
  29. package/build/storage/backends.d.ts.map +1 -0
  30. package/build/storage/backends.js +167 -0
  31. package/build/storage/backends.js.map +1 -0
  32. package/build/storage/encryption.js.map +1 -1
  33. package/build/storage/home-dir.d.ts +11 -0
  34. package/build/storage/home-dir.d.ts.map +1 -0
  35. package/build/storage/home-dir.js +18 -0
  36. package/build/storage/home-dir.js.map +1 -0
  37. package/build/storage/index.d.ts +1 -0
  38. package/build/storage/index.d.ts.map +1 -1
  39. package/build/storage/index.js +1 -0
  40. package/build/storage/index.js.map +1 -1
  41. package/build/storage/per-plugin-store.d.ts +5 -3
  42. package/build/storage/per-plugin-store.d.ts.map +1 -1
  43. package/build/storage/per-plugin-store.js +19 -28
  44. package/build/storage/per-plugin-store.js.map +1 -1
  45. package/build/transport/cache.js +5 -5
  46. package/build/transport/cache.js.map +1 -1
  47. package/build/transport/local-server.d.ts +3 -1
  48. package/build/transport/local-server.d.ts.map +1 -1
  49. package/build/transport/local-server.js +2 -2
  50. package/build/transport/local-server.js.map +1 -1
  51. package/build/transport/oauth-middleware.d.ts +2 -1
  52. package/build/transport/oauth-middleware.d.ts.map +1 -1
  53. package/build/transport/oauth-middleware.js +17 -5
  54. package/build/transport/oauth-middleware.js.map +1 -1
  55. package/package.json +9 -9
@@ -113,31 +113,26 @@ function getSafeNext(input) {
113
113
  }
114
114
  return next;
115
115
  }
116
- export async function loginGetHandler(req, res) {
117
- const next = getSafeNext(req.query?.next);
118
- res.set?.('Content-Type', 'text/html');
119
- // ``next`` flows from the query string but every interpolation is run
120
- // through ``escapeHtml`` (defined above) which replaces &, <, >, ", and
121
- // ' with their HTML entity equivalents — the same character set the
122
- // raw-html-format rule expects sanitisers to handle. Semgrep can't see
123
- // the custom helper so we suppress the warning here.
116
+ function renderLoginForm(next, errorMsg) {
124
117
  const safeNext = escapeHtml(String(next));
125
- // Visual parity with the relay credential form: same dark-theme card,
126
- // typography, ``.field-group`` / ``.field-label`` / ``.field-input``
127
- // classes, and primary submit button styling. Pure POST (no JavaScript)
128
- // so the gate works under strict CSP that blocks inline scripts.
129
- const bodyHtml = ` <div class="container">
118
+ const errorHtml = errorMsg
119
+ ? `\n <div id="login-error" class="status-box error" role="alert" style="display: block; margin-bottom: 1.25rem; margin-top: 0;">\n ${escapeHtml(errorMsg)}\n </div>`
120
+ : '';
121
+ const ariaAttributes = errorMsg
122
+ ? ' aria-invalid="true" aria-errormessage="login-error" aria-describedby="login-error relay-desc"'
123
+ : ' aria-describedby="relay-desc"';
124
+ return ` <div class="container">
130
125
  <div class="card">
131
126
  <div class="server-header">
132
127
  <h1 class="server-name">Relay login</h1>
133
128
  <div class="server-id">mcp-relay</div>
134
- <p class="server-description">Enter the relay password shared by your deployer.</p>
135
- </div>
129
+ <p class="server-description" id="relay-desc">Enter the relay password shared by your deployer.</p>
130
+ </div>${errorHtml}
136
131
 
137
- <p class="form-title">Authenticate</p>
132
+ <p class="form-title" id="form-title">Authenticate</p>
138
133
 
139
- <form method="POST" action="/login" novalidate>
140
- <!-- nosemgrep: javascript.express.security.injection.raw-html-format.raw-html-format -- safeNext is escapeHtml(next) at line 156 -->
134
+ <form method="POST" action="/login" aria-labelledby="form-title">
135
+ <!-- nosemgrep: javascript.express.security.injection.raw-html-format.raw-html-format -- safeNext is escapeHtml(next) -->
141
136
  <input type="hidden" name="next" value="${safeNext}">
142
137
  <div class="field-group">
143
138
  <label for="field-password" class="field-label">
@@ -155,15 +150,20 @@ export async function loginGetHandler(req, res) {
155
150
  autocapitalize="off"
156
151
  spellcheck="false"
157
152
  required
158
- autofocus
153
+ autofocus${ariaAttributes}
159
154
  />
160
155
  </div>
161
156
 
162
157
  <button type="submit" class="submit-btn">Continue</button>
163
158
  </form>
164
159
  </div>
165
- </div>`; // nosemgrep: javascript.express.security.injection.raw-html-format.raw-html-format
166
- res.send(renderFormShell('Relay login', bodyHtml));
160
+ </div>`;
161
+ }
162
+ export async function loginGetHandler(req, res) {
163
+ const next = getSafeNext(req.query?.next);
164
+ res.set?.('Content-Type', 'text/html');
165
+ res.set?.('X-Frame-Options', 'DENY');
166
+ res.send(renderFormShell('Relay login', renderLoginForm(next)));
167
167
  }
168
168
  export async function loginPostHandler(req, res) {
169
169
  const ip = req.ip ?? 'unknown';
@@ -178,7 +178,9 @@ export async function loginPostHandler(req, res) {
178
178
  const next = getSafeNext(req.body?.next);
179
179
  if (!configuredPassword || !timingSafeEqual(password, configuredPassword)) {
180
180
  bumpFail(ip);
181
- res.status(401).send('Invalid password.');
181
+ res.set?.('Content-Type', 'text/html');
182
+ res.set?.('X-Frame-Options', 'DENY');
183
+ res.status(401).send(renderFormShell('Relay login', renderLoginForm(next, 'Invalid password. Please try again.')));
182
184
  return;
183
185
  }
184
186
  clearFail(ip);
@@ -1 +1 @@
1
- {"version":3,"file":"relay-login.js","sourceRoot":"","sources":["../../src/auth/relay-login.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"relay-login.js","sourceRoot":"","sources":["../../src/auth/relay-login.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"well-known.d.ts","sourceRoot":"","sources":["../../src/auth/well-known.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAYtF;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMnH"}
1
+ {"version":3,"file":"well-known.d.ts","sourceRoot":"","sources":["../../src/auth/well-known.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAatF;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMnH"}
@@ -5,6 +5,7 @@ export function authorizationServerMetadata(issuerUrl) {
5
5
  authorization_endpoint: `${issuerUrl}/authorize`,
6
6
  token_endpoint: `${issuerUrl}/token`,
7
7
  registration_endpoint: `${issuerUrl}/register`,
8
+ jwks_uri: `${issuerUrl}/.well-known/jwks.json`,
8
9
  response_types_supported: ['code'],
9
10
  grant_types_supported: ['authorization_code', 'refresh_token'],
10
11
  code_challenge_methods_supported: ['S256'],
@@ -1 +1 @@
1
- {"version":3,"file":"well-known.js","sourceRoot":"","sources":["../../src/auth/well-known.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,MAAM,UAAU,2BAA2B,CAAC,SAAiB;IAC3D,OAAO;QACL,MAAM,EAAE,SAAS;QACjB,sBAAsB,EAAE,GAAG,SAAS,YAAY;QAChD,cAAc,EAAE,GAAG,SAAS,QAAQ;QACpC,qBAAqB,EAAE,GAAG,SAAS,WAAW;QAC9C,wBAAwB,EAAE,CAAC,MAAM,CAAC;QAClC,qBAAqB,EAAE,CAAC,oBAAoB,EAAE,eAAe,CAAC;QAC9D,gCAAgC,EAAE,CAAC,MAAM,CAAC;QAC1C,qCAAqC,EAAE,CAAC,MAAM,CAAC;QAC/C,gBAAgB,EAAE,CAAC,gBAAgB,CAAC;KACrC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,QAAgB,EAAE,oBAA8B;IACxF,OAAO;QACL,QAAQ;QACR,qBAAqB,EAAE,oBAAoB;QAC3C,wBAAwB,EAAE,CAAC,QAAQ,CAAC;KACrC,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"well-known.js","sourceRoot":"","sources":["../../src/auth/well-known.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,MAAM,UAAU,2BAA2B,CAAC,SAAiB;IAC3D,OAAO;QACL,MAAM,EAAE,SAAS;QACjB,sBAAsB,EAAE,GAAG,SAAS,YAAY;QAChD,cAAc,EAAE,GAAG,SAAS,QAAQ;QACpC,qBAAqB,EAAE,GAAG,SAAS,WAAW;QAC9C,QAAQ,EAAE,GAAG,SAAS,wBAAwB;QAC9C,wBAAwB,EAAE,CAAC,MAAM,CAAC;QAClC,qBAAqB,EAAE,CAAC,oBAAoB,EAAE,eAAe,CAAC;QAC9D,gCAAgC,EAAE,CAAC,MAAM,CAAC;QAC1C,qCAAqC,EAAE,CAAC,MAAM,CAAC;QAC/C,gBAAgB,EAAE,CAAC,gBAAgB,CAAC;KACrC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,QAAgB,EAAE,oBAA8B;IACxF,OAAO;QACL,QAAQ;QACR,qBAAqB,EAAE,oBAAoB;QAC3C,wBAAwB,EAAE,CAAC,QAAQ,CAAC;KACrC,CAAA;AACH,CAAC"}
@@ -1,4 +1,4 @@
1
1
  export { decrypt, type EncryptResult, encrypt } from './aes.js';
2
2
  export { deriveSharedSecret, exportPublicKey, generateKeyPair, importPublicKey } from './ecdh.js';
3
- export { deriveAesKey } from './kdf.js';
3
+ export { deriveAesKey, deriveJwtSigningSeed } from './kdf.js';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/crypto/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,aAAa,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAC/D,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AACjG,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/crypto/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,aAAa,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAC/D,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AACjG,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA"}
@@ -1,4 +1,4 @@
1
1
  export { decrypt, encrypt } from './aes.js';
2
2
  export { deriveSharedSecret, exportPublicKey, generateKeyPair, importPublicKey } from './ecdh.js';
3
- export { deriveAesKey } from './kdf.js';
3
+ export { deriveAesKey, deriveJwtSigningSeed } from './kdf.js';
4
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/crypto/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAsB,OAAO,EAAE,MAAM,UAAU,CAAA;AAC/D,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AACjG,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/crypto/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAsB,OAAO,EAAE,MAAM,UAAU,CAAA;AAC/D,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AACjG,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA"}
@@ -1,2 +1,15 @@
1
1
  export declare function deriveAesKey(sharedSecret: ArrayBuffer, passphrase: string): Promise<CryptoKey>;
2
+ /**
3
+ * Derive a deterministic 32-byte Ed25519 seed for OAuth JWT signing.
4
+ *
5
+ * Used in HTTP multi-user mode (CREDENTIAL_SECRET set) so every container
6
+ * replica converges on the SAME signing key without a shared volume or
7
+ * external secret store. Domain-separated per server via the HKDF info label.
8
+ *
9
+ * HKDF-SHA256 with IKM = secret, empty salt, info =
10
+ * `mcp-jwt-signing-key-v1:<serverName>`. Byte-identical to core-py's
11
+ * `derive_jwt_signing_seed` for the same inputs (enforced by the shared
12
+ * crypto-vectors fixture).
13
+ */
14
+ export declare function deriveJwtSigningSeed(secret: string, serverName: string): Buffer;
2
15
  //# sourceMappingURL=kdf.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"kdf.d.ts","sourceRoot":"","sources":["../../src/crypto/kdf.ts"],"names":[],"mappings":"AAIA,wBAAsB,YAAY,CAAC,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAWpG"}
1
+ {"version":3,"file":"kdf.d.ts","sourceRoot":"","sources":["../../src/crypto/kdf.ts"],"names":[],"mappings":"AAOA,wBAAsB,YAAY,CAAC,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAWpG;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAG/E"}
@@ -1,8 +1,26 @@
1
+ import { hkdfSync } from 'node:crypto';
1
2
  const encoder = new TextEncoder();
2
3
  const INFO = encoder.encode('mcp-relay');
4
+ const JWT_SIGNING_INFO_PREFIX = 'mcp-jwt-signing-key-v1:';
3
5
  export async function deriveAesKey(sharedSecret, passphrase) {
4
6
  const salt = encoder.encode(passphrase);
5
7
  const keyMaterial = await crypto.subtle.importKey('raw', sharedSecret, 'HKDF', false, ['deriveKey']);
6
8
  return crypto.subtle.deriveKey({ name: 'HKDF', hash: 'SHA-256', salt, info: INFO }, keyMaterial, { name: 'AES-GCM', length: 256 }, true, ['encrypt', 'decrypt']);
7
9
  }
10
+ /**
11
+ * Derive a deterministic 32-byte Ed25519 seed for OAuth JWT signing.
12
+ *
13
+ * Used in HTTP multi-user mode (CREDENTIAL_SECRET set) so every container
14
+ * replica converges on the SAME signing key without a shared volume or
15
+ * external secret store. Domain-separated per server via the HKDF info label.
16
+ *
17
+ * HKDF-SHA256 with IKM = secret, empty salt, info =
18
+ * `mcp-jwt-signing-key-v1:<serverName>`. Byte-identical to core-py's
19
+ * `derive_jwt_signing_seed` for the same inputs (enforced by the shared
20
+ * crypto-vectors fixture).
21
+ */
22
+ export function deriveJwtSigningSeed(secret, serverName) {
23
+ const info = encoder.encode(`${JWT_SIGNING_INFO_PREFIX}${serverName}`);
24
+ return Buffer.from(hkdfSync('sha256', Buffer.from(secret, 'utf-8'), Buffer.alloc(0), info, 32));
25
+ }
8
26
  //# sourceMappingURL=kdf.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"kdf.js","sourceRoot":"","sources":["../../src/crypto/kdf.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAA;AAEjC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;AAExC,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,YAAyB,EAAE,UAAkB;IAC9E,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IACvC,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,WAAW,CAAC,CAAC,CAAA;IAEpG,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,CAC5B,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EACnD,WAAW,EACX,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,EAChC,IAAI,EACJ,CAAC,SAAS,EAAE,SAAS,CAAC,CACvB,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"kdf.js","sourceRoot":"","sources":["../../src/crypto/kdf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAEtC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAA;AAEjC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;AACxC,MAAM,uBAAuB,GAAG,yBAAyB,CAAA;AAEzD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,YAAyB,EAAE,UAAkB;IAC9E,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IACvC,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,WAAW,CAAC,CAAC,CAAA;IAEpG,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,CAC5B,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EACnD,WAAW,EACX,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,EAChC,IAAI,EACJ,CAAC,SAAS,EAAE,SAAS,CAAC,CACvB,CAAA;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAc,EAAE,UAAkB;IACrE,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,uBAAuB,GAAG,UAAU,EAAE,CAAC,CAAA;IACtE,OAAO,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAA;AACjG,CAAC"}
@@ -1,6 +1,24 @@
1
1
  /**
2
- * RSA JWT Issuer and JWKS generation for TypeScript MCP servers.
2
+ * JWT Issuer and JWKS generation for TypeScript MCP servers.
3
3
  * Uses jose (industry-standard, zero-dep, Web Crypto compatible).
4
+ *
5
+ * Two signing modes, selected at construction:
6
+ *
7
+ * - LOCAL single-user (credentialSecret unset): RSA-2048, RS256, kid="key-1",
8
+ * keys generated on first run and persisted to disk so they survive restarts
9
+ * on a real machine. Behavior is unchanged from the pre-stability-fix code.
10
+ *
11
+ * - HTTP multi-user (credentialSecret set): Ed25519, EdDSA, signing key DERIVED
12
+ * deterministically from CREDENTIAL_SECRET via HKDF-SHA256. No disk I/O. Every
13
+ * container replica converges on the same key without a shared volume or
14
+ * external secret store, so OAuth tokens survive container recreation
15
+ * (Watchtower :latest redeploys). kid is the base64url SHA-256 thumbprint of
16
+ * the raw public key.
17
+ *
18
+ * The two modes are different deployments that never exchange tokens
19
+ * (iss/aud are server-scoped); the per-mode algorithm split is permanent and
20
+ * intentional. Each process runs exactly one algorithm; the verify path uses
21
+ * that single alg, never a {RS256, EdDSA} union.
4
22
  */
5
23
  import * as jose from 'jose';
6
24
  export declare class JWTIssuer {
@@ -8,46 +26,61 @@ export declare class JWTIssuer {
8
26
  private keysDir;
9
27
  private privateKeyPath;
10
28
  private publicKeyPath;
29
+ private credentialSecret;
30
+ alg: 'RS256' | 'EdDSA';
11
31
  private kid;
12
32
  private privateKey;
13
33
  private publicKey;
34
+ private okpX;
14
35
  private _initialized;
15
- constructor(serverName: string, keysDir?: string);
16
- /** Must call before using issuer — loads or generates RSA keys. */
36
+ constructor(serverName: string, keysDir?: string, credentialSecret?: string | null);
37
+ /** Must call before using issuer — loads/generates (RSA) or derives (EdDSA) keys. */
17
38
  init(): Promise<void>;
18
- /** Return JWKS payload for /.well-known/jwks.json */
39
+ private deriveEddsaKeys;
40
+ private loadOrGenerateRsaKeys;
41
+ /**
42
+ * Return JWKS payload for /.well-known/jwks.json. Always a `keys` array
43
+ * (multi-key-aware for future rotation). RSA mode emits an RSA JWK; EdDSA
44
+ * mode emits an OKP JWK.
45
+ */
19
46
  getJwks(): Promise<jose.JSONWebKeySet>;
20
- /** Issue an RS256 JWT access token (``typ="access"``). */
47
+ /** Issue a JWT access token (typ="access") signed with the active alg. */
21
48
  issueAccessToken(sub: string, expiresInSeconds?: number): Promise<string>;
22
49
  /**
23
- * Issue an RS256 JWT refresh token (``typ="refresh"``).
50
+ * Issue a JWT refresh token (typ="refresh") signed with the active alg.
24
51
  *
25
- * Defaults to a 30-day (2592000s) lifetime so long-running MCP clients can
26
- * mint fresh access tokens without forcing the user back through the
27
- * browser PKCE flow every hour. Same key / iss / aud as access tokens; the
28
- * ``typ`` claim is the only thing distinguishing them, and
29
- * ``verifyAccessToken`` rejects ``typ="refresh"`` so a refresh token can
30
- * never be used as an access token at the ``/mcp`` resource.
52
+ * Defaults to a 1-year (31536000s) lifetime so long-running MCP clients can
53
+ * mint fresh access tokens without forcing the user back through the browser
54
+ * PKCE flow. The access token stays short-lived (1h); the refresh token is the
55
+ * renewal credential and is rotated on every use (the /token refresh handler
56
+ * issues a new refresh token each time), so the security control is rotation,
57
+ * not a short TTL. A short refresh TTL was the residual re-auth driver: a
58
+ * self-hosted server a user touches only intermittently (less than once a
59
+ * month) would silently expire its refresh token between sessions, forcing a
60
+ * fresh browser OAuth tab on the next use. With a 1-year floor, only a
61
+ * genuinely long idle gap re-prompts. Same key / iss / aud as access tokens;
62
+ * the typ claim is the only thing distinguishing them, and verifyAccessToken
63
+ * rejects typ="refresh" so a refresh token can never be used as an access
64
+ * token at the /mcp resource.
31
65
  */
32
66
  issueRefreshToken(sub: string, expiresInSeconds?: number): Promise<string>;
33
67
  /**
34
- * Verify a JWT access token and return its payload. Throws on failure
35
- * (bad signature, wrong issuer/audience, expired) — the same jose errors
36
- * existing callers already catch. Additionally rejects tokens whose
37
- * ``typ`` claim is ``"refresh"`` (throwing ``jose.errors.JWTClaimValidationFailed``)
38
- * so a refresh token cannot be replayed as an access token. Tokens with
39
- * ``typ="access"`` OR a missing ``typ`` claim are accepted (the latter
40
- * keeps already-issued pre-refresh-support tokens valid).
68
+ * Verify a JWT access token and return its payload. Throws on failure (bad
69
+ * signature, wrong issuer/audience, expired) — the same jose errors existing
70
+ * callers already catch. The verify path uses the single active algorithm,
71
+ * never a union. Additionally rejects tokens whose typ claim is "refresh"
72
+ * (throwing jose.errors.JWTClaimValidationFailed) so a refresh token cannot
73
+ * be replayed as an access token. Tokens with typ="access" OR a missing typ
74
+ * claim are accepted (the latter keeps already-issued pre-refresh-support
75
+ * tokens valid).
41
76
  */
42
77
  verifyAccessToken(token: string): Promise<jose.JWTPayload>;
43
78
  /**
44
79
  * Verify a JWT refresh token and return its payload. Same key / audience /
45
- * issuer checks as ``verifyAccessToken`` and throws the same jose errors on
46
- * failure. Additionally asserts ``typ=="refresh"`` (throwing
47
- * ``jose.errors.JWTClaimValidationFailed`` otherwise) so an access token
48
- * can never be exchanged at the refresh grant. ``JWTClaimValidationFailed``
49
- * extends ``jose.errors.JOSEError``, so callers' existing ``catch`` clauses
50
- * around ``verifyAccessToken`` already catch it.
80
+ * issuer checks as verifyAccessToken and throws the same jose errors on
81
+ * failure; uses the single active algorithm. Additionally asserts
82
+ * typ=="refresh" (throwing jose.errors.JWTClaimValidationFailed otherwise) so
83
+ * an access token can never be exchanged at the refresh grant.
51
84
  */
52
85
  verifyRefreshToken(token: string): Promise<jose.JWTPayload>;
53
86
  }
@@ -1 +1 @@
1
- {"version":3,"file":"jwt-issuer.d.ts","sourceRoot":"","sources":["../../src/oauth/jwt-issuer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAI5B,qBAAa,SAAS;IACpB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,GAAG,CAAU;IACrB,OAAO,CAAC,UAAU,CAA8B;IAChD,OAAO,CAAC,SAAS,CAA8B;IAC/C,OAAO,CAAC,YAAY,CAAQ;gBAEhB,UAAU,EAAE,MAAM,EAAE,OAAO,SAAmB;IAO1D,mEAAmE;IAC7D,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA4B3B,qDAAqD;IAC/C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC;IAS5C,0DAA0D;IACpD,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,gBAAgB,SAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAW7E;;;;;;;;;OASG;IACG,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,gBAAgB,SAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAWjF;;;;;;;;OAQG;IACG,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;IAYhE;;;;;;;;OAQG;IACG,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;CAWlE"}
1
+ {"version":3,"file":"jwt-issuer.d.ts","sourceRoot":"","sources":["../../src/oauth/jwt-issuer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAMH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAU5B,qBAAa,SAAS;IACpB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,gBAAgB,CAAe;IACvC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAA;IACtB,OAAO,CAAC,GAAG,CAAU;IACrB,OAAO,CAAC,UAAU,CAA8B;IAChD,OAAO,CAAC,SAAS,CAA8B;IAC/C,OAAO,CAAC,IAAI,CAAsB;IAClC,OAAO,CAAC,YAAY,CAAQ;gBAEhB,UAAU,EAAE,MAAM,EAAE,OAAO,SAAmB,EAAE,gBAAgB,GAAE,MAAM,GAAG,IAAW;IASlG,qFAAqF;IAC/E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAgBb,eAAe;YAYf,qBAAqB;IA0BnC;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC;IAc5C,0EAA0E;IACpE,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,gBAAgB,SAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAW7E;;;;;;;;;;;;;;;;OAgBG;IACG,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,gBAAgB,SAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAWlF;;;;;;;;;OASG;IACG,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;IAahE;;;;;;OAMG;IACG,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;CAYlE"}
@@ -1,27 +1,80 @@
1
1
  /**
2
- * RSA JWT Issuer and JWKS generation for TypeScript MCP servers.
2
+ * JWT Issuer and JWKS generation for TypeScript MCP servers.
3
3
  * Uses jose (industry-standard, zero-dep, Web Crypto compatible).
4
+ *
5
+ * Two signing modes, selected at construction:
6
+ *
7
+ * - LOCAL single-user (credentialSecret unset): RSA-2048, RS256, kid="key-1",
8
+ * keys generated on first run and persisted to disk so they survive restarts
9
+ * on a real machine. Behavior is unchanged from the pre-stability-fix code.
10
+ *
11
+ * - HTTP multi-user (credentialSecret set): Ed25519, EdDSA, signing key DERIVED
12
+ * deterministically from CREDENTIAL_SECRET via HKDF-SHA256. No disk I/O. Every
13
+ * container replica converges on the same key without a shared volume or
14
+ * external secret store, so OAuth tokens survive container recreation
15
+ * (Watchtower :latest redeploys). kid is the base64url SHA-256 thumbprint of
16
+ * the raw public key.
17
+ *
18
+ * The two modes are different deployments that never exchange tokens
19
+ * (iss/aud are server-scoped); the per-mode algorithm split is permanent and
20
+ * intentional. Each process runs exactly one algorithm; the verify path uses
21
+ * that single alg, never a {RS256, EdDSA} union.
4
22
  */
23
+ import { createHash, createPrivateKey } from 'node:crypto';
5
24
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
6
25
  import { homedir } from 'node:os';
7
26
  import { join } from 'node:path';
8
27
  import * as jose from 'jose';
28
+ import { deriveJwtSigningSeed } from '../crypto/kdf.js';
9
29
  const DEFAULT_KEYS_DIR = join(homedir(), '.mcp-core', 'jwt-keys');
30
+ // RFC 8410 PKCS8 DER prefix for an Ed25519 private key. Prepended to the
31
+ // 32-byte HKDF seed to build an importable PKCS8 key (jose 6.2.3 cannot import
32
+ // a raw seed via importJWK d-only).
33
+ const ED25519_PKCS8_PREFIX = Buffer.from('302e020100300506032b657004220420', 'hex');
10
34
  export class JWTIssuer {
11
- constructor(serverName, keysDir = DEFAULT_KEYS_DIR) {
35
+ constructor(serverName, keysDir = DEFAULT_KEYS_DIR, credentialSecret = null) {
12
36
  this.kid = 'key-1';
13
37
  this.privateKey = null;
14
38
  this.publicKey = null;
39
+ this.okpX = null;
15
40
  this._initialized = false;
16
41
  this.serverName = serverName;
17
42
  this.keysDir = keysDir;
43
+ this.credentialSecret = credentialSecret;
44
+ this.alg = credentialSecret ? 'EdDSA' : 'RS256';
18
45
  this.privateKeyPath = join(this.keysDir, `${serverName}_private.pem`);
19
46
  this.publicKeyPath = join(this.keysDir, `${serverName}_public.pem`);
20
47
  }
21
- /** Must call before using issuer — loads or generates RSA keys. */
48
+ /** Must call before using issuer — loads/generates (RSA) or derives (EdDSA) keys. */
22
49
  async init() {
23
50
  if (this._initialized)
24
51
  return;
52
+ if (this.credentialSecret) {
53
+ await this.deriveEddsaKeys(this.credentialSecret);
54
+ // Don't name the source env var in the message: only serverName + the
55
+ // public kid thumbprint are logged (never the secret), and the literal
56
+ // "CREDENTIAL_SECRET" token trips the SAST logger-credential heuristic
57
+ // for no real benefit (parity with core-py jwt_issuer.py).
58
+ console.error(`JWTIssuer[${this.serverName}]: HTTP multi-user mode, EdDSA signing key derived (kid=${this.kid})`);
59
+ }
60
+ else {
61
+ await this.loadOrGenerateRsaKeys();
62
+ console.error(`JWTIssuer[${this.serverName}]: local single-user mode, RS256 key on disk (${this.keysDir})`);
63
+ }
64
+ this._initialized = true;
65
+ }
66
+ async deriveEddsaKeys(credentialSecret) {
67
+ const seed = deriveJwtSigningSeed(credentialSecret, this.serverName);
68
+ const der = Buffer.concat([ED25519_PKCS8_PREFIX, seed]);
69
+ const pem = `-----BEGIN PRIVATE KEY-----\n${der.toString('base64')}\n-----END PRIVATE KEY-----\n`;
70
+ this.privateKey = await jose.importPKCS8(pem, 'EdDSA', { extractable: false });
71
+ // Recover the public JWK x via node:crypto (jose has no seed->public path).
72
+ const jwk = createPrivateKey(pem).export({ format: 'jwk' });
73
+ this.okpX = jwk.x;
74
+ this.publicKey = (await jose.importJWK({ kty: 'OKP', crv: 'Ed25519', x: jwk.x }, 'EdDSA'));
75
+ this.kid = createHash('sha256').update(Buffer.from(jwk.x, 'base64url')).digest('base64url').slice(0, 16);
76
+ }
77
+ async loadOrGenerateRsaKeys() {
25
78
  mkdirSync(this.keysDir, { recursive: true, mode: 0o700 });
26
79
  if (existsSync(this.privateKeyPath) && existsSync(this.publicKeyPath)) {
27
80
  const privatePem = readFileSync(this.privateKeyPath, 'utf-8');
@@ -42,24 +95,32 @@ export class JWTIssuer {
42
95
  this.privateKey = await jose.importPKCS8(privatePem, 'RS256', { extractable: false });
43
96
  this.publicKey = await jose.importSPKI(publicPem, 'RS256', { extractable: true });
44
97
  }
45
- this._initialized = true;
46
98
  }
47
- /** Return JWKS payload for /.well-known/jwks.json */
99
+ /**
100
+ * Return JWKS payload for /.well-known/jwks.json. Always a `keys` array
101
+ * (multi-key-aware for future rotation). RSA mode emits an RSA JWK; EdDSA
102
+ * mode emits an OKP JWK.
103
+ */
48
104
  async getJwks() {
49
105
  if (!this.publicKey)
50
106
  throw new Error('JWTIssuer not initialized');
107
+ if (this.alg === 'EdDSA') {
108
+ return {
109
+ keys: [{ kty: 'OKP', crv: 'Ed25519', x: this.okpX, use: 'sig', alg: 'EdDSA', kid: this.kid }]
110
+ };
111
+ }
51
112
  const jwk = await jose.exportJWK(this.publicKey);
52
113
  jwk.kid = this.kid;
53
114
  jwk.use = 'sig';
54
115
  jwk.alg = 'RS256';
55
116
  return { keys: [jwk] };
56
117
  }
57
- /** Issue an RS256 JWT access token (``typ="access"``). */
118
+ /** Issue a JWT access token (typ="access") signed with the active alg. */
58
119
  async issueAccessToken(sub, expiresInSeconds = 3600) {
59
120
  if (!this.privateKey)
60
121
  throw new Error('JWTIssuer not initialized');
61
122
  return new jose.SignJWT({ sub, typ: 'access' })
62
- .setProtectedHeader({ alg: 'RS256', kid: this.kid })
123
+ .setProtectedHeader({ alg: this.alg, kid: this.kid })
63
124
  .setIssuer(this.serverName)
64
125
  .setAudience(this.serverName)
65
126
  .setIssuedAt()
@@ -67,20 +128,27 @@ export class JWTIssuer {
67
128
  .sign(this.privateKey);
68
129
  }
69
130
  /**
70
- * Issue an RS256 JWT refresh token (``typ="refresh"``).
131
+ * Issue a JWT refresh token (typ="refresh") signed with the active alg.
71
132
  *
72
- * Defaults to a 30-day (2592000s) lifetime so long-running MCP clients can
73
- * mint fresh access tokens without forcing the user back through the
74
- * browser PKCE flow every hour. Same key / iss / aud as access tokens; the
75
- * ``typ`` claim is the only thing distinguishing them, and
76
- * ``verifyAccessToken`` rejects ``typ="refresh"`` so a refresh token can
77
- * never be used as an access token at the ``/mcp`` resource.
133
+ * Defaults to a 1-year (31536000s) lifetime so long-running MCP clients can
134
+ * mint fresh access tokens without forcing the user back through the browser
135
+ * PKCE flow. The access token stays short-lived (1h); the refresh token is the
136
+ * renewal credential and is rotated on every use (the /token refresh handler
137
+ * issues a new refresh token each time), so the security control is rotation,
138
+ * not a short TTL. A short refresh TTL was the residual re-auth driver: a
139
+ * self-hosted server a user touches only intermittently (less than once a
140
+ * month) would silently expire its refresh token between sessions, forcing a
141
+ * fresh browser OAuth tab on the next use. With a 1-year floor, only a
142
+ * genuinely long idle gap re-prompts. Same key / iss / aud as access tokens;
143
+ * the typ claim is the only thing distinguishing them, and verifyAccessToken
144
+ * rejects typ="refresh" so a refresh token can never be used as an access
145
+ * token at the /mcp resource.
78
146
  */
79
- async issueRefreshToken(sub, expiresInSeconds = 2592000) {
147
+ async issueRefreshToken(sub, expiresInSeconds = 31536000) {
80
148
  if (!this.privateKey)
81
149
  throw new Error('JWTIssuer not initialized');
82
150
  return new jose.SignJWT({ sub, typ: 'refresh' })
83
- .setProtectedHeader({ alg: 'RS256', kid: this.kid })
151
+ .setProtectedHeader({ alg: this.alg, kid: this.kid })
84
152
  .setIssuer(this.serverName)
85
153
  .setAudience(this.serverName)
86
154
  .setIssuedAt()
@@ -88,20 +156,22 @@ export class JWTIssuer {
88
156
  .sign(this.privateKey);
89
157
  }
90
158
  /**
91
- * Verify a JWT access token and return its payload. Throws on failure
92
- * (bad signature, wrong issuer/audience, expired) — the same jose errors
93
- * existing callers already catch. Additionally rejects tokens whose
94
- * ``typ`` claim is ``"refresh"`` (throwing ``jose.errors.JWTClaimValidationFailed``)
95
- * so a refresh token cannot be replayed as an access token. Tokens with
96
- * ``typ="access"`` OR a missing ``typ`` claim are accepted (the latter
97
- * keeps already-issued pre-refresh-support tokens valid).
159
+ * Verify a JWT access token and return its payload. Throws on failure (bad
160
+ * signature, wrong issuer/audience, expired) — the same jose errors existing
161
+ * callers already catch. The verify path uses the single active algorithm,
162
+ * never a union. Additionally rejects tokens whose typ claim is "refresh"
163
+ * (throwing jose.errors.JWTClaimValidationFailed) so a refresh token cannot
164
+ * be replayed as an access token. Tokens with typ="access" OR a missing typ
165
+ * claim are accepted (the latter keeps already-issued pre-refresh-support
166
+ * tokens valid).
98
167
  */
99
168
  async verifyAccessToken(token) {
100
169
  if (!this.publicKey)
101
170
  throw new Error('JWTIssuer not initialized');
102
171
  const { payload } = await jose.jwtVerify(token, this.publicKey, {
103
172
  issuer: this.serverName,
104
- audience: this.serverName
173
+ audience: this.serverName,
174
+ algorithms: [this.alg]
105
175
  });
106
176
  if (payload.typ === 'refresh') {
107
177
  throw new jose.errors.JWTClaimValidationFailed('Refresh token cannot be used as an access token', payload, 'typ');
@@ -110,19 +180,18 @@ export class JWTIssuer {
110
180
  }
111
181
  /**
112
182
  * Verify a JWT refresh token and return its payload. Same key / audience /
113
- * issuer checks as ``verifyAccessToken`` and throws the same jose errors on
114
- * failure. Additionally asserts ``typ=="refresh"`` (throwing
115
- * ``jose.errors.JWTClaimValidationFailed`` otherwise) so an access token
116
- * can never be exchanged at the refresh grant. ``JWTClaimValidationFailed``
117
- * extends ``jose.errors.JOSEError``, so callers' existing ``catch`` clauses
118
- * around ``verifyAccessToken`` already catch it.
183
+ * issuer checks as verifyAccessToken and throws the same jose errors on
184
+ * failure; uses the single active algorithm. Additionally asserts
185
+ * typ=="refresh" (throwing jose.errors.JWTClaimValidationFailed otherwise) so
186
+ * an access token can never be exchanged at the refresh grant.
119
187
  */
120
188
  async verifyRefreshToken(token) {
121
189
  if (!this.publicKey)
122
190
  throw new Error('JWTIssuer not initialized');
123
191
  const { payload } = await jose.jwtVerify(token, this.publicKey, {
124
192
  issuer: this.serverName,
125
- audience: this.serverName
193
+ audience: this.serverName,
194
+ algorithms: [this.alg]
126
195
  });
127
196
  if (payload.typ !== 'refresh') {
128
197
  throw new jose.errors.JWTClaimValidationFailed('Token is not a refresh token', payload, 'typ');
@@ -1 +1 @@
1
- {"version":3,"file":"jwt-issuer.js","sourceRoot":"","sources":["../../src/oauth/jwt-issuer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"jwt-issuer.js","sourceRoot":"","sources":["../../src/oauth/jwt-issuer.ts"],"names":[],"mappings":"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"}