@nocoo/base-mcp 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +315 -3
  2. package/dist/auth/index.d.ts +1 -0
  3. package/dist/auth/index.d.ts.map +1 -1
  4. package/dist/auth/index.js +2 -0
  5. package/dist/auth/index.js.map +1 -1
  6. package/dist/auth/oauth/constants.d.ts +7 -0
  7. package/dist/auth/oauth/constants.d.ts.map +1 -0
  8. package/dist/auth/oauth/constants.js +10 -0
  9. package/dist/auth/oauth/constants.js.map +1 -0
  10. package/dist/auth/oauth/handlers/authorize.d.ts +12 -0
  11. package/dist/auth/oauth/handlers/authorize.d.ts.map +1 -0
  12. package/dist/auth/oauth/handlers/authorize.js +89 -0
  13. package/dist/auth/oauth/handlers/authorize.js.map +1 -0
  14. package/dist/auth/oauth/handlers/callback.d.ts +13 -0
  15. package/dist/auth/oauth/handlers/callback.d.ts.map +1 -0
  16. package/dist/auth/oauth/handlers/callback.js +72 -0
  17. package/dist/auth/oauth/handlers/callback.js.map +1 -0
  18. package/dist/auth/oauth/handlers/index.d.ts +5 -0
  19. package/dist/auth/oauth/handlers/index.d.ts.map +1 -0
  20. package/dist/auth/oauth/handlers/index.js +8 -0
  21. package/dist/auth/oauth/handlers/index.js.map +1 -0
  22. package/dist/auth/oauth/handlers/register.d.ts +9 -0
  23. package/dist/auth/oauth/handlers/register.d.ts.map +1 -0
  24. package/dist/auth/oauth/handlers/register.js +62 -0
  25. package/dist/auth/oauth/handlers/register.js.map +1 -0
  26. package/dist/auth/oauth/handlers/token.d.ts +10 -0
  27. package/dist/auth/oauth/handlers/token.d.ts.map +1 -0
  28. package/dist/auth/oauth/handlers/token.js +139 -0
  29. package/dist/auth/oauth/handlers/token.js.map +1 -0
  30. package/dist/auth/oauth/index.d.ts +4 -0
  31. package/dist/auth/oauth/index.d.ts.map +1 -0
  32. package/dist/auth/oauth/index.js +8 -0
  33. package/dist/auth/oauth/index.js.map +1 -0
  34. package/dist/auth/oauth/testing/index.d.ts +2 -0
  35. package/dist/auth/oauth/testing/index.d.ts.map +1 -0
  36. package/dist/auth/oauth/testing/index.js +5 -0
  37. package/dist/auth/oauth/testing/index.js.map +1 -0
  38. package/dist/auth/oauth/testing/mock-stores.d.ts +36 -0
  39. package/dist/auth/oauth/testing/mock-stores.d.ts.map +1 -0
  40. package/dist/auth/oauth/testing/mock-stores.js +218 -0
  41. package/dist/auth/oauth/testing/mock-stores.js.map +1 -0
  42. package/dist/auth/oauth/types.d.ts +187 -0
  43. package/dist/auth/oauth/types.d.ts.map +1 -0
  44. package/dist/auth/oauth/types.js +5 -0
  45. package/dist/auth/oauth/types.js.map +1 -0
  46. package/package.json +12 -10
@@ -0,0 +1,62 @@
1
+ // ---------------------------------------------------------------------------
2
+ // OAuth Register Handler — Dynamic Client Registration (RFC 7591)
3
+ // ---------------------------------------------------------------------------
4
+ import { isLoopbackRedirectUri } from "../../pkce.js";
5
+ /**
6
+ * Handle dynamic client registration.
7
+ *
8
+ * Per RFC 7591, clients can register themselves to obtain a client_id.
9
+ * Only loopback redirect URIs are allowed (native CLI apps).
10
+ */
11
+ export async function handleRegister(ctx, input) {
12
+ // Validate client_name
13
+ if (!input.client_name || typeof input.client_name !== "string") {
14
+ return {
15
+ success: false,
16
+ status: 400,
17
+ error: "client_name is required",
18
+ };
19
+ }
20
+ if (input.client_name.length > 255) {
21
+ return {
22
+ success: false,
23
+ status: 400,
24
+ error: "client_name must be 255 characters or less",
25
+ };
26
+ }
27
+ // Validate redirect_uris
28
+ if (!Array.isArray(input.redirect_uris) || input.redirect_uris.length === 0) {
29
+ return {
30
+ success: false,
31
+ status: 400,
32
+ error: "redirect_uris must be a non-empty array",
33
+ };
34
+ }
35
+ for (const uri of input.redirect_uris) {
36
+ if (!isLoopbackRedirectUri(uri)) {
37
+ return {
38
+ success: false,
39
+ status: 400,
40
+ error: `Invalid redirect_uri: ${uri}. Only loopback addresses (localhost, 127.0.0.1, [::1]) are allowed`,
41
+ };
42
+ }
43
+ }
44
+ // Create client
45
+ const client = await ctx.clients.create({
46
+ client_name: input.client_name,
47
+ redirect_uris: input.redirect_uris,
48
+ grant_types: input.grant_types ?? ["authorization_code"],
49
+ });
50
+ return {
51
+ success: true,
52
+ status: 201,
53
+ body: {
54
+ client_id: client.client_id,
55
+ client_name: client.client_name,
56
+ redirect_uris: JSON.parse(client.redirect_uris),
57
+ grant_types: JSON.parse(client.grant_types),
58
+ token_endpoint_auth_method: "none",
59
+ },
60
+ };
61
+ }
62
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../../../src/auth/oauth/handlers/register.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,kEAAkE;AAClE,8EAA8E;AAE9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAGtD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAiB,EACjB,KAAoB;IAEpB,uBAAuB;IACvB,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;QAChE,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,GAAG;YACX,KAAK,EAAE,yBAAyB;SACjC,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QACnC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,GAAG;YACX,KAAK,EAAE,4CAA4C;SACpD,CAAC;IACJ,CAAC;IAED,yBAAyB;IACzB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5E,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,GAAG;YACX,KAAK,EAAE,yCAAyC;SACjD,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;QACtC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,GAAG;gBACX,KAAK,EAAE,yBAAyB,GAAG,qEAAqE;aACzG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,gBAAgB;IAChB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;QACtC,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,CAAC,oBAAoB,CAAC;KACzD,CAAC,CAAC;IAEH,OAAO;QACL,OAAO,EAAE,IAAI;QACb,MAAM,EAAE,GAAG;QACX,IAAI,EAAE;YACJ,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC;YAC/C,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC;YAC3C,0BAA0B,EAAE,MAAM;SACnC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { OAuthContext, TokenInput, TokenResult } from "../types.js";
2
+ /**
3
+ * Handle OAuth token request.
4
+ *
5
+ * Supports two grant types:
6
+ * - authorization_code: Exchange code for tokens
7
+ * - refresh_token: Refresh access token using refresh token
8
+ */
9
+ export declare function handleToken(ctx: OAuthContext, input: TokenInput): Promise<TokenResult>;
10
+ //# sourceMappingURL=token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../../../src/auth/oauth/handlers/token.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGzE;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,YAAY,EACjB,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,WAAW,CAAC,CAmBtB"}
@@ -0,0 +1,139 @@
1
+ // ---------------------------------------------------------------------------
2
+ // OAuth Token Handler — Token Exchange Endpoint
3
+ // ---------------------------------------------------------------------------
4
+ import { verifyPkceS256 } from "../../pkce.js";
5
+ import { generateToken, hashToken, tokenPreview } from "../../token.js";
6
+ import { ACCESS_TOKEN_TTL, REFRESH_TOKEN_TTL } from "../constants.js";
7
+ /**
8
+ * Handle OAuth token request.
9
+ *
10
+ * Supports two grant types:
11
+ * - authorization_code: Exchange code for tokens
12
+ * - refresh_token: Refresh access token using refresh token
13
+ */
14
+ export async function handleToken(ctx, input) {
15
+ const { grant_type } = input;
16
+ if (!grant_type) {
17
+ return oauthError("invalid_request", "grant_type is required");
18
+ }
19
+ if (grant_type === "authorization_code") {
20
+ return handleAuthorizationCode(ctx, input);
21
+ }
22
+ if (grant_type === "refresh_token") {
23
+ return handleRefreshToken(ctx, input);
24
+ }
25
+ return oauthError("unsupported_grant_type", `Unsupported grant_type: ${grant_type}`);
26
+ }
27
+ // ---------------------------------------------------------------------------
28
+ // Authorization Code Exchange
29
+ // ---------------------------------------------------------------------------
30
+ async function handleAuthorizationCode(ctx, input) {
31
+ const { code, redirect_uri, client_id, code_verifier } = input;
32
+ if (!code || !redirect_uri || !client_id || !code_verifier) {
33
+ return oauthError("invalid_request", "Missing required fields: code, redirect_uri, client_id, code_verifier");
34
+ }
35
+ // Step 1: Look up auth code
36
+ const authCode = await ctx.authCodes.findByCode(code);
37
+ if (!authCode) {
38
+ return oauthError("invalid_grant", "Authorization code is invalid, expired, or already consumed");
39
+ }
40
+ // Step 2: Validate client_id matches
41
+ if (authCode.client_id !== client_id) {
42
+ return oauthError("invalid_grant", "client_id does not match");
43
+ }
44
+ // Step 3: Validate redirect_uri matches
45
+ if (authCode.redirect_uri !== redirect_uri) {
46
+ return oauthError("invalid_grant", "redirect_uri does not match");
47
+ }
48
+ // Step 4: Verify PKCE S256
49
+ const pkceValid = await verifyPkceS256(code_verifier, authCode.code_challenge);
50
+ if (!pkceValid) {
51
+ return oauthError("invalid_grant", "PKCE verification failed");
52
+ }
53
+ // Step 5: Atomically consume the code
54
+ const consumed = await ctx.authCodes.consume(code);
55
+ if (!consumed) {
56
+ return oauthError("invalid_grant", "Authorization code already consumed (race condition)");
57
+ }
58
+ // Validate user_email is set
59
+ const userEmail = authCode.user_email;
60
+ if (!userEmail) {
61
+ return oauthError("server_error", "Authorization code missing user email");
62
+ }
63
+ // Step 6: Token rotation — revoke existing tokens
64
+ await ctx.tokens.revokeByClientAndUser(client_id, userEmail);
65
+ // Step 7: Issue new token pair
66
+ return issueTokenPair(ctx, client_id, userEmail, authCode.scope);
67
+ }
68
+ // ---------------------------------------------------------------------------
69
+ // Refresh Token Exchange
70
+ // ---------------------------------------------------------------------------
71
+ async function handleRefreshToken(ctx, input) {
72
+ const { refresh_token, client_id } = input;
73
+ if (!refresh_token || !client_id) {
74
+ return oauthError("invalid_request", "Missing required fields: refresh_token, client_id");
75
+ }
76
+ // Look up token by refresh hash
77
+ const refreshHash = await hashToken(refresh_token);
78
+ const existingToken = await ctx.tokens.findByRefreshHash(refreshHash);
79
+ if (!existingToken) {
80
+ return oauthError("invalid_grant", "Refresh token is invalid, expired, or revoked");
81
+ }
82
+ // Verify client_id matches
83
+ if (existingToken.client_id !== client_id) {
84
+ return oauthError("invalid_grant", "client_id does not match");
85
+ }
86
+ // Token rotation — revoke all tokens for this client
87
+ await ctx.tokens.revokeByClientAndUser(client_id, existingToken.user_email);
88
+ // Issue new token pair
89
+ return issueTokenPair(ctx, client_id, existingToken.user_email, existingToken.scope, existingToken.client_name ?? undefined);
90
+ }
91
+ // ---------------------------------------------------------------------------
92
+ // Helpers
93
+ // ---------------------------------------------------------------------------
94
+ async function issueTokenPair(ctx, clientId, userEmail, scope, clientName) {
95
+ // Generate tokens with prefix
96
+ const accessToken = `${ctx.tokenPrefix}_at_${generateToken(24)}`;
97
+ const refreshToken = `${ctx.tokenPrefix}_rt_${generateToken(24)}`;
98
+ const accessHash = await hashToken(accessToken);
99
+ const refreshHash = await hashToken(refreshToken);
100
+ const now = Math.floor(Date.now() / 1000);
101
+ // Look up client name if not provided
102
+ let resolvedClientName = clientName;
103
+ if (!resolvedClientName) {
104
+ const client = await ctx.clients.findByClientId(clientId);
105
+ resolvedClientName = client?.client_name;
106
+ }
107
+ // Store token
108
+ await ctx.tokens.create({
109
+ access_token_hash: accessHash,
110
+ access_token_preview: tokenPreview(accessToken),
111
+ refresh_token_hash: refreshHash,
112
+ client_id: clientId,
113
+ user_email: userEmail,
114
+ scope,
115
+ client_name: resolvedClientName,
116
+ expires_at: now + ACCESS_TOKEN_TTL,
117
+ refresh_expires_at: now + REFRESH_TOKEN_TTL,
118
+ });
119
+ return {
120
+ success: true,
121
+ status: 200,
122
+ body: {
123
+ access_token: accessToken,
124
+ token_type: "Bearer",
125
+ expires_in: ACCESS_TOKEN_TTL,
126
+ refresh_token: refreshToken,
127
+ scope,
128
+ },
129
+ };
130
+ }
131
+ function oauthError(error, errorDescription) {
132
+ return {
133
+ success: false,
134
+ status: 400,
135
+ error,
136
+ error_description: errorDescription,
137
+ };
138
+ }
139
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../../../src/auth/oauth/handlers/token.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export type { McpClient, McpAuthCode, McpToken, ClientStore, AuthCodeStore, OAuthTokenStore, AuthContext, OAuthContext, RegisterResult, AuthorizeResult, CallbackResult, TokenResult, RevokeResult, RegisterInput, AuthorizeInput, CallbackInput, TokenInput, } from "./types.js";
2
+ export { AUTH_CODE_TTL, ACCESS_TOKEN_TTL, REFRESH_TOKEN_TTL, } from "./constants.js";
3
+ export { handleRegister, handleAuthorize, handleCallback, handleToken, } from "./handlers/index.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/oauth/index.ts"],"names":[],"mappings":"AAKA,YAAY,EACV,SAAS,EACT,WAAW,EACX,QAAQ,EACR,WAAW,EACX,aAAa,EACb,eAAe,EACf,WAAW,EACX,YAAY,EACZ,cAAc,EACd,eAAe,EACf,cAAc,EACd,WAAW,EACX,YAAY,EACZ,aAAa,EACb,cAAc,EACd,aAAa,EACb,UAAU,GACX,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,cAAc,EACd,eAAe,EACf,cAAc,EACd,WAAW,GACZ,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,8 @@
1
+ // ---------------------------------------------------------------------------
2
+ // OAuth Module Index — Export all OAuth types and handlers
3
+ // ---------------------------------------------------------------------------
4
+ // Constants
5
+ export { AUTH_CODE_TTL, ACCESS_TOKEN_TTL, REFRESH_TOKEN_TTL, } from "./constants.js";
6
+ // Handlers
7
+ export { handleRegister, handleAuthorize, handleCallback, handleToken, } from "./handlers/index.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/auth/oauth/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,2DAA2D;AAC3D,8EAA8E;AAuB9E,YAAY;AACZ,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAExB,WAAW;AACX,OAAO,EACL,cAAc,EACd,eAAe,EACf,cAAc,EACd,WAAW,GACZ,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { createMockClientStore, createMockAuthCodeStore, createMockTokenStore, createMockAuthContext, createMockOAuthContext, type MockAuthContextOptions, type CreateMockOAuthContextOptions, } from "./mock-stores.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/auth/oauth/testing/index.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,6BAA6B,GACnC,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,5 @@
1
+ // ---------------------------------------------------------------------------
2
+ // OAuth Testing Module Index
3
+ // ---------------------------------------------------------------------------
4
+ export { createMockClientStore, createMockAuthCodeStore, createMockTokenStore, createMockAuthContext, createMockOAuthContext, } from "./mock-stores.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/auth/oauth/testing/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,6BAA6B;AAC7B,8EAA8E;AAE9E,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,GAGvB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,36 @@
1
+ import type { ClientStore, AuthCodeStore, OAuthTokenStore, AuthContext, OAuthContext, McpClient, McpAuthCode, McpToken } from "../types.js";
2
+ export declare function createMockClientStore(): ClientStore & {
3
+ clients: Map<string, McpClient>;
4
+ reset(): void;
5
+ };
6
+ export declare function createMockAuthCodeStore(): AuthCodeStore & {
7
+ sessions: Map<string, McpAuthCode>;
8
+ codes: Map<string, McpAuthCode>;
9
+ reset(): void;
10
+ };
11
+ export declare function createMockTokenStore(): OAuthTokenStore & {
12
+ tokens: Map<string, McpToken>;
13
+ reset(): void;
14
+ };
15
+ export interface MockAuthContextOptions {
16
+ authenticated?: boolean;
17
+ email?: string | null;
18
+ allowedEmails?: string[];
19
+ }
20
+ export declare function createMockAuthContext(options?: MockAuthContextOptions): AuthContext & {
21
+ setAuthenticated(value: boolean): void;
22
+ setEmail(email: string | null): void;
23
+ };
24
+ export interface CreateMockOAuthContextOptions {
25
+ issuer?: string;
26
+ tokenPrefix?: string;
27
+ auth?: MockAuthContextOptions;
28
+ }
29
+ export declare function createMockOAuthContext(options?: CreateMockOAuthContextOptions): OAuthContext & {
30
+ clients: ReturnType<typeof createMockClientStore>;
31
+ authCodes: ReturnType<typeof createMockAuthCodeStore>;
32
+ tokens: ReturnType<typeof createMockTokenStore>;
33
+ auth: ReturnType<typeof createMockAuthContext>;
34
+ reset(): void;
35
+ };
36
+ //# sourceMappingURL=mock-stores.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-stores.d.ts","sourceRoot":"","sources":["../../../../src/auth/oauth/testing/mock-stores.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACb,eAAe,EACf,WAAW,EACX,YAAY,EACZ,SAAS,EACT,WAAW,EACX,QAAQ,EACT,MAAM,aAAa,CAAC;AAMrB,wBAAgB,qBAAqB,IAAI,WAAW,GAAG;IACrD,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAChC,KAAK,IAAI,IAAI,CAAC;CACf,CAmCA;AAMD,wBAAgB,uBAAuB,IAAI,aAAa,GAAG;IACzD,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACnC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAChC,KAAK,IAAI,IAAI,CAAC;CACf,CAoEA;AAMD,wBAAgB,oBAAoB,IAAI,eAAe,GAAG;IACxD,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC9B,KAAK,IAAI,IAAI,CAAC;CACf,CAmEA;AAMD,MAAM,WAAW,sBAAsB;IACrC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,wBAAgB,qBAAqB,CACnC,OAAO,GAAE,sBAA2B,GACnC,WAAW,GAAG;IAAE,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAA;CAAE,CA2BhG;AAMD,MAAM,WAAW,6BAA6B;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,sBAAsB,CAAC;CAC/B;AAED,wBAAgB,sBAAsB,CACpC,OAAO,GAAE,6BAAkC,GAC1C,YAAY,GAAG;IAChB,OAAO,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;IAClD,SAAS,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;IACtD,MAAM,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;IAChD,IAAI,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;IAC/C,KAAK,IAAI,IAAI,CAAC;CACf,CAoBA"}
@@ -0,0 +1,218 @@
1
+ // ---------------------------------------------------------------------------
2
+ // OAuth Testing Utilities — Mock stores for unit testing
3
+ // ---------------------------------------------------------------------------
4
+ // ---------------------------------------------------------------------------
5
+ // Mock Client Store
6
+ // ---------------------------------------------------------------------------
7
+ export function createMockClientStore() {
8
+ const clients = new Map();
9
+ let counter = 0;
10
+ return {
11
+ clients,
12
+ reset() {
13
+ clients.clear();
14
+ counter = 0;
15
+ },
16
+ async create(input) {
17
+ counter++;
18
+ const id = `client_${counter}`;
19
+ const clientId = `test_mcp_${Date.now()}_${counter}`;
20
+ const now = Math.floor(Date.now() / 1000);
21
+ const client = {
22
+ id,
23
+ client_id: clientId,
24
+ client_name: input.client_name,
25
+ redirect_uris: JSON.stringify(input.redirect_uris),
26
+ grant_types: JSON.stringify(input.grant_types),
27
+ created_at: now,
28
+ };
29
+ clients.set(clientId, client);
30
+ return client;
31
+ },
32
+ async findByClientId(clientId) {
33
+ return clients.get(clientId) ?? null;
34
+ },
35
+ };
36
+ }
37
+ // ---------------------------------------------------------------------------
38
+ // Mock Auth Code Store
39
+ // ---------------------------------------------------------------------------
40
+ export function createMockAuthCodeStore() {
41
+ const sessions = new Map();
42
+ const codes = new Map();
43
+ return {
44
+ sessions,
45
+ codes,
46
+ reset() {
47
+ sessions.clear();
48
+ codes.clear();
49
+ },
50
+ async createSession(input) {
51
+ const session = {
52
+ state: input.state,
53
+ client_id: input.client_id,
54
+ redirect_uri: input.redirect_uri,
55
+ code_challenge: input.code_challenge,
56
+ code_challenge_method: input.code_challenge_method,
57
+ scope: input.scope,
58
+ code: null,
59
+ user_email: null,
60
+ consumed: 0,
61
+ expires_at: input.expires_at,
62
+ };
63
+ sessions.set(input.state, session);
64
+ },
65
+ async findByState(state) {
66
+ const session = sessions.get(state);
67
+ if (!session)
68
+ return null;
69
+ const now = Math.floor(Date.now() / 1000);
70
+ if (session.expires_at < now)
71
+ return null;
72
+ return session;
73
+ },
74
+ async upgrade(state, code, userEmail, expiresAt) {
75
+ const session = sessions.get(state);
76
+ if (!session)
77
+ return false;
78
+ if (session.code !== null)
79
+ return false;
80
+ const now = Math.floor(Date.now() / 1000);
81
+ if (session.expires_at < now)
82
+ return false;
83
+ session.code = code;
84
+ session.user_email = userEmail;
85
+ session.expires_at = expiresAt;
86
+ codes.set(code, session);
87
+ return true;
88
+ },
89
+ async findByCode(code) {
90
+ const session = codes.get(code);
91
+ if (!session)
92
+ return null;
93
+ if (session.consumed !== 0)
94
+ return null;
95
+ const now = Math.floor(Date.now() / 1000);
96
+ if (session.expires_at < now)
97
+ return null;
98
+ return session;
99
+ },
100
+ async consume(code) {
101
+ const session = codes.get(code);
102
+ if (!session)
103
+ return false;
104
+ if (session.consumed !== 0)
105
+ return false;
106
+ session.consumed = 1;
107
+ return true;
108
+ },
109
+ };
110
+ }
111
+ // ---------------------------------------------------------------------------
112
+ // Mock Token Store
113
+ // ---------------------------------------------------------------------------
114
+ export function createMockTokenStore() {
115
+ const tokens = new Map();
116
+ let counter = 0;
117
+ return {
118
+ tokens,
119
+ reset() {
120
+ tokens.clear();
121
+ counter = 0;
122
+ },
123
+ async create(input) {
124
+ counter++;
125
+ const id = `token_${counter}`;
126
+ const now = Math.floor(Date.now() / 1000);
127
+ const token = {
128
+ id,
129
+ access_token_hash: input.access_token_hash,
130
+ access_token_preview: input.access_token_preview,
131
+ refresh_token_hash: input.refresh_token_hash,
132
+ client_id: input.client_id,
133
+ user_email: input.user_email,
134
+ client_name: input.client_name ?? null,
135
+ scope: input.scope,
136
+ revoked: 0,
137
+ revoked_at: null,
138
+ expires_at: input.expires_at,
139
+ refresh_expires_at: input.refresh_expires_at,
140
+ last_used_at: null,
141
+ created_at: now,
142
+ };
143
+ tokens.set(id, token);
144
+ return token;
145
+ },
146
+ async findByRefreshHash(refreshHash) {
147
+ for (const token of tokens.values()) {
148
+ if (token.refresh_token_hash === refreshHash) {
149
+ if (token.revoked !== 0)
150
+ return null;
151
+ const now = Math.floor(Date.now() / 1000);
152
+ if (token.refresh_expires_at < now)
153
+ return null;
154
+ return token;
155
+ }
156
+ }
157
+ return null;
158
+ },
159
+ async revokeByClientAndUser(clientId, userEmail) {
160
+ let count = 0;
161
+ const now = Math.floor(Date.now() / 1000);
162
+ for (const token of tokens.values()) {
163
+ if (token.client_id === clientId &&
164
+ token.user_email === userEmail &&
165
+ token.revoked === 0) {
166
+ token.revoked = 1;
167
+ token.revoked_at = now;
168
+ count++;
169
+ }
170
+ }
171
+ return count;
172
+ },
173
+ };
174
+ }
175
+ export function createMockAuthContext(options = {}) {
176
+ let authenticated = options.authenticated ?? false;
177
+ let email = options.email ?? null;
178
+ const allowedEmails = options.allowedEmails ?? [];
179
+ return {
180
+ setAuthenticated(value) {
181
+ authenticated = value;
182
+ },
183
+ setEmail(value) {
184
+ email = value;
185
+ },
186
+ async isAuthenticated() {
187
+ return authenticated;
188
+ },
189
+ async getEmail() {
190
+ return email;
191
+ },
192
+ isEmailAllowed(emailToCheck) {
193
+ if (allowedEmails.length === 0)
194
+ return true; // No whitelist = allow all
195
+ return allowedEmails.includes(emailToCheck);
196
+ },
197
+ };
198
+ }
199
+ export function createMockOAuthContext(options = {}) {
200
+ const clients = createMockClientStore();
201
+ const authCodes = createMockAuthCodeStore();
202
+ const tokens = createMockTokenStore();
203
+ const auth = createMockAuthContext(options.auth);
204
+ return {
205
+ clients,
206
+ authCodes,
207
+ tokens,
208
+ auth,
209
+ issuer: options.issuer ?? "https://test.example.com",
210
+ tokenPrefix: options.tokenPrefix ?? "test",
211
+ reset() {
212
+ clients.reset();
213
+ authCodes.reset();
214
+ tokens.reset();
215
+ },
216
+ };
217
+ }
218
+ //# sourceMappingURL=mock-stores.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-stores.js","sourceRoot":"","sources":["../../../../src/auth/oauth/testing/mock-stores.ts"],"names":[],"mappings":"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"}