@mcp-guardian/server 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/README.md +105 -8
  2. package/dist/auth/auth-types.d.ts +40 -0
  3. package/dist/auth/auth-types.d.ts.map +1 -0
  4. package/dist/auth/auth-types.js +5 -0
  5. package/dist/auth/auth-types.js.map +1 -0
  6. package/dist/auth/dashboard-auth.d.ts +97 -0
  7. package/dist/auth/dashboard-auth.d.ts.map +1 -0
  8. package/dist/auth/dashboard-auth.js +319 -0
  9. package/dist/auth/dashboard-auth.js.map +1 -0
  10. package/dist/auth/dpop.d.ts +38 -0
  11. package/dist/auth/dpop.d.ts.map +1 -0
  12. package/dist/auth/dpop.js +72 -0
  13. package/dist/auth/dpop.js.map +1 -0
  14. package/dist/auth/oauth.d.ts +25 -0
  15. package/dist/auth/oauth.d.ts.map +1 -0
  16. package/dist/auth/oauth.js +96 -0
  17. package/dist/auth/oauth.js.map +1 -0
  18. package/dist/auth/redis-session-cache.d.ts +21 -0
  19. package/dist/auth/redis-session-cache.d.ts.map +1 -0
  20. package/dist/auth/redis-session-cache.js +74 -0
  21. package/dist/auth/redis-session-cache.js.map +1 -0
  22. package/dist/auth/session-cache.d.ts +47 -0
  23. package/dist/auth/session-cache.d.ts.map +1 -0
  24. package/dist/auth/session-cache.js +91 -0
  25. package/dist/auth/session-cache.js.map +1 -0
  26. package/dist/cli.js +23 -5
  27. package/dist/cli.js.map +1 -1
  28. package/dist/database/database-interface.d.ts +17 -0
  29. package/dist/database/database-interface.d.ts.map +1 -0
  30. package/dist/database/database-interface.js +2 -0
  31. package/dist/database/database-interface.js.map +1 -0
  32. package/dist/database/postgres-db.d.ts +18 -0
  33. package/dist/database/postgres-db.d.ts.map +1 -0
  34. package/dist/database/postgres-db.js +118 -0
  35. package/dist/database/postgres-db.js.map +1 -0
  36. package/dist/index.js +1 -1
  37. package/dist/policy/policy-watcher.d.ts +24 -0
  38. package/dist/policy/policy-watcher.d.ts.map +1 -0
  39. package/dist/policy/policy-watcher.js +68 -0
  40. package/dist/policy/policy-watcher.js.map +1 -0
  41. package/dist/policy/shell-tokenizer.d.ts +92 -0
  42. package/dist/policy/shell-tokenizer.d.ts.map +1 -0
  43. package/dist/policy/shell-tokenizer.js +300 -0
  44. package/dist/policy/shell-tokenizer.js.map +1 -0
  45. package/dist/proxy/http-proxy-server.d.ts +26 -0
  46. package/dist/proxy/http-proxy-server.d.ts.map +1 -0
  47. package/dist/proxy/http-proxy-server.js +172 -0
  48. package/dist/proxy/http-proxy-server.js.map +1 -0
  49. package/dist/proxy/proxy-manager.d.ts +3 -1
  50. package/dist/proxy/proxy-manager.d.ts.map +1 -1
  51. package/dist/proxy/proxy-manager.js +10 -3
  52. package/dist/proxy/proxy-manager.js.map +1 -1
  53. package/dist/proxy/proxy-server.d.ts +15 -8
  54. package/dist/proxy/proxy-server.d.ts.map +1 -1
  55. package/dist/proxy/proxy-server.js +80 -26
  56. package/dist/proxy/proxy-server.js.map +1 -1
  57. package/dist/utils/circuit-breaker.d.ts +29 -0
  58. package/dist/utils/circuit-breaker.d.ts.map +1 -0
  59. package/dist/utils/circuit-breaker.js +81 -0
  60. package/dist/utils/circuit-breaker.js.map +1 -0
  61. package/dist/utils/dashboard-server.d.ts +19 -0
  62. package/dist/utils/dashboard-server.d.ts.map +1 -0
  63. package/dist/utils/dashboard-server.js +258 -0
  64. package/dist/utils/dashboard-server.js.map +1 -0
  65. package/dist/utils/metrics.d.ts +17 -0
  66. package/dist/utils/metrics.d.ts.map +1 -0
  67. package/dist/utils/metrics.js +79 -0
  68. package/dist/utils/metrics.js.map +1 -0
  69. package/dist/utils/mtls-config.d.ts +27 -0
  70. package/dist/utils/mtls-config.d.ts.map +1 -0
  71. package/dist/utils/mtls-config.js +82 -0
  72. package/dist/utils/mtls-config.js.map +1 -0
  73. package/dist/utils/payload-normalizer.d.ts +62 -0
  74. package/dist/utils/payload-normalizer.d.ts.map +1 -0
  75. package/dist/utils/payload-normalizer.js +240 -0
  76. package/dist/utils/payload-normalizer.js.map +1 -0
  77. package/dist/utils/policy-auditor.d.ts +24 -0
  78. package/dist/utils/policy-auditor.d.ts.map +1 -0
  79. package/dist/utils/policy-auditor.js +58 -0
  80. package/dist/utils/policy-auditor.js.map +1 -0
  81. package/dist/utils/redis-rate-limiter.d.ts +22 -0
  82. package/dist/utils/redis-rate-limiter.d.ts.map +1 -0
  83. package/dist/utils/redis-rate-limiter.js +61 -0
  84. package/dist/utils/redis-rate-limiter.js.map +1 -0
  85. package/dist/utils/structured-logger.d.ts +1 -1
  86. package/dist/utils/structured-logger.d.ts.map +1 -1
  87. package/dist/utils/tracing.d.ts +7 -0
  88. package/dist/utils/tracing.d.ts.map +1 -0
  89. package/dist/utils/tracing.js +34 -0
  90. package/dist/utils/tracing.js.map +1 -0
  91. package/package.json +2 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-auth.js","sourceRoot":"","sources":["../../src/auth/dashboard-auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import * as jose from 'jose';
2
+ /**
3
+ * DPoP (Demonstrating Proof of Possession) — RFC 9449.
4
+ * Validates sender-constrained tokens to prevent token replay.
5
+ * The client must include a DPoP proof JWT in the DPoP header.
6
+ */
7
+ export interface DPoPProof {
8
+ /** The access token hash (ath) claim */
9
+ ath?: string;
10
+ /** The HTTP method of the request */
11
+ htm: string;
12
+ /** The HTTP URI of the request */
13
+ htu: string;
14
+ /** Issued at (Unix timestamp) */
15
+ iat: number;
16
+ /** Unique JWT ID for replay detection */
17
+ jti: string;
18
+ }
19
+ export declare class DPoPValidator {
20
+ private usedNonces;
21
+ private readonly nonceTtlMs;
22
+ private lastCleanup;
23
+ constructor(nonceTtlMs?: number);
24
+ /**
25
+ * Validate a DPoP proof JWT.
26
+ * Checks: signature (JWK), htm, htu, iat freshness (60s window), ath (if access token provided), nonce replay.
27
+ */
28
+ validate(proofToken: string, jwk: jose.JWK, httpMethod: string, httpUri: string, accessToken?: string): Promise<{
29
+ valid: boolean;
30
+ error?: string;
31
+ }>;
32
+ /**
33
+ * Compute the access token hash (ath) as per RFC 9449 §4.2.
34
+ * ath = base64url(sha256(access_token))
35
+ */
36
+ private computeAth;
37
+ }
38
+ //# sourceMappingURL=dpop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dpop.d.ts","sourceRoot":"","sources":["../../src/auth/dpop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,wCAAwC;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,kCAAkC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,iCAAiC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,WAAW,CAAsB;gBAE7B,UAAU,GAAE,MAAuB;IAI/C;;;OAGG;IACG,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAyDzJ;;;OAGG;YACW,UAAU;CAIzB"}
@@ -0,0 +1,72 @@
1
+ import * as jose from 'jose';
2
+ import { Logger } from '../utils/logger.js';
3
+ export class DPoPValidator {
4
+ usedNonces = new Set();
5
+ nonceTtlMs;
6
+ lastCleanup = Date.now();
7
+ constructor(nonceTtlMs = 10 * 60 * 1000) {
8
+ this.nonceTtlMs = nonceTtlMs;
9
+ }
10
+ /**
11
+ * Validate a DPoP proof JWT.
12
+ * Checks: signature (JWK), htm, htu, iat freshness (60s window), ath (if access token provided), nonce replay.
13
+ */
14
+ async validate(proofToken, jwk, httpMethod, httpUri, accessToken) {
15
+ try {
16
+ // Verify the proof JWT is signed by the client's private key matching the JWK
17
+ const publicKey = await jose.importJWK(jwk, 'ES256');
18
+ const { payload } = await jose.jwtVerify(proofToken, publicKey, {
19
+ algorithms: ['ES256', 'RS256', 'EdDSA'],
20
+ clockTolerance: 10,
21
+ });
22
+ const proof = payload;
23
+ // Validate htm (HTTP method)
24
+ if (proof.htm !== httpMethod.toUpperCase()) {
25
+ return { valid: false, error: `DPoP: htm mismatch (expected ${httpMethod.toUpperCase()}, got ${proof.htm})` };
26
+ }
27
+ // Validate htu (HTTP URI) — must match the request URI
28
+ if (proof.htu !== httpUri) {
29
+ return { valid: false, error: `DPoP: htu mismatch (expected ${httpUri}, got ${proof.htu})` };
30
+ }
31
+ // Validate iat freshness (must be within last 60 seconds)
32
+ const now = Math.floor(Date.now() / 1000);
33
+ if (proof.iat < now - 60) {
34
+ return { valid: false, error: 'DPoP: proof too old (iat > 60s ago)' };
35
+ }
36
+ if (proof.iat > now + 10) {
37
+ return { valid: false, error: 'DPoP: proof from the future' };
38
+ }
39
+ // Validate nonce (jti) for replay detection
40
+ if (this.usedNonces.has(proof.jti)) {
41
+ Logger.warn(`[dpop] Replay detected: jti ${proof.jti}`);
42
+ return { valid: false, error: 'DPoP: nonce already used (replay detected)' };
43
+ }
44
+ this.usedNonces.add(proof.jti);
45
+ // Validate ath (access token hash) if access token provided
46
+ if (accessToken && proof.ath) {
47
+ const expectedAth = await this.computeAth(accessToken);
48
+ if (proof.ath !== expectedAth) {
49
+ return { valid: false, error: 'DPoP: ath mismatch (access token hash does not match)' };
50
+ }
51
+ }
52
+ // Periodic cleanup of old nonces
53
+ if (Date.now() - this.lastCleanup > 60000) {
54
+ this.usedNonces.clear();
55
+ this.lastCleanup = Date.now();
56
+ }
57
+ return { valid: true };
58
+ }
59
+ catch (err) {
60
+ return { valid: false, error: `DPoP validation failed: ${err?.message}` };
61
+ }
62
+ }
63
+ /**
64
+ * Compute the access token hash (ath) as per RFC 9449 §4.2.
65
+ * ath = base64url(sha256(access_token))
66
+ */
67
+ async computeAth(accessToken) {
68
+ const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(accessToken));
69
+ return Buffer.from(digest).toString('base64url');
70
+ }
71
+ }
72
+ //# sourceMappingURL=dpop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dpop.js","sourceRoot":"","sources":["../../src/auth/dpop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { AuthConfig, AuthValidationResult, OIDCDiscovery } from './auth-types.js';
2
+ export declare class OAuthValidator {
3
+ private config;
4
+ private jwks;
5
+ private cachedDiscovery;
6
+ constructor(config: AuthConfig);
7
+ /**
8
+ * Perform OIDC discovery to fetch JWKS URI from issuer.
9
+ */
10
+ discover(): Promise<OIDCDiscovery>;
11
+ /**
12
+ * Initialize JWKS from discovery or explicit URI.
13
+ */
14
+ init(): Promise<void>;
15
+ /**
16
+ * Validate a JWT bearer token and extract agent identity.
17
+ */
18
+ validate(token: string): Promise<AuthValidationResult>;
19
+ /**
20
+ * Extract Bearer token from Authorization header.
21
+ */
22
+ static extractToken(authorizationHeader?: string): string | null;
23
+ getConfig(): AuthConfig;
24
+ }
25
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAiB,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGjG,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,IAAI,CAA2D;IACvE,OAAO,CAAC,eAAe,CAA8B;gBAEzC,MAAM,EAAE,UAAU;IAI9B;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,aAAa,CAAC;IAiBxC;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B;;OAEG;IACG,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAkC5D;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,mBAAmB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAMhE,SAAS,IAAI,UAAU;CAGxB"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * OAuth 2.1 / OIDC JWT Validator for MCP Guardian proxy.
3
+ *
4
+ * Validates bearer tokens from MCP requests against an OIDC provider.
5
+ * Uses OIDC Discovery (RFC 8414) to auto-configure JWKS endpoint.
6
+ * Supports Client Credentials flow (most common for server-to-agent MCP).
7
+ */
8
+ import * as jose from 'jose';
9
+ import { StructuredLogger } from '../utils/structured-logger.js';
10
+ export class OAuthValidator {
11
+ config;
12
+ jwks = null;
13
+ cachedDiscovery = null;
14
+ constructor(config) {
15
+ this.config = config;
16
+ }
17
+ /**
18
+ * Perform OIDC discovery to fetch JWKS URI from issuer.
19
+ */
20
+ async discover() {
21
+ if (this.cachedDiscovery)
22
+ return this.cachedDiscovery;
23
+ const discoveryUrl = `${this.config.issuer}/.well-known/openid-configuration`;
24
+ try {
25
+ const res = await fetch(discoveryUrl);
26
+ if (!res.ok)
27
+ throw new Error(`OIDC discovery failed: HTTP ${res.status}`);
28
+ const meta = (await res.json());
29
+ this.cachedDiscovery = meta;
30
+ StructuredLogger.info({ event: 'oidc_discovery', issuer: this.config.issuer, jwks_uri: meta.jwks_uri });
31
+ return meta;
32
+ }
33
+ catch (err) {
34
+ StructuredLogger.logError({ event: 'oidc_discovery_error', serverName: 'oauth', error: `Failed to discover OIDC config: ${err?.message}` });
35
+ throw err;
36
+ }
37
+ }
38
+ /**
39
+ * Initialize JWKS from discovery or explicit URI.
40
+ */
41
+ async init() {
42
+ let jwksUri = this.config.jwksUri;
43
+ if (!jwksUri) {
44
+ const discovery = await this.discover();
45
+ jwksUri = discovery.jwks_uri;
46
+ }
47
+ this.jwks = jose.createRemoteJWKSet(new URL(jwksUri));
48
+ }
49
+ /**
50
+ * Validate a JWT bearer token and extract agent identity.
51
+ */
52
+ async validate(token) {
53
+ if (!this.jwks) {
54
+ try {
55
+ await this.init();
56
+ }
57
+ catch (err) {
58
+ return { valid: false, error: `Auth provider unreachable: ${err?.message}` };
59
+ }
60
+ }
61
+ if (!this.jwks) {
62
+ return { valid: false, error: 'JWKS not initialized' };
63
+ }
64
+ try {
65
+ const { payload } = await jose.jwtVerify(token, this.jwks, {
66
+ issuer: this.config.issuer,
67
+ audience: this.config.audience,
68
+ clockTolerance: this.config.clockTolerance || 30,
69
+ });
70
+ const identity = {
71
+ sub: payload.sub || 'unknown',
72
+ clientId: payload.client_id || payload.azp,
73
+ scopes: payload.scope ? String(payload.scope).split(' ') : undefined,
74
+ issuer: payload.iss || this.config.issuer,
75
+ expiresAt: payload.exp ? payload.exp * 1000 : undefined,
76
+ };
77
+ return { valid: true, identity };
78
+ }
79
+ catch (err) {
80
+ return { valid: false, error: `JWT validation failed: ${err?.message}` };
81
+ }
82
+ }
83
+ /**
84
+ * Extract Bearer token from Authorization header.
85
+ */
86
+ static extractToken(authorizationHeader) {
87
+ if (!authorizationHeader)
88
+ return null;
89
+ const match = authorizationHeader.match(/^Bearer\s+(.+)$/i);
90
+ return match ? match[1] : null;
91
+ }
92
+ getConfig() {
93
+ return this.config;
94
+ }
95
+ }
96
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { AgentIdentity } from './auth-types.js';
2
+ import { SessionCache, SessionEntry } from './session-cache.js';
3
+ /**
4
+ * Redis-backed session cache for multi-replica HA deployments.
5
+ * Extends SessionCache to use Redis instead of in-memory Maps.
6
+ * Enable with: REDIS_URL=redis://localhost:6379
7
+ */
8
+ export declare class RedisSessionCache extends SessionCache {
9
+ private redis;
10
+ private readonly prefix;
11
+ private readonly noncePrefix;
12
+ constructor(sessionTtlMs?: number, nonceTtlMs?: number);
13
+ createSession(identity: AgentIdentity, jwtNonce?: string): SessionEntry;
14
+ validateSession(token: string): AgentIdentity | null;
15
+ validateSessionAsync(token: string): Promise<AgentIdentity | null>;
16
+ isNonceUsedAsync(nonce: string): Promise<boolean>;
17
+ revokeSessionAsync(token: string): Promise<void>;
18
+ cleanup(): Promise<void>;
19
+ close(): Promise<void>;
20
+ }
21
+ //# sourceMappingURL=redis-session-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-session-cache.d.ts","sourceRoot":"","sources":["../../src/auth/redis-session-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGhE;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,YAAY;IACjD,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;IAClD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;gBAEzC,YAAY,GAAE,MAAsB,EAAE,UAAU,GAAE,MAAuB;IAU5E,aAAa,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY;IAqBvE,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAUvD,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAelE,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKjD,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
@@ -0,0 +1,74 @@
1
+ import { Redis } from 'ioredis';
2
+ import { SessionCache } from './session-cache.js';
3
+ import { Logger } from '../utils/logger.js';
4
+ /**
5
+ * Redis-backed session cache for multi-replica HA deployments.
6
+ * Extends SessionCache to use Redis instead of in-memory Maps.
7
+ * Enable with: REDIS_URL=redis://localhost:6379
8
+ */
9
+ export class RedisSessionCache extends SessionCache {
10
+ redis;
11
+ prefix = 'mcp_guardian:session:';
12
+ noncePrefix = 'mcp_guardian:nonce:';
13
+ constructor(sessionTtlMs = 5 * 60 * 1000, nonceTtlMs = 10 * 60 * 1000) {
14
+ super(sessionTtlMs, nonceTtlMs);
15
+ const redisUrl = process.env['REDIS_URL'] || 'redis://localhost:6379';
16
+ this.redis = new Redis(redisUrl, {
17
+ maxRetriesPerRequest: 3,
18
+ lazyConnect: false,
19
+ });
20
+ Logger.info(`[redis-session-cache] Connected to ${redisUrl}`);
21
+ }
22
+ createSession(identity, jwtNonce) {
23
+ const entry = super.createSession(identity, jwtNonce);
24
+ // Store in Redis with TTL
25
+ const ttlSeconds = Math.ceil((entry.expiresAt - Date.now()) / 1000);
26
+ this.redis.setex(`${this.prefix}${entry.token}`, ttlSeconds, JSON.stringify(entry)).catch(err => Logger.error(`[redis-session-cache] Failed to store session: ${err?.message}`));
27
+ // Store nonce with longer TTL
28
+ if (entry.nonce) {
29
+ const nonceTtlSeconds = Math.ceil(this.sessionTtlMs / 1000) * 2;
30
+ this.redis.setex(`${this.noncePrefix}${entry.nonce}`, nonceTtlSeconds, '1')
31
+ .catch(err => Logger.error(`[redis-session-cache] Failed to store nonce: ${err?.message}`));
32
+ }
33
+ return entry;
34
+ }
35
+ validateSession(token) {
36
+ // Check local cache first, then Redis
37
+ const local = super.validateSession(token);
38
+ if (local)
39
+ return local;
40
+ // Fallback to Redis for cross-replica sessions
41
+ // Note: async validateSession would require refactoring proxy-server
42
+ return null;
43
+ }
44
+ async validateSessionAsync(token) {
45
+ const raw = await this.redis.get(`${this.prefix}${token}`);
46
+ if (!raw)
47
+ return null;
48
+ try {
49
+ const entry = JSON.parse(raw);
50
+ if (Date.now() > entry.expiresAt) {
51
+ this.redis.del(`${this.prefix}${token}`);
52
+ return null;
53
+ }
54
+ return entry.identity;
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ }
60
+ async isNonceUsedAsync(nonce) {
61
+ const exists = await this.redis.exists(`${this.noncePrefix}${nonce}`);
62
+ return exists === 1;
63
+ }
64
+ async revokeSessionAsync(token) {
65
+ await this.redis.del(`${this.prefix}${token}`);
66
+ }
67
+ async cleanup() {
68
+ // Redis handles expiry via TTL — no manual cleanup needed
69
+ }
70
+ async close() {
71
+ await this.redis.quit();
72
+ }
73
+ }
74
+ //# sourceMappingURL=redis-session-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-session-cache.js","sourceRoot":"","sources":["../../src/auth/redis-session-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import { AgentIdentity } from './auth-types.js';
2
+ /**
3
+ * Session cache for replay protection.
4
+ * After a JWT is validated once, a short-lived session token is issued.
5
+ * Subsequent calls must include this session token, not the raw JWT.
6
+ * This prevents replay of captured JWTs within their expiry window.
7
+ *
8
+ * In production, replace with Redis for multi-replica HA.
9
+ */
10
+ export interface SessionEntry {
11
+ token: string;
12
+ identity: AgentIdentity;
13
+ nonce: string;
14
+ createdAt: number;
15
+ expiresAt: number;
16
+ }
17
+ export declare class SessionCache {
18
+ private sessions;
19
+ private usedNonces;
20
+ protected readonly sessionTtlMs: number;
21
+ protected readonly nonceTtlMs: number;
22
+ constructor(sessionTtlMs?: number, nonceTtlMs?: number);
23
+ /**
24
+ * Create a session after successful JWT validation.
25
+ * Returns a session token the client must use for subsequent calls.
26
+ * The JWT cannot be replayed because:
27
+ * 1. We track used nonces (jti or sub+iat)
28
+ * 2. We issue a session token with a short (5min) TTL
29
+ */
30
+ createSession(identity: AgentIdentity, jwtNonce?: string): SessionEntry;
31
+ /**
32
+ * Validate a session token.
33
+ * Returns the agent identity if valid, null if expired/not found.
34
+ */
35
+ validateSession(token: string): AgentIdentity | null;
36
+ /**
37
+ * Check if a JWT nonce has been used (replay detection).
38
+ */
39
+ isNonceUsed(nonce: string): boolean;
40
+ /**
41
+ * Revoke a session (e.g., on logout or suspicious activity).
42
+ */
43
+ revokeSession(token: string): void;
44
+ protected cleanup(): void;
45
+ get size(): number;
46
+ }
47
+ //# sourceMappingURL=session-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-cache.d.ts","sourceRoot":"","sources":["../../src/auth/session-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD;;;;;;;GAOG;AAEH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAwC;IACxD,OAAO,CAAC,UAAU,CAA0B;IAC5C,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IACxC,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAE1B,YAAY,GAAE,MAAsB,EAAE,UAAU,GAAE,MAAuB;IAOrF;;;;;;OAMG;IACH,aAAa,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY;IAuBvE;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAUpD;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAInC;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIlC,SAAS,CAAC,OAAO,IAAI,IAAI;IAqBzB,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
@@ -0,0 +1,91 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { Logger } from '../utils/logger.js';
3
+ export class SessionCache {
4
+ sessions = new Map();
5
+ usedNonces = new Set();
6
+ sessionTtlMs;
7
+ nonceTtlMs;
8
+ constructor(sessionTtlMs = 5 * 60 * 1000, nonceTtlMs = 10 * 60 * 1000) {
9
+ this.sessionTtlMs = sessionTtlMs;
10
+ this.nonceTtlMs = nonceTtlMs;
11
+ // Cleanup expired entries every 60s
12
+ setInterval(() => this.cleanup(), 60000);
13
+ }
14
+ /**
15
+ * Create a session after successful JWT validation.
16
+ * Returns a session token the client must use for subsequent calls.
17
+ * The JWT cannot be replayed because:
18
+ * 1. We track used nonces (jti or sub+iat)
19
+ * 2. We issue a session token with a short (5min) TTL
20
+ */
21
+ createSession(identity, jwtNonce) {
22
+ const nonce = jwtNonce || `${identity.sub}:${Date.now()}:${randomUUID()}`;
23
+ // Prevent nonce replay
24
+ if (this.usedNonces.has(nonce)) {
25
+ Logger.warn(`[session-cache] Replay detected: nonce ${nonce}`);
26
+ }
27
+ this.usedNonces.add(nonce);
28
+ const token = `mcp_guardian_session_${randomUUID()}`;
29
+ const now = Date.now();
30
+ const entry = {
31
+ token,
32
+ identity,
33
+ nonce,
34
+ createdAt: now,
35
+ expiresAt: now + this.sessionTtlMs,
36
+ };
37
+ this.sessions.set(token, entry);
38
+ return entry;
39
+ }
40
+ /**
41
+ * Validate a session token.
42
+ * Returns the agent identity if valid, null if expired/not found.
43
+ */
44
+ validateSession(token) {
45
+ const entry = this.sessions.get(token);
46
+ if (!entry)
47
+ return null;
48
+ if (Date.now() > entry.expiresAt) {
49
+ this.sessions.delete(token);
50
+ return null;
51
+ }
52
+ return entry.identity;
53
+ }
54
+ /**
55
+ * Check if a JWT nonce has been used (replay detection).
56
+ */
57
+ isNonceUsed(nonce) {
58
+ return this.usedNonces.has(nonce);
59
+ }
60
+ /**
61
+ * Revoke a session (e.g., on logout or suspicious activity).
62
+ */
63
+ revokeSession(token) {
64
+ this.sessions.delete(token);
65
+ }
66
+ cleanup() {
67
+ const now = Date.now();
68
+ // Clean expired sessions
69
+ for (const [token, entry] of this.sessions) {
70
+ if (now > entry.expiresAt) {
71
+ this.sessions.delete(token);
72
+ }
73
+ }
74
+ // Clean expired nonces (keep for nonceTtlMs to detect replays)
75
+ // This is simplified — in production, use a time-sorted structure
76
+ if (this.usedNonces.size > 10000) {
77
+ // Full sweep
78
+ const entries = Array.from(this.sessions.values());
79
+ const validTokens = new Set(entries.map(e => e.token));
80
+ for (const token of this.sessions.keys()) {
81
+ if (!validTokens.has(token))
82
+ this.sessions.delete(token);
83
+ }
84
+ this.usedNonces.clear();
85
+ }
86
+ }
87
+ get size() {
88
+ return this.sessions.size;
89
+ }
90
+ }
91
+ //# sourceMappingURL=session-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-cache.js","sourceRoot":"","sources":["../../src/auth/session-cache.ts"],"names":[],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -7,6 +7,7 @@ import { ReportGenerator } from './reporter/report-generator.js';
7
7
  import { calculateOverallScore } from './utils/scoring.js';
8
8
  import { ProxyManager } from './proxy/proxy-manager.js';
9
9
  import { PolicyEngine } from './policy/policy-engine.js';
10
+ import { OAuthValidator } from './auth/oauth.js';
10
11
  import { createContainer } from './container.js';
11
12
  // ── Shared helpers ────────────────────────────────────────────────────
12
13
  function loadConfigs(options) {
@@ -40,7 +41,7 @@ const program = new Command();
40
41
  program
41
42
  .name('mcp-guardian')
42
43
  .description('Security, cost, and health audit for MCP infrastructure')
43
- .version('0.4.0');
44
+ .version('0.5.0');
44
45
  program
45
46
  .command('scan')
46
47
  .description('Run security scan on MCP servers')
@@ -184,10 +185,13 @@ program
184
185
  });
185
186
  program
186
187
  .command('proxy')
187
- .description('Start MCP Guardian proxy to capture real token usage data with active policy enforcement')
188
+ .description('Start MCP Guardian proxy with optional OAuth 2.1 authentication and active policy enforcement')
188
189
  .option('-c, --config <path>', 'Path to MCP config file')
189
190
  .option('--policy <path>', 'Path to policy YAML file (enables active blocking)')
190
191
  .option('--blocking-mode <mode>', 'Override policy mode: audit (passive), warn (flag), block (enforce)', 'block')
192
+ .option('--auth-issuer <url>', 'OIDC issuer URL for JWT validation (e.g., https://accounts.google.com)')
193
+ .option('--auth-audience <aud>', 'Expected audience claim in JWT')
194
+ .option('--auth-required', 'Require authentication for all tool calls (fail-closed)', false)
191
195
  .action(async (opts) => {
192
196
  const paths = opts.config ? [opts.config] : ConfigParser.findConfigPaths();
193
197
  if (paths.length === 0) {
@@ -199,6 +203,21 @@ program
199
203
  console.error(chalk.yellow('No servers found in config.'));
200
204
  process.exit(0);
201
205
  }
206
+ // Configure OAuth 2.1 if --auth-issuer provided
207
+ let authValidator;
208
+ if (opts.authIssuer) {
209
+ if (!opts.authAudience) {
210
+ console.error(chalk.red('--auth-audience is required when --auth-issuer is set'));
211
+ process.exit(1);
212
+ }
213
+ const authConfig = {
214
+ issuer: opts.authIssuer,
215
+ audience: opts.authAudience,
216
+ required: opts.authRequired || false,
217
+ };
218
+ authValidator = new OAuthValidator(authConfig);
219
+ console.error(chalk.green(`OAuth 2.1 enabled: ${authConfig.issuer} (audience: ${authConfig.audience})${authConfig.required ? ' [REQUIRED]' : ' [OPTIONAL]'}`));
220
+ }
202
221
  // Load policy config if --policy flag provided
203
222
  let policyEngine;
204
223
  if (opts.policy) {
@@ -207,7 +226,6 @@ program
207
226
  const { load } = await import('js-yaml');
208
227
  const policyYaml = readFileSync(opts.policy, 'utf-8');
209
228
  const policyConfig = load(policyYaml);
210
- // Override mode from CLI flag if specified
211
229
  if (opts.blockingMode && ['audit', 'warn', 'block'].includes(opts.blockingMode)) {
212
230
  policyConfig.policy.mode = opts.blockingMode;
213
231
  }
@@ -221,10 +239,10 @@ program
221
239
  }
222
240
  }
223
241
  else {
224
- console.error(chalk.dim('No policy file specified — running in audit-only mode (no blocking)'));
242
+ console.error(chalk.dim('No policy file specified — running in audit-only mode'));
225
243
  }
226
244
  const db = new HistoryDatabase();
227
- const manager = new ProxyManager(db, policyEngine);
245
+ const manager = new ProxyManager(db, policyEngine, authValidator);
228
246
  await manager.startAll(servers);
229
247
  console.error(chalk.green('MCP Guardian proxy running. Press Ctrl+C to stop.'));
230
248
  const cleanup = () => { manager.stopAll(); db.close(); process.exit(0); };