@n24q02m/mcp-core 1.16.0 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/auth/delegated-oauth-app.d.ts.map +1 -1
- package/build/auth/delegated-oauth-app.js +54 -6
- package/build/auth/delegated-oauth-app.js.map +1 -1
- package/build/auth/local-oauth-app.d.ts.map +1 -1
- package/build/auth/local-oauth-app.js +52 -6
- package/build/auth/local-oauth-app.js.map +1 -1
- package/build/auth/relay-login.d.ts.map +1 -1
- package/build/auth/relay-login.js +19 -7
- package/build/auth/relay-login.js.map +1 -1
- package/build/auth/well-known.d.ts.map +1 -1
- package/build/auth/well-known.js +3 -2
- package/build/auth/well-known.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/oauth/cache.d.ts +22 -0
- package/build/oauth/cache.d.ts.map +1 -0
- package/build/oauth/cache.js +24 -0
- package/build/oauth/cache.js.map +1 -0
- package/build/oauth/index.d.ts +3 -1
- package/build/oauth/index.d.ts.map +1 -1
- package/build/oauth/index.js +3 -1
- package/build/oauth/index.js.map +1 -1
- package/build/oauth/jwt-issuer.d.ts +31 -2
- package/build/oauth/jwt-issuer.d.ts.map +1 -1
- package/build/oauth/jwt-issuer.js +56 -3
- package/build/oauth/jwt-issuer.js.map +1 -1
- package/build/oauth/pkce.d.ts +10 -0
- package/build/oauth/pkce.d.ts.map +1 -0
- package/build/oauth/pkce.js +34 -0
- package/build/oauth/pkce.js.map +1 -0
- package/build/oauth/provider.d.ts +6 -21
- package/build/oauth/provider.d.ts.map +1 -1
- package/build/oauth/provider.js +20 -55
- package/build/oauth/provider.js.map +1 -1
- package/build/relay/browser.d.ts.map +1 -1
- package/build/relay/browser.js +5 -10
- package/build/relay/browser.js.map +1 -1
- package/build/storage/config-file.d.ts.map +1 -1
- package/build/storage/config-file.js +72 -20
- package/build/storage/config-file.js.map +1 -1
- package/build/storage/encryption.d.ts +4 -2
- package/build/storage/encryption.d.ts.map +1 -1
- package/build/storage/encryption.js +6 -5
- package/build/storage/encryption.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export class InMemoryAuthCache {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.cache = new Map();
|
|
4
|
+
}
|
|
5
|
+
save(session) {
|
|
6
|
+
this.cache.set(session.sessionId, session);
|
|
7
|
+
// Cleanup expired entries
|
|
8
|
+
const now = Math.floor(Date.now() / 1000);
|
|
9
|
+
for (const [id, sess] of this.cache) {
|
|
10
|
+
if (sess.expiresAt < now)
|
|
11
|
+
this.cache.delete(id);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
getAndDelete(sessionId) {
|
|
15
|
+
const sess = this.cache.get(sessionId);
|
|
16
|
+
if (!sess)
|
|
17
|
+
return null;
|
|
18
|
+
this.cache.delete(sessionId);
|
|
19
|
+
if (sess.expiresAt < Math.floor(Date.now() / 1000))
|
|
20
|
+
return null;
|
|
21
|
+
return sess;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/oauth/cache.ts"],"names":[],"mappings":"AAkBA,MAAM,OAAO,iBAAiB;IAA9B;QACU,UAAK,GAAG,IAAI,GAAG,EAA0B,CAAA;IAkBnD,CAAC;IAhBC,IAAI,CAAC,OAAuB;QAC1B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;QAC1C,0BAA0B;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;QACzC,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACpC,IAAI,IAAI,CAAC,SAAS,GAAG,GAAG;gBAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QACjD,CAAC;IACH,CAAC;IAED,YAAY,CAAC,SAAiB;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QACtC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAA;QACtB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QAC5B,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YAAE,OAAO,IAAI,CAAA;QAC/D,OAAO,IAAI,CAAA;IACb,CAAC;CACF"}
|
package/build/oauth/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
export { InMemoryAuthCache, type IOAuthSessionCache, type PreAuthSession } from './cache.js';
|
|
1
2
|
export { JWTIssuer } from './jwt-issuer.js';
|
|
2
|
-
export {
|
|
3
|
+
export { verifyPKCE } from './pkce.js';
|
|
4
|
+
export { OAuthProvider, type OAuthProviderOptions } from './provider.js';
|
|
3
5
|
export { type IUserCredentialStore, SqliteUserStore } from './user-store.js';
|
|
4
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EACL,aAAa,EACb,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,KAAK,oBAAoB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA"}
|
package/build/oauth/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
export { InMemoryAuthCache } from './cache.js';
|
|
1
2
|
export { JWTIssuer } from './jwt-issuer.js';
|
|
2
|
-
export {
|
|
3
|
+
export { verifyPKCE } from './pkce.js';
|
|
4
|
+
export { OAuthProvider } from './provider.js';
|
|
3
5
|
export { SqliteUserStore } from './user-store.js';
|
|
4
6
|
//# sourceMappingURL=index.js.map
|
package/build/oauth/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EAGlB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EACL,aAAa,EAEd,MAAM,eAAe,CAAA;AACtB,OAAO,EAA6B,eAAe,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -17,9 +17,38 @@ export declare class JWTIssuer {
|
|
|
17
17
|
init(): Promise<void>;
|
|
18
18
|
/** Return JWKS payload for /.well-known/jwks.json */
|
|
19
19
|
getJwks(): Promise<jose.JSONWebKeySet>;
|
|
20
|
-
/** Issue an RS256 JWT access token. */
|
|
20
|
+
/** Issue an RS256 JWT access token (``typ="access"``). */
|
|
21
21
|
issueAccessToken(sub: string, expiresInSeconds?: number): Promise<string>;
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* Issue an RS256 JWT refresh token (``typ="refresh"``).
|
|
24
|
+
*
|
|
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.
|
|
31
|
+
*/
|
|
32
|
+
issueRefreshToken(sub: string, expiresInSeconds?: number): Promise<string>;
|
|
33
|
+
/**
|
|
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).
|
|
41
|
+
*/
|
|
23
42
|
verifyAccessToken(token: string): Promise<jose.JWTPayload>;
|
|
43
|
+
/**
|
|
44
|
+
* 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.
|
|
51
|
+
*/
|
|
52
|
+
verifyRefreshToken(token: string): Promise<jose.JWTPayload>;
|
|
24
53
|
}
|
|
25
54
|
//# sourceMappingURL=jwt-issuer.d.ts.map
|
|
@@ -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;IA0B3B,qDAAqD;IAC/C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC;IAS5C,
|
|
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;IA0B3B,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"}
|
|
@@ -53,11 +53,11 @@ export class JWTIssuer {
|
|
|
53
53
|
jwk.alg = 'RS256';
|
|
54
54
|
return { keys: [jwk] };
|
|
55
55
|
}
|
|
56
|
-
/** Issue an RS256 JWT access token. */
|
|
56
|
+
/** Issue an RS256 JWT access token (``typ="access"``). */
|
|
57
57
|
async issueAccessToken(sub, expiresInSeconds = 3600) {
|
|
58
58
|
if (!this.privateKey)
|
|
59
59
|
throw new Error('JWTIssuer not initialized');
|
|
60
|
-
return new jose.SignJWT({ sub })
|
|
60
|
+
return new jose.SignJWT({ sub, typ: 'access' })
|
|
61
61
|
.setProtectedHeader({ alg: 'RS256', kid: this.kid })
|
|
62
62
|
.setIssuer(this.serverName)
|
|
63
63
|
.setAudience(this.serverName)
|
|
@@ -65,7 +65,36 @@ export class JWTIssuer {
|
|
|
65
65
|
.setExpirationTime(`${expiresInSeconds}s`)
|
|
66
66
|
.sign(this.privateKey);
|
|
67
67
|
}
|
|
68
|
-
/**
|
|
68
|
+
/**
|
|
69
|
+
* Issue an RS256 JWT refresh token (``typ="refresh"``).
|
|
70
|
+
*
|
|
71
|
+
* Defaults to a 30-day (2592000s) lifetime so long-running MCP clients can
|
|
72
|
+
* mint fresh access tokens without forcing the user back through the
|
|
73
|
+
* browser PKCE flow every hour. Same key / iss / aud as access tokens; the
|
|
74
|
+
* ``typ`` claim is the only thing distinguishing them, and
|
|
75
|
+
* ``verifyAccessToken`` rejects ``typ="refresh"`` so a refresh token can
|
|
76
|
+
* never be used as an access token at the ``/mcp`` resource.
|
|
77
|
+
*/
|
|
78
|
+
async issueRefreshToken(sub, expiresInSeconds = 2592000) {
|
|
79
|
+
if (!this.privateKey)
|
|
80
|
+
throw new Error('JWTIssuer not initialized');
|
|
81
|
+
return new jose.SignJWT({ sub, typ: 'refresh' })
|
|
82
|
+
.setProtectedHeader({ alg: 'RS256', kid: this.kid })
|
|
83
|
+
.setIssuer(this.serverName)
|
|
84
|
+
.setAudience(this.serverName)
|
|
85
|
+
.setIssuedAt()
|
|
86
|
+
.setExpirationTime(`${expiresInSeconds}s`)
|
|
87
|
+
.sign(this.privateKey);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Verify a JWT access token and return its payload. Throws on failure
|
|
91
|
+
* (bad signature, wrong issuer/audience, expired) — the same jose errors
|
|
92
|
+
* existing callers already catch. Additionally rejects tokens whose
|
|
93
|
+
* ``typ`` claim is ``"refresh"`` (throwing ``jose.errors.JWTClaimValidationFailed``)
|
|
94
|
+
* so a refresh token cannot be replayed as an access token. Tokens with
|
|
95
|
+
* ``typ="access"`` OR a missing ``typ`` claim are accepted (the latter
|
|
96
|
+
* keeps already-issued pre-refresh-support tokens valid).
|
|
97
|
+
*/
|
|
69
98
|
async verifyAccessToken(token) {
|
|
70
99
|
if (!this.publicKey)
|
|
71
100
|
throw new Error('JWTIssuer not initialized');
|
|
@@ -73,6 +102,30 @@ export class JWTIssuer {
|
|
|
73
102
|
issuer: this.serverName,
|
|
74
103
|
audience: this.serverName
|
|
75
104
|
});
|
|
105
|
+
if (payload.typ === 'refresh') {
|
|
106
|
+
throw new jose.errors.JWTClaimValidationFailed('Refresh token cannot be used as an access token', payload, 'typ');
|
|
107
|
+
}
|
|
108
|
+
return payload;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Verify a JWT refresh token and return its payload. Same key / audience /
|
|
112
|
+
* issuer checks as ``verifyAccessToken`` and throws the same jose errors on
|
|
113
|
+
* failure. Additionally asserts ``typ=="refresh"`` (throwing
|
|
114
|
+
* ``jose.errors.JWTClaimValidationFailed`` otherwise) so an access token
|
|
115
|
+
* can never be exchanged at the refresh grant. ``JWTClaimValidationFailed``
|
|
116
|
+
* extends ``jose.errors.JOSEError``, so callers' existing ``catch`` clauses
|
|
117
|
+
* around ``verifyAccessToken`` already catch it.
|
|
118
|
+
*/
|
|
119
|
+
async verifyRefreshToken(token) {
|
|
120
|
+
if (!this.publicKey)
|
|
121
|
+
throw new Error('JWTIssuer not initialized');
|
|
122
|
+
const { payload } = await jose.jwtVerify(token, this.publicKey, {
|
|
123
|
+
issuer: this.serverName,
|
|
124
|
+
audience: this.serverName
|
|
125
|
+
});
|
|
126
|
+
if (payload.typ !== 'refresh') {
|
|
127
|
+
throw new jose.errors.JWTClaimValidationFailed('Token is not a refresh token', payload, 'typ');
|
|
128
|
+
}
|
|
76
129
|
return payload;
|
|
77
130
|
}
|
|
78
131
|
}
|
|
@@ -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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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verify PKCE code challenge.
|
|
3
|
+
* Throws an error if verification fails.
|
|
4
|
+
*
|
|
5
|
+
* @param codeVerifier The PKCE code verifier.
|
|
6
|
+
* @param codeChallenge The stored code challenge.
|
|
7
|
+
* @param method The code challenge method (S256 or plain).
|
|
8
|
+
*/
|
|
9
|
+
export declare function verifyPKCE(codeVerifier: string, codeChallenge: string, method: string): void;
|
|
10
|
+
//# sourceMappingURL=pkce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pkce.d.ts","sourceRoot":"","sources":["../../src/oauth/pkce.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAqB5F"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createHash, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
/**
|
|
3
|
+
* Verify PKCE code challenge.
|
|
4
|
+
* Throws an error if verification fails.
|
|
5
|
+
*
|
|
6
|
+
* @param codeVerifier The PKCE code verifier.
|
|
7
|
+
* @param codeChallenge The stored code challenge.
|
|
8
|
+
* @param method The code challenge method (S256 or plain).
|
|
9
|
+
*/
|
|
10
|
+
export function verifyPKCE(codeVerifier, codeChallenge, method) {
|
|
11
|
+
if (method === 'S256') {
|
|
12
|
+
const digest = createHash('sha256').update(codeVerifier).digest('base64url');
|
|
13
|
+
const expected = Buffer.from(digest);
|
|
14
|
+
const actual = Buffer.from(codeChallenge);
|
|
15
|
+
const isLengthEqual = expected.length === actual.length;
|
|
16
|
+
const compareActual = isLengthEqual ? actual : expected;
|
|
17
|
+
if (!timingSafeEqual(expected, compareActual) || !isLengthEqual) {
|
|
18
|
+
throw new Error('invalid_grant: PKCE verification failed');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
else if (method === 'plain') {
|
|
22
|
+
const expected = Buffer.from(codeVerifier);
|
|
23
|
+
const actual = Buffer.from(codeChallenge);
|
|
24
|
+
const isLengthEqual = expected.length === actual.length;
|
|
25
|
+
const compareActual = isLengthEqual ? actual : expected;
|
|
26
|
+
if (!timingSafeEqual(expected, compareActual) || !isLengthEqual) {
|
|
27
|
+
throw new Error('invalid_grant: PKCE plain verification failed');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
throw new Error('unsupported_challenge_method');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=pkce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pkce.js","sourceRoot":"","sources":["../../src/oauth/pkce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAEzD;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,YAAoB,EAAE,aAAqB,EAAE,MAAc;IACpF,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;QAC5E,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACpC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QACzC,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAA;QACvD,MAAM,aAAa,GAAG,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAA;QACvD,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;QAC5D,CAAC;IACH,CAAC;SAAM,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;QAC1C,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QACzC,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAA;QACvD,MAAM,aAAa,GAAG,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAA;QACvD,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;QAClE,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAA;IACjD,CAAC;AACH,CAAC"}
|
|
@@ -6,28 +6,9 @@
|
|
|
6
6
|
* and uses the Relay Server purely as a UI consent transport.
|
|
7
7
|
*/
|
|
8
8
|
import type { RelayConfigSchema } from '../schema/types.js';
|
|
9
|
+
import { type IOAuthSessionCache } from './cache.js';
|
|
9
10
|
import type { JWTIssuer } from './jwt-issuer.js';
|
|
10
|
-
export
|
|
11
|
-
sessionId: string;
|
|
12
|
-
clientId: string;
|
|
13
|
-
redirectUri: string;
|
|
14
|
-
state: string;
|
|
15
|
-
codeChallenge: string;
|
|
16
|
-
codeChallengeMethod: string;
|
|
17
|
-
/** Serialized CryptoKeyPair for later credential retrieval */
|
|
18
|
-
keyPairJwk: JsonWebKey;
|
|
19
|
-
passphrase: string;
|
|
20
|
-
expiresAt: number;
|
|
21
|
-
}
|
|
22
|
-
export interface IOAuthSessionCache {
|
|
23
|
-
save(session: PreAuthSession): void;
|
|
24
|
-
getAndDelete(sessionId: string): PreAuthSession | null;
|
|
25
|
-
}
|
|
26
|
-
export declare class InMemoryAuthCache implements IOAuthSessionCache {
|
|
27
|
-
private cache;
|
|
28
|
-
save(session: PreAuthSession): void;
|
|
29
|
-
getAndDelete(sessionId: string): PreAuthSession | null;
|
|
30
|
-
}
|
|
11
|
+
export { InMemoryAuthCache, type IOAuthSessionCache, type PreAuthSession } from './cache.js';
|
|
31
12
|
export interface OAuthProviderOptions {
|
|
32
13
|
serverName: string;
|
|
33
14
|
relayBaseUrl: string;
|
|
@@ -59,6 +40,10 @@ export declare class OAuthProvider {
|
|
|
59
40
|
accessToken: string;
|
|
60
41
|
credentials: Record<string, string>;
|
|
61
42
|
}>;
|
|
43
|
+
/**
|
|
44
|
+
* Reconstruct relay session from pre-auth session.
|
|
45
|
+
*/
|
|
46
|
+
private reconstructRelaySession;
|
|
62
47
|
/**
|
|
63
48
|
* Get RFC 8414 Authorization Server Metadata.
|
|
64
49
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/oauth/provider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/oauth/provider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAqB,KAAK,kBAAkB,EAAuB,MAAM,YAAY,CAAA;AAC5F,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAGhD,OAAO,EACL,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,iBAAiB,CAAA;IAC9B,SAAS,EAAE,SAAS,CAAA;IACpB,KAAK,CAAC,EAAE,kBAAkB,CAAA;CAC3B;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,KAAK,CAAoB;gBAErB,OAAO,EAAE,oBAAoB;IAQzC;;OAEG;IACG,uBAAuB,CAC3B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,mBAAmB,SAAS,GAC3B,OAAO,CAAC,MAAM,CAAC;IAqBlB;;;;;;;;OAQG;IACG,YAAY,CAChB,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,GAC/D,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC;IAsBxE;;OAEG;YACW,uBAAuB;IAwBrC;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAYtD"}
|
package/build/oauth/provider.js
CHANGED
|
@@ -5,31 +5,10 @@
|
|
|
5
5
|
* The MCP Server issues JWTs, processes PKCE verification,
|
|
6
6
|
* and uses the Relay Server purely as a UI consent transport.
|
|
7
7
|
*/
|
|
8
|
-
import { createHash, timingSafeEqual } from 'node:crypto';
|
|
9
8
|
import { createSession, pollForResult } from '../relay/client.js';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
save(session) {
|
|
15
|
-
this.cache.set(session.sessionId, session);
|
|
16
|
-
// Cleanup expired entries
|
|
17
|
-
const now = Math.floor(Date.now() / 1000);
|
|
18
|
-
for (const [id, sess] of this.cache) {
|
|
19
|
-
if (sess.expiresAt < now)
|
|
20
|
-
this.cache.delete(id);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
getAndDelete(sessionId) {
|
|
24
|
-
const sess = this.cache.get(sessionId);
|
|
25
|
-
if (!sess)
|
|
26
|
-
return null;
|
|
27
|
-
this.cache.delete(sessionId);
|
|
28
|
-
if (sess.expiresAt < Math.floor(Date.now() / 1000))
|
|
29
|
-
return null;
|
|
30
|
-
return sess;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
9
|
+
import { InMemoryAuthCache } from './cache.js';
|
|
10
|
+
import { verifyPKCE } from './pkce.js';
|
|
11
|
+
export { InMemoryAuthCache } from './cache.js';
|
|
33
12
|
export class OAuthProvider {
|
|
34
13
|
constructor(options) {
|
|
35
14
|
this.serverName = options.serverName;
|
|
@@ -73,37 +52,9 @@ export class OAuthProvider {
|
|
|
73
52
|
if (!preAuth)
|
|
74
53
|
throw new Error('invalid_grant: Expired or invalid code');
|
|
75
54
|
// Verify PKCE
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const actual = Buffer.from(preAuth.codeChallenge);
|
|
80
|
-
const isLengthEqual = expected.length === actual.length;
|
|
81
|
-
const compareActual = isLengthEqual ? actual : expected;
|
|
82
|
-
if (!timingSafeEqual(expected, compareActual) || !isLengthEqual) {
|
|
83
|
-
throw new Error('invalid_grant: PKCE verification failed');
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
else if (preAuth.codeChallengeMethod === 'plain') {
|
|
87
|
-
const expected = Buffer.from(codeVerifier);
|
|
88
|
-
const actual = Buffer.from(preAuth.codeChallenge);
|
|
89
|
-
const isLengthEqual = expected.length === actual.length;
|
|
90
|
-
const compareActual = isLengthEqual ? actual : expected;
|
|
91
|
-
if (!timingSafeEqual(expected, compareActual) || !isLengthEqual) {
|
|
92
|
-
throw new Error('invalid_grant: PKCE plain verification failed');
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
throw new Error('unsupported_challenge_method');
|
|
97
|
-
}
|
|
98
|
-
// Reconstruct key pair to decrypt relay credentials
|
|
99
|
-
const privateKey = await crypto.subtle.importKey('jwk', preAuth.keyPairJwk, { name: 'ECDH', namedCurve: 'P-256' }, true, ['deriveKey', 'deriveBits']);
|
|
100
|
-
const publicKey = await crypto.subtle.importKey('jwk', { ...preAuth.keyPairJwk, d: undefined }, { name: 'ECDH', namedCurve: 'P-256' }, true, []);
|
|
101
|
-
const reconstructedSession = {
|
|
102
|
-
sessionId: preAuth.sessionId,
|
|
103
|
-
keyPair: { privateKey, publicKey },
|
|
104
|
-
passphrase: preAuth.passphrase,
|
|
105
|
-
relayUrl: ''
|
|
106
|
-
};
|
|
55
|
+
verifyPKCE(codeVerifier, preAuth.codeChallenge, preAuth.codeChallengeMethod);
|
|
56
|
+
// Reconstruct relay session
|
|
57
|
+
const reconstructedSession = await this.reconstructRelaySession(preAuth);
|
|
107
58
|
// Poll for credentials (short timeout — form already submitted)
|
|
108
59
|
const credentials = await pollForResult(this.relayBaseUrl, reconstructedSession, 1000, 10_000);
|
|
109
60
|
// Extract unique user_id
|
|
@@ -114,6 +65,20 @@ export class OAuthProvider {
|
|
|
114
65
|
const accessToken = await this.jwtIssuer.issueAccessToken(userId);
|
|
115
66
|
return { accessToken, credentials };
|
|
116
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Reconstruct relay session from pre-auth session.
|
|
70
|
+
*/
|
|
71
|
+
async reconstructRelaySession(preAuth) {
|
|
72
|
+
// Reconstruct key pair to decrypt relay credentials
|
|
73
|
+
const privateKey = await crypto.subtle.importKey('jwk', preAuth.keyPairJwk, { name: 'ECDH', namedCurve: 'P-256' }, true, ['deriveKey', 'deriveBits']);
|
|
74
|
+
const publicKey = await crypto.subtle.importKey('jwk', { ...preAuth.keyPairJwk, d: undefined }, { name: 'ECDH', namedCurve: 'P-256' }, true, []);
|
|
75
|
+
return {
|
|
76
|
+
sessionId: preAuth.sessionId,
|
|
77
|
+
keyPair: { privateKey, publicKey },
|
|
78
|
+
passphrase: preAuth.passphrase,
|
|
79
|
+
relayUrl: ''
|
|
80
|
+
};
|
|
81
|
+
}
|
|
117
82
|
/**
|
|
118
83
|
* Get RFC 8414 Authorization Server Metadata.
|
|
119
84
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/oauth/provider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/oauth/provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/relay/browser.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/relay/browser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAqDH;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAoClE"}
|
package/build/relay/browser.js
CHANGED
|
@@ -23,17 +23,12 @@ async function isWsl() {
|
|
|
23
23
|
function encodePowerShellCommand(command) {
|
|
24
24
|
return Buffer.from(command, 'utf16le').toString('base64');
|
|
25
25
|
}
|
|
26
|
-
async function openInPowerShell(url
|
|
26
|
+
async function openInPowerShell(url) {
|
|
27
27
|
try {
|
|
28
|
-
const
|
|
28
|
+
const base64Url = Buffer.from(url, 'utf8').toString('base64');
|
|
29
|
+
const command = `$url = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${base64Url}')); Start-Process $url`;
|
|
29
30
|
const encodedCommand = encodePowerShellCommand(command);
|
|
30
|
-
await execFileAsync('powershell.exe', ['-NoProfile', '-EncodedCommand', encodedCommand]
|
|
31
|
-
env: {
|
|
32
|
-
...process.env,
|
|
33
|
-
...extraEnv,
|
|
34
|
-
MCP_BROWSER_URL: url
|
|
35
|
-
}
|
|
36
|
-
});
|
|
31
|
+
await execFileAsync('powershell.exe', ['-NoProfile', '-EncodedCommand', encodedCommand]);
|
|
37
32
|
return true;
|
|
38
33
|
}
|
|
39
34
|
catch {
|
|
@@ -50,7 +45,7 @@ async function openInWsl(url) {
|
|
|
50
45
|
/* fall through */
|
|
51
46
|
}
|
|
52
47
|
// Fallback to powershell.exe -EncodedCommand
|
|
53
|
-
return openInPowerShell(url
|
|
48
|
+
return openInPowerShell(url);
|
|
54
49
|
}
|
|
55
50
|
/**
|
|
56
51
|
* Try to open URL in default browser. Returns true if likely succeeded.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/relay/browser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAErC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAA;AAEzC,4EAA4E;AAC5E,+EAA+E;AAC/E,kCAAkC;AAClC,MAAM,6BAA6B,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA;AACnD,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAkB,CAAA;AAEpD,KAAK,UAAU,KAAK;IAClB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,CAAA;QACxD,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAA;QACnC,OAAO,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,SAAS,uBAAuB,CAAC,OAAe;IAC9C,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC3D,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,GAAW,
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/relay/browser.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-file.d.ts","sourceRoot":"","sources":["../../src/storage/config-file.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config-file.d.ts","sourceRoot":"","sources":["../../src/storage/config-file.ts"],"names":[],"mappings":"AAqDA,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAEvD;AA2BD,wBAAgB,uBAAuB,IAAI,IAAI,CAG9C;AAkFD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAIzC;AAED,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,CAG3F;AAED,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAInG;AAED,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYpE;AAED;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,oBAAoB,CAAA;AAEnD;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIzE;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAGrD;AAED,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMtE;AAED,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6ClF"}
|