@vinkius-core/mcp-fusion-api-key 1.0.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.
@@ -0,0 +1,108 @@
1
+ /**
2
+ * API Key Manager — Validation & Hashing
3
+ *
4
+ * Validates API keys using multiple strategies:
5
+ * - Static key set (in-memory)
6
+ * - SHA-256 hash comparison (for safe storage)
7
+ * - Async validator function (database lookup)
8
+ *
9
+ * All comparisons use timing-safe operations to prevent timing attacks.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { ApiKeyManager } from '@vinkius-core/mcp-fusion-api-key';
14
+ *
15
+ * // Static keys
16
+ * const manager = new ApiKeyManager({
17
+ * keys: ['sk_live_abc123', 'sk_live_def456'],
18
+ * });
19
+ *
20
+ * // Hash-based (for DB storage)
21
+ * const hash = ApiKeyManager.hashKey('sk_live_abc123');
22
+ * const manager = new ApiKeyManager({ hashedKeys: [hash] });
23
+ *
24
+ * // Async validator (DB lookup)
25
+ * const manager = new ApiKeyManager({
26
+ * validator: async (key) => {
27
+ * const record = await db.apiKeys.findByKey(key);
28
+ * return record ? { valid: true, metadata: { userId: record.userId } } : { valid: false };
29
+ * },
30
+ * });
31
+ * ```
32
+ */
33
+ export interface ApiKeyManagerConfig {
34
+ /** Static set of valid API keys (plaintext). */
35
+ readonly keys?: readonly string[];
36
+ /** Set of pre-hashed keys (SHA-256 hex). Use `ApiKeyManager.hashKey()` to generate. */
37
+ readonly hashedKeys?: readonly string[];
38
+ /**
39
+ * Async validator function for dynamic key lookup (e.g., database).
40
+ * Takes priority over `keys` and `hashedKeys` when provided.
41
+ */
42
+ readonly validator?: (key: string) => Promise<ApiKeyValidationResult>;
43
+ /** Prefix required on API keys (e.g., 'sk_live_'). Optional. */
44
+ readonly prefix?: string;
45
+ /** Minimum key length. Default: 16 */
46
+ readonly minLength?: number;
47
+ }
48
+ export interface ApiKeyValidationResult {
49
+ /** Whether the key is valid. */
50
+ readonly valid: boolean;
51
+ /** Optional metadata about the key owner (userId, scopes, etc.). */
52
+ readonly metadata?: Record<string, unknown>;
53
+ /** Reason for rejection (only when valid is false). */
54
+ readonly reason?: string;
55
+ }
56
+ export declare class ApiKeyManager {
57
+ private readonly _config;
58
+ private readonly _minLength;
59
+ private readonly _keyHashes;
60
+ constructor(config: ApiKeyManagerConfig);
61
+ /**
62
+ * Validate an API key.
63
+ *
64
+ * @param key - Raw API key string
65
+ * @returns Validation result with optional metadata
66
+ */
67
+ validate(key: string): Promise<ApiKeyValidationResult>;
68
+ /**
69
+ * Quick boolean check without detailed result.
70
+ */
71
+ isValid(key: string): Promise<boolean>;
72
+ /**
73
+ * Hash an API key using SHA-256 for safe storage.
74
+ *
75
+ * @param rawKey - Plaintext API key
76
+ * @returns Hex-encoded SHA-256 hash
77
+ */
78
+ static hashKey(rawKey: string): string;
79
+ /**
80
+ * Compare a raw key against a stored hash using timing-safe comparison.
81
+ *
82
+ * @param rawKey - Plaintext API key
83
+ * @param storedHash - SHA-256 hex hash to compare against
84
+ * @returns Whether the key matches the hash
85
+ */
86
+ static matchKey(rawKey: string, storedHash: string): boolean;
87
+ /**
88
+ * Generate a random API key with optional prefix.
89
+ *
90
+ * @param options - Generation options
91
+ * @returns Random API key string
92
+ */
93
+ static generateKey(options?: {
94
+ prefix?: string;
95
+ length?: number;
96
+ }): string;
97
+ /**
98
+ * Check if a hash exists in the pre-computed set using timing-safe comparison.
99
+ * @internal
100
+ */
101
+ private _isHashInSet;
102
+ /**
103
+ * Timing-safe string comparison to prevent timing attacks.
104
+ * @internal
105
+ */
106
+ private static _timingSafeCompare;
107
+ }
108
+ //# sourceMappingURL=ApiKeyManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiKeyManager.d.ts","sourceRoot":"","sources":["../src/ApiKeyManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAQH,MAAM,WAAW,mBAAmB;IAChC,gDAAgD;IAChD,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAElC,uFAAuF;IACvF,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAExC;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAEtE,gEAAgE;IAChE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAEzB,sCAAsC;IACtC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,sBAAsB;IACnC,gCAAgC;IAChC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAExB,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE5C,uDAAuD;IACvD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC5B;AAMD,qBAAa,aAAa;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;gBAE7B,MAAM,EAAE,mBAAmB;IAuBvC;;;;;OAKG;IACG,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IA4B5D;;OAEG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAO5C;;;;;OAKG;IACH,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAItC;;;;;;OAMG;IACH,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO;IAK5D;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IAS1E;;;OAGG;IACH,OAAO,CAAC,YAAY;IASpB;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;CAQpC"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * API Key Manager — Validation & Hashing
3
+ *
4
+ * Validates API keys using multiple strategies:
5
+ * - Static key set (in-memory)
6
+ * - SHA-256 hash comparison (for safe storage)
7
+ * - Async validator function (database lookup)
8
+ *
9
+ * All comparisons use timing-safe operations to prevent timing attacks.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { ApiKeyManager } from '@vinkius-core/mcp-fusion-api-key';
14
+ *
15
+ * // Static keys
16
+ * const manager = new ApiKeyManager({
17
+ * keys: ['sk_live_abc123', 'sk_live_def456'],
18
+ * });
19
+ *
20
+ * // Hash-based (for DB storage)
21
+ * const hash = ApiKeyManager.hashKey('sk_live_abc123');
22
+ * const manager = new ApiKeyManager({ hashedKeys: [hash] });
23
+ *
24
+ * // Async validator (DB lookup)
25
+ * const manager = new ApiKeyManager({
26
+ * validator: async (key) => {
27
+ * const record = await db.apiKeys.findByKey(key);
28
+ * return record ? { valid: true, metadata: { userId: record.userId } } : { valid: false };
29
+ * },
30
+ * });
31
+ * ```
32
+ */
33
+ import * as crypto from 'node:crypto';
34
+ // ============================================================================
35
+ // ApiKeyManager
36
+ // ============================================================================
37
+ export class ApiKeyManager {
38
+ _config;
39
+ _minLength;
40
+ _keyHashes;
41
+ constructor(config) {
42
+ if (!config.keys?.length && !config.hashedKeys?.length && !config.validator) {
43
+ throw new Error('ApiKeyManager requires at least one of: keys, hashedKeys, validator');
44
+ }
45
+ this._config = config;
46
+ this._minLength = config.minLength ?? 16;
47
+ // Pre-hash static keys for timing-safe comparison
48
+ this._keyHashes = new Set();
49
+ if (config.keys) {
50
+ for (const key of config.keys) {
51
+ this._keyHashes.add(ApiKeyManager.hashKey(key));
52
+ }
53
+ }
54
+ if (config.hashedKeys) {
55
+ for (const hash of config.hashedKeys) {
56
+ this._keyHashes.add(hash);
57
+ }
58
+ }
59
+ }
60
+ // ── Public API ───────────────────────────────────────
61
+ /**
62
+ * Validate an API key.
63
+ *
64
+ * @param key - Raw API key string
65
+ * @returns Validation result with optional metadata
66
+ */
67
+ async validate(key) {
68
+ // Format checks
69
+ if (!key || typeof key !== 'string') {
70
+ return { valid: false, reason: 'API key is empty or not a string' };
71
+ }
72
+ if (key.length < this._minLength) {
73
+ return { valid: false, reason: `API key too short (min ${this._minLength} chars)` };
74
+ }
75
+ if (this._config.prefix && !key.startsWith(this._config.prefix)) {
76
+ return { valid: false, reason: `API key must start with '${this._config.prefix}'` };
77
+ }
78
+ // Async validator takes priority
79
+ if (this._config.validator) {
80
+ return this._config.validator(key);
81
+ }
82
+ // Hash-based comparison (timing-safe)
83
+ const keyHash = ApiKeyManager.hashKey(key);
84
+ const isValid = this._isHashInSet(keyHash);
85
+ return isValid
86
+ ? { valid: true }
87
+ : { valid: false, reason: 'Invalid API key' };
88
+ }
89
+ /**
90
+ * Quick boolean check without detailed result.
91
+ */
92
+ async isValid(key) {
93
+ const result = await this.validate(key);
94
+ return result.valid;
95
+ }
96
+ // ── Static Utilities ─────────────────────────────────
97
+ /**
98
+ * Hash an API key using SHA-256 for safe storage.
99
+ *
100
+ * @param rawKey - Plaintext API key
101
+ * @returns Hex-encoded SHA-256 hash
102
+ */
103
+ static hashKey(rawKey) {
104
+ return crypto.createHash('sha256').update(rawKey).digest('hex');
105
+ }
106
+ /**
107
+ * Compare a raw key against a stored hash using timing-safe comparison.
108
+ *
109
+ * @param rawKey - Plaintext API key
110
+ * @param storedHash - SHA-256 hex hash to compare against
111
+ * @returns Whether the key matches the hash
112
+ */
113
+ static matchKey(rawKey, storedHash) {
114
+ const keyHash = ApiKeyManager.hashKey(rawKey);
115
+ return ApiKeyManager._timingSafeCompare(keyHash, storedHash);
116
+ }
117
+ /**
118
+ * Generate a random API key with optional prefix.
119
+ *
120
+ * @param options - Generation options
121
+ * @returns Random API key string
122
+ */
123
+ static generateKey(options) {
124
+ const prefix = options?.prefix ?? 'sk_';
125
+ const length = options?.length ?? 32;
126
+ const random = crypto.randomBytes(length).toString('base64url').slice(0, length);
127
+ return `${prefix}${random}`;
128
+ }
129
+ // ── Private Helpers ──────────────────────────────────
130
+ /**
131
+ * Check if a hash exists in the pre-computed set using timing-safe comparison.
132
+ * @internal
133
+ */
134
+ _isHashInSet(hash) {
135
+ for (const stored of this._keyHashes) {
136
+ if (ApiKeyManager._timingSafeCompare(hash, stored)) {
137
+ return true;
138
+ }
139
+ }
140
+ return false;
141
+ }
142
+ /**
143
+ * Timing-safe string comparison to prevent timing attacks.
144
+ * @internal
145
+ */
146
+ static _timingSafeCompare(a, b) {
147
+ if (a.length !== b.length)
148
+ return false;
149
+ try {
150
+ return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));
151
+ }
152
+ catch {
153
+ return false;
154
+ }
155
+ }
156
+ }
157
+ //# sourceMappingURL=ApiKeyManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiKeyManager.js","sourceRoot":"","sources":["../src/ApiKeyManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * API Key Auth Tool Factory — Pre-built API Key Validation Tool
3
+ *
4
+ * Creates a complete mcp-fusion tool with validate and status actions.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { createApiKeyTool } from '@vinkius-core/mcp-fusion-api-key';
9
+ *
10
+ * const apiKeyTool = createApiKeyTool({
11
+ * keys: ['sk_live_abc123'],
12
+ * });
13
+ * ```
14
+ */
15
+ import type { ApiKeyManagerConfig } from './ApiKeyManager.js';
16
+ export interface ApiKeyToolConfig<TContext = unknown> extends ApiKeyManagerConfig {
17
+ /** Tool name in MCP. Default: 'api_key_auth' */
18
+ readonly toolName?: string;
19
+ /** Tool description for the LLM. */
20
+ readonly description?: string;
21
+ /** Tags for selective tool exposure. */
22
+ readonly tags?: string[];
23
+ /** Extract API key from context for the `status` action. */
24
+ readonly extractKey?: (ctx: TContext) => string | null | undefined;
25
+ }
26
+ /**
27
+ * Creates a complete API key auth tool with validate and status actions.
28
+ *
29
+ * Actions:
30
+ * - `validate` — Validate an API key and return metadata
31
+ * - `status` — Check if API key is present/valid
32
+ */
33
+ export declare function createApiKeyTool<TContext = unknown>(config: ApiKeyToolConfig<TContext>): import("@vinkius-core/mcp-fusion").GroupedToolBuilder<TContext, Record<string, never>, string, Record<string, never> & {
34
+ [x: `${string}.validate`]: Record<string, unknown>;
35
+ } & {
36
+ [x: `${string}.status`]: Record<string, unknown>;
37
+ }>;
38
+ //# sourceMappingURL=createApiKeyTool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createApiKeyTool.d.ts","sourceRoot":"","sources":["../src/createApiKeyTool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAM9D,MAAM,WAAW,gBAAgB,CAAC,QAAQ,GAAG,OAAO,CAAE,SAAQ,mBAAmB;IAC7E,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAE3B,oCAAoC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAE9B,wCAAwC;IACxC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB,4DAA4D;IAC5D,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACtE;AAkBD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,GAAG,OAAO,EAAE,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC;;;;GAkEtF"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * API Key Auth Tool Factory — Pre-built API Key Validation Tool
3
+ *
4
+ * Creates a complete mcp-fusion tool with validate and status actions.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { createApiKeyTool } from '@vinkius-core/mcp-fusion-api-key';
9
+ *
10
+ * const apiKeyTool = createApiKeyTool({
11
+ * keys: ['sk_live_abc123'],
12
+ * });
13
+ * ```
14
+ */
15
+ import { createTool } from '@vinkius-core/mcp-fusion';
16
+ import { ApiKeyManager } from './ApiKeyManager.js';
17
+ // ============================================================================
18
+ // Response Helpers
19
+ // ============================================================================
20
+ function ok(data) {
21
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
22
+ }
23
+ function fail(data) {
24
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }], isError: true };
25
+ }
26
+ // ============================================================================
27
+ // Factory
28
+ // ============================================================================
29
+ /**
30
+ * Creates a complete API key auth tool with validate and status actions.
31
+ *
32
+ * Actions:
33
+ * - `validate` — Validate an API key and return metadata
34
+ * - `status` — Check if API key is present/valid
35
+ */
36
+ export function createApiKeyTool(config) {
37
+ const manager = new ApiKeyManager(config);
38
+ const toolName = config.toolName ?? 'api_key_auth';
39
+ const description = config.description ?? 'API key authentication — validate keys and check status';
40
+ const extractKey = config.extractKey;
41
+ const tool = createTool(toolName);
42
+ if (config.tags?.length) {
43
+ tool.tags(...config.tags);
44
+ }
45
+ return tool
46
+ .action({
47
+ name: 'validate',
48
+ description: 'Validate an API key',
49
+ handler: async (_ctx, args) => {
50
+ const key = args['key'];
51
+ if (!key) {
52
+ return fail({ message: 'API key is required' });
53
+ }
54
+ const result = await manager.validate(key);
55
+ if (!result.valid) {
56
+ return fail({
57
+ message: `Validation failed: ${result.reason}`,
58
+ valid: false,
59
+ });
60
+ }
61
+ return ok({
62
+ valid: true,
63
+ metadata: result.metadata,
64
+ });
65
+ },
66
+ })
67
+ .action({
68
+ name: 'status',
69
+ description: 'Check API key authentication status from context',
70
+ handler: async (ctx) => {
71
+ if (!extractKey) {
72
+ return ok({
73
+ available: false,
74
+ reason: 'No key extractor configured',
75
+ });
76
+ }
77
+ const key = extractKey(ctx);
78
+ if (!key) {
79
+ return ok({
80
+ authenticated: false,
81
+ reason: 'No API key found in context',
82
+ });
83
+ }
84
+ const result = await manager.validate(key);
85
+ return ok({
86
+ authenticated: result.valid,
87
+ valid: result.valid,
88
+ reason: result.reason,
89
+ metadata: result.metadata,
90
+ });
91
+ },
92
+ });
93
+ }
94
+ //# sourceMappingURL=createApiKeyTool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createApiKeyTool.js","sourceRoot":"","sources":["../src/createApiKeyTool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @vinkius-core/mcp-fusion-api-key — API Key Validation for MCP Servers
3
+ *
4
+ * Timing-safe API key validation with SHA-256 hashing,
5
+ * async validators, and mcp-fusion middleware integration.
6
+ * Zero external dependencies — uses native Node.js crypto.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { ApiKeyManager, requireApiKey, createApiKeyTool } from '@vinkius-core/mcp-fusion-api-key';
11
+ *
12
+ * // Middleware
13
+ * const projects = createTool('projects')
14
+ * .use(requireApiKey({ keys: ['sk_live_abc123'] }))
15
+ * .action({ name: 'list', handler: async () => success([]) });
16
+ *
17
+ * // Standalone
18
+ * const manager = new ApiKeyManager({ keys: ['sk_live_abc123'] });
19
+ * const result = await manager.validate('sk_live_abc123');
20
+ * ```
21
+ *
22
+ * @module @vinkius-core/mcp-fusion-api-key
23
+ * @author Vinkius Labs
24
+ * @license Apache-2.0
25
+ */
26
+ export { ApiKeyManager } from './ApiKeyManager.js';
27
+ export type { ApiKeyManagerConfig, ApiKeyValidationResult, } from './ApiKeyManager.js';
28
+ export { createApiKeyTool } from './createApiKeyTool.js';
29
+ export type { ApiKeyToolConfig } from './createApiKeyTool.js';
30
+ export { requireApiKey } from './middleware.js';
31
+ export type { RequireApiKeyOptions } from './middleware.js';
32
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EACR,mBAAmB,EACnB,sBAAsB,GACzB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @vinkius-core/mcp-fusion-api-key — API Key Validation for MCP Servers
3
+ *
4
+ * Timing-safe API key validation with SHA-256 hashing,
5
+ * async validators, and mcp-fusion middleware integration.
6
+ * Zero external dependencies — uses native Node.js crypto.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { ApiKeyManager, requireApiKey, createApiKeyTool } from '@vinkius-core/mcp-fusion-api-key';
11
+ *
12
+ * // Middleware
13
+ * const projects = createTool('projects')
14
+ * .use(requireApiKey({ keys: ['sk_live_abc123'] }))
15
+ * .action({ name: 'list', handler: async () => success([]) });
16
+ *
17
+ * // Standalone
18
+ * const manager = new ApiKeyManager({ keys: ['sk_live_abc123'] });
19
+ * const result = await manager.validate('sk_live_abc123');
20
+ * ```
21
+ *
22
+ * @module @vinkius-core/mcp-fusion-api-key
23
+ * @author Vinkius Labs
24
+ * @license Apache-2.0
25
+ */
26
+ export { ApiKeyManager } from './ApiKeyManager.js';
27
+ export { createApiKeyTool } from './createApiKeyTool.js';
28
+ export { requireApiKey } from './middleware.js';
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAMnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * API Key Auth Middleware — requireApiKey()
3
+ *
4
+ * mcp-fusion middleware that ensures requests carry a valid API key.
5
+ * Extracts the key, validates it via ApiKeyManager, and rejects
6
+ * invalid/missing keys with self-healing error responses.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { requireApiKey } from '@vinkius-core/mcp-fusion-api-key';
11
+ *
12
+ * const projects = createTool('projects')
13
+ * .use(requireApiKey({ keys: ['sk_live_abc123'] }))
14
+ * .action({ name: 'list', handler: async (ctx) => { ... } });
15
+ * ```
16
+ */
17
+ import type { ToolResponse } from '@vinkius-core/mcp-fusion';
18
+ import type { ApiKeyManagerConfig } from './ApiKeyManager.js';
19
+ export interface RequireApiKeyOptions extends ApiKeyManagerConfig {
20
+ /**
21
+ * Custom function to extract the API key from the context.
22
+ * Default: checks `ctx.apiKey`, `ctx.headers['x-api-key']`,
23
+ * `ctx.headers.authorization` (ApiKey/Bearer prefix).
24
+ */
25
+ readonly extractKey?: (ctx: unknown) => string | null | undefined;
26
+ /**
27
+ * Callback invoked after successful validation.
28
+ * Use this to inject key metadata into the context.
29
+ */
30
+ readonly onValidated?: (ctx: unknown, metadata?: Record<string, unknown>) => void;
31
+ /** Error code for toolError response. Default: 'APIKEY_INVALID' */
32
+ readonly errorCode?: string;
33
+ /** Recovery hint for the LLM. Default: 'Provide a valid API key' */
34
+ readonly recoveryHint?: string;
35
+ /** Recovery action name. Default: 'auth' */
36
+ readonly recoveryAction?: string;
37
+ }
38
+ /**
39
+ * Creates a mcp-fusion middleware that validates API keys.
40
+ *
41
+ * Returns `toolError('APIKEY_INVALID')` with self-healing hints
42
+ * when no valid key is found.
43
+ */
44
+ export declare function requireApiKey(options: RequireApiKeyOptions): (ctx: unknown, _args: Record<string, unknown>, next: () => Promise<ToolResponse>) => Promise<ToolResponse>;
45
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAM9D,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC7D;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAElE;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAElF,mEAAmE;IACnE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B,oEAAoE;IACpE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE/B,4CAA4C;IAC5C,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CACpC;AAMD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,IAQzC,KAAK,OAAO,EAAE,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,MAAM,OAAO,CAAC,YAAY,CAAC,KAAG,OAAO,CAAC,YAAY,CAAC,CA2BxH"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * API Key Auth Middleware — requireApiKey()
3
+ *
4
+ * mcp-fusion middleware that ensures requests carry a valid API key.
5
+ * Extracts the key, validates it via ApiKeyManager, and rejects
6
+ * invalid/missing keys with self-healing error responses.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { requireApiKey } from '@vinkius-core/mcp-fusion-api-key';
11
+ *
12
+ * const projects = createTool('projects')
13
+ * .use(requireApiKey({ keys: ['sk_live_abc123'] }))
14
+ * .action({ name: 'list', handler: async (ctx) => { ... } });
15
+ * ```
16
+ */
17
+ import { toolError } from '@vinkius-core/mcp-fusion';
18
+ import { ApiKeyManager } from './ApiKeyManager.js';
19
+ // ============================================================================
20
+ // Middleware Factory
21
+ // ============================================================================
22
+ /**
23
+ * Creates a mcp-fusion middleware that validates API keys.
24
+ *
25
+ * Returns `toolError('APIKEY_INVALID')` with self-healing hints
26
+ * when no valid key is found.
27
+ */
28
+ export function requireApiKey(options) {
29
+ const manager = new ApiKeyManager(options);
30
+ const extractKey = options.extractKey ?? defaultExtractKey;
31
+ const errorCode = options.errorCode ?? 'APIKEY_INVALID';
32
+ const recoveryHint = options.recoveryHint ?? 'Provide a valid API key';
33
+ const recoveryAction = options.recoveryAction ?? 'auth';
34
+ const onValidated = options.onValidated;
35
+ return async (ctx, _args, next) => {
36
+ const raw = extractKey(ctx);
37
+ if (!raw) {
38
+ return toolError(errorCode, {
39
+ message: 'API key authentication required',
40
+ suggestion: recoveryHint,
41
+ availableActions: [recoveryAction],
42
+ });
43
+ }
44
+ const result = await manager.validate(raw);
45
+ if (!result.valid) {
46
+ return toolError(errorCode, {
47
+ message: `API key validation failed: ${result.reason}`,
48
+ suggestion: recoveryHint,
49
+ availableActions: [recoveryAction],
50
+ });
51
+ }
52
+ if (onValidated) {
53
+ onValidated(ctx, result.metadata);
54
+ }
55
+ return next();
56
+ };
57
+ }
58
+ // ============================================================================
59
+ // Default Key Extractor
60
+ // ============================================================================
61
+ /**
62
+ * Default API key extractor — checks common patterns:
63
+ * - `ctx.apiKey`
64
+ * - `ctx.headers['x-api-key']`
65
+ * - `ctx.headers.authorization` with `ApiKey ` or `Bearer ` prefix
66
+ */
67
+ function defaultExtractKey(ctx) {
68
+ if (!ctx || typeof ctx !== 'object')
69
+ return null;
70
+ const obj = ctx;
71
+ // Direct apiKey property
72
+ if (typeof obj['apiKey'] === 'string' && obj['apiKey']) {
73
+ return obj['apiKey'];
74
+ }
75
+ // Headers
76
+ const headers = obj['headers'];
77
+ if (headers) {
78
+ // x-api-key header
79
+ if (typeof headers['x-api-key'] === 'string' && headers['x-api-key']) {
80
+ return headers['x-api-key'];
81
+ }
82
+ // Authorization header with ApiKey or Bearer prefix
83
+ const auth = headers['authorization'];
84
+ if (typeof auth === 'string' && auth) {
85
+ if (auth.startsWith('ApiKey '))
86
+ return auth.slice(7);
87
+ if (auth.startsWith('Bearer '))
88
+ return auth.slice(7);
89
+ return auth;
90
+ }
91
+ }
92
+ return null;
93
+ }
94
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@vinkius-core/mcp-fusion-api-key",
3
+ "version": "1.0.0",
4
+ "description": "API key validation middleware for MCP servers built with mcp-fusion. Timing-safe comparison, SHA-256 hashing, async validators, and self-healing error responses.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "test": "vitest run",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "keywords": [
20
+ "mcp",
21
+ "mcp-fusion",
22
+ "api-key",
23
+ "authentication",
24
+ "middleware",
25
+ "ai",
26
+ "llm"
27
+ ],
28
+ "author": "Vinkius Labs",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/vinkius-labs/mcp-fusion.git",
32
+ "directory": "packages/api-key"
33
+ },
34
+ "bugs": {
35
+ "url": "https://github.com/vinkius-labs/mcp-fusion/issues"
36
+ },
37
+ "homepage": "https://mcp-fusion.vinkius.com/",
38
+ "files": [
39
+ "dist",
40
+ "README.md"
41
+ ],
42
+ "engines": {
43
+ "node": ">=18.0.0"
44
+ },
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "peerDependencies": {
49
+ "@vinkius-core/mcp-fusion": "^2.0.0"
50
+ },
51
+ "license": "Apache-2.0"
52
+ }