@frontmcp/auth 0.10.0 → 0.11.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.
- package/__test-utils__/assertion.helpers.d.ts +2 -0
- package/__test-utils__/assertion.helpers.d.ts.map +1 -0
- package/authorization/authorization.class.d.ts +122 -0
- package/authorization/authorization.class.d.ts.map +1 -0
- package/authorization/authorization.types.d.ts +65 -1
- package/authorization/authorization.types.d.ts.map +1 -1
- package/authorization/index.d.ts +11 -2
- package/authorization/index.d.ts.map +1 -1
- package/authorization/orchestrated.accessor.d.ts +161 -0
- package/authorization/orchestrated.accessor.d.ts.map +1 -0
- package/authorization/orchestrated.authorization.d.ts +257 -0
- package/authorization/orchestrated.authorization.d.ts.map +1 -0
- package/authorization/public.authorization.d.ts +92 -0
- package/authorization/public.authorization.d.ts.map +1 -0
- package/authorization/transparent.authorization.d.ts +130 -0
- package/authorization/transparent.authorization.d.ts.map +1 -0
- package/common/auth-logger.interface.d.ts +15 -0
- package/common/auth-logger.interface.d.ts.map +1 -0
- package/common/index.d.ts +6 -0
- package/common/index.d.ts.map +1 -0
- package/common/jwt.types.d.ts +87 -0
- package/common/jwt.types.d.ts.map +1 -0
- package/common/session-user.types.d.ts +17 -0
- package/common/session-user.types.d.ts.map +1 -0
- package/common/session.types.d.ts +190 -0
- package/common/session.types.d.ts.map +1 -0
- package/common/zod-utils.d.ts +5 -0
- package/common/zod-utils.d.ts.map +1 -0
- package/consent/consent.types.d.ts +112 -0
- package/consent/consent.types.d.ts.map +1 -0
- package/consent/index.d.ts +2 -0
- package/consent/index.d.ts.map +1 -0
- package/detection/auth-provider-detection.d.ts +53 -0
- package/detection/auth-provider-detection.d.ts.map +1 -0
- package/detection/index.d.ts +3 -0
- package/detection/index.d.ts.map +1 -0
- package/errors/auth-internal.error.d.ts +33 -0
- package/errors/auth-internal.error.d.ts.map +1 -0
- package/errors/auth-internal.errors.d.ts +123 -0
- package/errors/auth-internal.errors.d.ts.map +1 -0
- package/errors/index.d.ts +3 -0
- package/errors/index.d.ts.map +1 -0
- package/esm/index.mjs +5473 -1204
- package/esm/package.json +18 -3
- package/index.d.ts +18 -5
- package/index.d.ts.map +1 -1
- package/index.js +5351 -961
- package/jwks/jwks.service.d.ts +1 -0
- package/jwks/jwks.service.d.ts.map +1 -1
- package/jwks/jwks.types.d.ts +3 -0
- package/jwks/jwks.types.d.ts.map +1 -1
- package/machine-id/index.d.ts +2 -0
- package/machine-id/index.d.ts.map +1 -0
- package/machine-id/machine-id.d.ts +28 -0
- package/machine-id/machine-id.d.ts.map +1 -0
- package/options/app-auth.schema.d.ts +272 -0
- package/options/app-auth.schema.d.ts.map +1 -0
- package/options/index.d.ts +15 -0
- package/options/index.d.ts.map +1 -0
- package/options/interfaces.d.ts +250 -0
- package/options/interfaces.d.ts.map +1 -0
- package/options/orchestrated.schema.d.ts +446 -0
- package/options/orchestrated.schema.d.ts.map +1 -0
- package/options/public.schema.d.ts +19 -0
- package/options/public.schema.d.ts.map +1 -0
- package/options/schema.d.ts +265 -0
- package/options/schema.d.ts.map +1 -0
- package/options/shared.schemas.d.ts +128 -0
- package/options/shared.schemas.d.ts.map +1 -0
- package/options/transparent.schema.d.ts +33 -0
- package/options/transparent.schema.d.ts.map +1 -0
- package/options/typecheck.d.ts +2 -0
- package/options/typecheck.d.ts.map +1 -0
- package/options/utils.d.ts +33 -0
- package/options/utils.d.ts.map +1 -0
- package/package.json +18 -3
- package/session/encrypted-authorization-vault.d.ts +182 -0
- package/session/encrypted-authorization-vault.d.ts.map +1 -0
- package/session/federated-auth.session.d.ts +252 -0
- package/session/federated-auth.session.d.ts.map +1 -0
- package/session/index.d.ts +21 -1
- package/session/index.d.ts.map +1 -1
- package/session/orchestrated-token.store.d.ts +155 -0
- package/session/orchestrated-token.store.d.ts.map +1 -0
- package/session/redis-session.store.d.ts +93 -0
- package/session/redis-session.store.d.ts.map +1 -0
- package/session/session-crypto.d.ts +84 -0
- package/session/session-crypto.d.ts.map +1 -0
- package/session/session-rate-limiter.d.ts +114 -0
- package/session/session-rate-limiter.d.ts.map +1 -0
- package/session/session.transport.d.ts +11 -0
- package/session/session.transport.d.ts.map +1 -0
- package/session/session.types.d.ts +66 -0
- package/session/session.types.d.ts.map +1 -0
- package/session/token.refresh.d.ts +61 -0
- package/session/token.refresh.d.ts.map +1 -0
- package/session/transport-session.types.d.ts +479 -0
- package/session/transport-session.types.d.ts.map +1 -0
- package/session/utils/auth-token.utils.d.ts +12 -0
- package/session/utils/auth-token.utils.d.ts.map +1 -0
- package/session/utils/index.d.ts +2 -0
- package/session/utils/index.d.ts.map +1 -1
- package/session/utils/session-crypto.utils.d.ts +30 -0
- package/session/utils/session-crypto.utils.d.ts.map +1 -0
- package/session/vercel-kv-session.store.d.ts +123 -0
- package/session/vercel-kv-session.store.d.ts.map +1 -0
- package/utils/authorization-id.utils.d.ts +12 -0
- package/utils/authorization-id.utils.d.ts.map +1 -0
- package/utils/index.d.ts +1 -0
- package/utils/index.d.ts.map +1 -1
- package/vault/auth-providers.accessor.d.ts +154 -0
- package/vault/auth-providers.accessor.d.ts.map +1 -0
- package/vault/auth-providers.accessor.impl.d.ts +54 -0
- package/vault/auth-providers.accessor.impl.d.ts.map +1 -0
- package/vault/auth-providers.registry.d.ts +111 -0
- package/vault/auth-providers.registry.d.ts.map +1 -0
- package/vault/auth-providers.types.d.ts +3 -3
- package/vault/auth-providers.vault.d.ts +94 -0
- package/vault/auth-providers.vault.d.ts.map +1 -0
- package/vault/credential-loaders/eager-loader.d.ts +47 -0
- package/vault/credential-loaders/eager-loader.d.ts.map +1 -0
- package/vault/credential-loaders/index.d.ts +7 -0
- package/vault/credential-loaders/index.d.ts.map +1 -0
- package/vault/credential-loaders/lazy-loader.d.ts +54 -0
- package/vault/credential-loaders/lazy-loader.d.ts.map +1 -0
- package/vault/index.d.ts +9 -0
- package/vault/index.d.ts.map +1 -1
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { Redis } from 'ioredis';
|
|
2
|
+
import { SessionStore, StoredSession, RedisConfig, SessionSecurityConfig } from './transport-session.types';
|
|
3
|
+
import type { AuthLogger } from '../common/auth-logger.interface';
|
|
4
|
+
/**
|
|
5
|
+
* Extended Redis configuration with security options.
|
|
6
|
+
*/
|
|
7
|
+
export interface RedisSessionStoreConfig extends RedisConfig {
|
|
8
|
+
/** Security hardening options */
|
|
9
|
+
security?: SessionSecurityConfig;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Redis-backed session store implementation
|
|
13
|
+
*
|
|
14
|
+
* Provides persistent session storage for distributed deployments.
|
|
15
|
+
* Sessions are stored as JSON with optional TTL.
|
|
16
|
+
* Uses @frontmcp/utils RedisStorageAdapter internally.
|
|
17
|
+
*
|
|
18
|
+
* Security features (configurable via security option):
|
|
19
|
+
* - HMAC signing: Detects session data tampering
|
|
20
|
+
* - Rate limiting: Prevents session enumeration attacks
|
|
21
|
+
* - Max lifetime: Prevents indefinite session extension
|
|
22
|
+
*/
|
|
23
|
+
export declare class RedisSessionStore implements SessionStore {
|
|
24
|
+
private readonly storage;
|
|
25
|
+
private readonly keyPrefix;
|
|
26
|
+
private readonly defaultTtlMs;
|
|
27
|
+
private readonly logger?;
|
|
28
|
+
private externalInstance;
|
|
29
|
+
private readonly security;
|
|
30
|
+
private readonly rateLimiter?;
|
|
31
|
+
constructor(config: RedisSessionStoreConfig | {
|
|
32
|
+
redis: Redis;
|
|
33
|
+
keyPrefix?: string;
|
|
34
|
+
defaultTtlMs?: number;
|
|
35
|
+
security?: SessionSecurityConfig;
|
|
36
|
+
}, logger?: AuthLogger);
|
|
37
|
+
/**
|
|
38
|
+
* Get the full key for a session ID (without prefix, adapter handles it)
|
|
39
|
+
* @throws Error if sessionId is empty
|
|
40
|
+
*/
|
|
41
|
+
private validateSessionId;
|
|
42
|
+
/**
|
|
43
|
+
* Ensure the storage adapter is connected
|
|
44
|
+
*/
|
|
45
|
+
private ensureConnected;
|
|
46
|
+
/**
|
|
47
|
+
* Get a stored session by ID
|
|
48
|
+
*
|
|
49
|
+
* Note: Uses atomic GETEX to extend TTL while reading, preventing race conditions
|
|
50
|
+
* where concurrent readers might resurrect expired sessions.
|
|
51
|
+
*
|
|
52
|
+
* @param sessionId - The session ID to look up
|
|
53
|
+
* @param options - Optional parameters for rate limiting
|
|
54
|
+
* @param options.clientIdentifier - Client identifier (e.g., IP address) for rate limiting.
|
|
55
|
+
* When provided, rate limiting is applied per-client to prevent session enumeration.
|
|
56
|
+
* If not provided, falls back to sessionId which provides DoS protection per-session.
|
|
57
|
+
*/
|
|
58
|
+
get(sessionId: string, options?: {
|
|
59
|
+
clientIdentifier?: string;
|
|
60
|
+
}): Promise<StoredSession | null>;
|
|
61
|
+
/**
|
|
62
|
+
* Store a session with optional TTL
|
|
63
|
+
*/
|
|
64
|
+
set(sessionId: string, session: StoredSession, ttlMs?: number): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Delete a session
|
|
67
|
+
*/
|
|
68
|
+
delete(sessionId: string): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Check if a session exists
|
|
71
|
+
*/
|
|
72
|
+
exists(sessionId: string): Promise<boolean>;
|
|
73
|
+
/**
|
|
74
|
+
* Allocate a new session ID
|
|
75
|
+
*/
|
|
76
|
+
allocId(): string;
|
|
77
|
+
/**
|
|
78
|
+
* Disconnect from Redis (only if we created the connection)
|
|
79
|
+
*/
|
|
80
|
+
disconnect(): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Get the underlying Redis client (for advanced use cases)
|
|
83
|
+
*/
|
|
84
|
+
getRedisClient(): Redis | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* Test Redis connection by sending a PING command.
|
|
87
|
+
* Useful for validating connection on startup.
|
|
88
|
+
*
|
|
89
|
+
* @returns true if connection is healthy, false otherwise
|
|
90
|
+
*/
|
|
91
|
+
ping(): Promise<boolean>;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=redis-session.store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-session.store.d.ts","sourceRoot":"","sources":["../../src/session/redis-session.store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EACL,YAAY,EACZ,aAAa,EACb,WAAW,EAEX,qBAAqB,EACtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAKlE;;GAEG;AACH,MAAM,WAAW,uBAAwB,SAAQ,WAAW;IAC1D,iCAAiC;IACjC,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAClC;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAkB,YAAW,YAAY;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAa;IACrC,OAAO,CAAC,gBAAgB,CAAS;IAGjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAqB;gBAGhD,MAAM,EACF,uBAAuB,GACvB;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,qBAAqB,CAAA;KAAE,EACjG,MAAM,CAAC,EAAE,UAAU;IAyCrB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAMzB;;OAEG;YACW,eAAe;IAK7B;;;;;;;;;;;OAWG;IACG,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAuIpG;;OAEG;IACG,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BnF;;OAEG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9C;;OAEG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMjD;;OAEG;IACH,OAAO,IAAI,MAAM;IAIjB;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMjC;;OAEG;IACH,cAAc,IAAI,KAAK,GAAG,SAAS;IAInC;;;;;OAKG;IACG,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;CAW/B"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Cryptographic Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides HMAC signing and verification for stored session data.
|
|
5
|
+
* Protects against session data tampering when stored in external
|
|
6
|
+
* systems like Redis that don't provide application-level integrity.
|
|
7
|
+
*
|
|
8
|
+
* This module wraps the generic @frontmcp/utils HMAC signing utilities
|
|
9
|
+
* with session-specific types and environment-based secret handling.
|
|
10
|
+
*/
|
|
11
|
+
import { isSignedData, type SignedData } from '@frontmcp/utils';
|
|
12
|
+
import type { StoredSession } from './transport-session.types';
|
|
13
|
+
/**
|
|
14
|
+
* Signed session wrapper structure.
|
|
15
|
+
* Contains the session data and its HMAC signature.
|
|
16
|
+
*/
|
|
17
|
+
export type SignedSession = SignedData<StoredSession>;
|
|
18
|
+
/**
|
|
19
|
+
* Configuration for session signing.
|
|
20
|
+
*/
|
|
21
|
+
export interface SessionSigningConfig {
|
|
22
|
+
/**
|
|
23
|
+
* The secret key used for HMAC signing.
|
|
24
|
+
* Should be at least 32 bytes for security.
|
|
25
|
+
* Uses MCP_SESSION_SECRET environment variable if not provided.
|
|
26
|
+
*/
|
|
27
|
+
secret?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Sign a stored session with HMAC-SHA256.
|
|
31
|
+
*
|
|
32
|
+
* Creates a tamper-evident wrapper around the session data.
|
|
33
|
+
* Any modification to the session will invalidate the signature.
|
|
34
|
+
*
|
|
35
|
+
* @param session - The session to sign
|
|
36
|
+
* @param config - Optional signing configuration
|
|
37
|
+
* @returns JSON string containing signed session
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const signed = signSession(session);
|
|
42
|
+
* await redis.set(key, signed);
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function signSession(session: StoredSession, config?: SessionSigningConfig): string;
|
|
46
|
+
/**
|
|
47
|
+
* Verify and extract a signed session.
|
|
48
|
+
*
|
|
49
|
+
* Validates the HMAC signature and returns the session if valid.
|
|
50
|
+
* Returns null if the signature is invalid or the data is corrupted.
|
|
51
|
+
*
|
|
52
|
+
* @param signedData - JSON string from signSession()
|
|
53
|
+
* @param config - Optional signing configuration
|
|
54
|
+
* @returns The verified session or null if invalid
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const raw = await redis.get(key);
|
|
59
|
+
* const session = verifySession(raw);
|
|
60
|
+
* if (!session) {
|
|
61
|
+
* // Session was tampered with or corrupted
|
|
62
|
+
* await redis.del(key);
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare function verifySession(signedData: string, config?: SessionSigningConfig): StoredSession | null;
|
|
67
|
+
/**
|
|
68
|
+
* Check if a stored value is a signed session.
|
|
69
|
+
* Useful for migrating from unsigned to signed sessions.
|
|
70
|
+
*
|
|
71
|
+
* @param data - Raw data from storage
|
|
72
|
+
* @returns true if the data appears to be a signed session
|
|
73
|
+
*/
|
|
74
|
+
export { isSignedData as isSignedSession };
|
|
75
|
+
/**
|
|
76
|
+
* Verify or parse a session, supporting both signed and unsigned formats.
|
|
77
|
+
* Useful for backwards compatibility during migration.
|
|
78
|
+
*
|
|
79
|
+
* @param data - Raw data from storage
|
|
80
|
+
* @param config - Optional signing configuration
|
|
81
|
+
* @returns The session (verified if signed, parsed if unsigned) or null
|
|
82
|
+
*/
|
|
83
|
+
export declare function verifyOrParseSession(data: string, config?: SessionSigningConfig): StoredSession | null;
|
|
84
|
+
//# sourceMappingURL=session-crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-crypto.d.ts","sourceRoot":"","sources":["../../src/session/session-crypto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAGL,YAAY,EAEZ,KAAK,UAAU,EAEhB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAG/D;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA4BD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,oBAAoB,GAAG,MAAM,CAEzF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,oBAAoB,GAAG,aAAa,GAAG,IAAI,CAErG;AAED;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,IAAI,eAAe,EAAE,CAAC;AAE3C;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,oBAAoB,GAAG,aAAa,GAAG,IAAI,CAEtG"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Rate Limiter
|
|
3
|
+
*
|
|
4
|
+
* Simple sliding window rate limiter for session lookup operations.
|
|
5
|
+
* Protects against session enumeration attacks by limiting the rate
|
|
6
|
+
* of session lookups per client IP or identifier.
|
|
7
|
+
*/
|
|
8
|
+
export interface SessionRateLimiterConfig {
|
|
9
|
+
/**
|
|
10
|
+
* Time window in milliseconds for rate limiting.
|
|
11
|
+
* @default 60000 (1 minute)
|
|
12
|
+
*/
|
|
13
|
+
windowMs?: number;
|
|
14
|
+
/**
|
|
15
|
+
* Maximum requests allowed per window per key.
|
|
16
|
+
* @default 100
|
|
17
|
+
*/
|
|
18
|
+
maxRequests?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Interval in milliseconds for automatic cleanup of expired entries.
|
|
21
|
+
* Set to 0 to disable automatic cleanup.
|
|
22
|
+
* @default 60000 (1 minute)
|
|
23
|
+
*/
|
|
24
|
+
cleanupIntervalMs?: number;
|
|
25
|
+
}
|
|
26
|
+
export interface RateLimitResult {
|
|
27
|
+
/** Whether the request is allowed */
|
|
28
|
+
allowed: boolean;
|
|
29
|
+
/** Number of remaining requests in the current window */
|
|
30
|
+
remaining: number;
|
|
31
|
+
/** Timestamp when the rate limit resets (epoch ms) */
|
|
32
|
+
resetAt: number;
|
|
33
|
+
/** Time to wait before retry (only set if not allowed) */
|
|
34
|
+
retryAfterMs?: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Sliding window rate limiter for session operations.
|
|
38
|
+
*
|
|
39
|
+
* Uses an in-memory sliding window algorithm to track request timestamps
|
|
40
|
+
* per key (typically client IP). Automatically cleans up expired entries.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* const rateLimiter = new SessionRateLimiter({ maxRequests: 50, windowMs: 60000 });
|
|
45
|
+
*
|
|
46
|
+
* // In session store get()
|
|
47
|
+
* const clientIp = getClientIp(req);
|
|
48
|
+
* const result = rateLimiter.check(clientIp);
|
|
49
|
+
* if (!result.allowed) {
|
|
50
|
+
* throw new RateLimitError(Math.ceil(result.retryAfterMs / 1000));
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare class SessionRateLimiter {
|
|
55
|
+
private readonly windowMs;
|
|
56
|
+
private readonly maxRequests;
|
|
57
|
+
private readonly requests;
|
|
58
|
+
private cleanupTimer;
|
|
59
|
+
constructor(config?: SessionRateLimiterConfig);
|
|
60
|
+
/**
|
|
61
|
+
* Check if a request is allowed for the given key.
|
|
62
|
+
*
|
|
63
|
+
* @param key - Identifier for rate limiting (e.g., client IP, session ID prefix)
|
|
64
|
+
* @returns Rate limit result with allowed status and metadata
|
|
65
|
+
*/
|
|
66
|
+
check(key: string): RateLimitResult;
|
|
67
|
+
/**
|
|
68
|
+
* Check if a request would be allowed without recording it.
|
|
69
|
+
* Useful for pre-checking without consuming quota.
|
|
70
|
+
*
|
|
71
|
+
* @param key - Identifier for rate limiting
|
|
72
|
+
* @returns true if request would be allowed
|
|
73
|
+
*/
|
|
74
|
+
wouldAllow(key: string): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Reset rate limit for a specific key.
|
|
77
|
+
* Useful for testing or after successful authentication.
|
|
78
|
+
*
|
|
79
|
+
* @param key - Identifier to reset
|
|
80
|
+
*/
|
|
81
|
+
reset(key: string): void;
|
|
82
|
+
/**
|
|
83
|
+
* Clean up expired entries from all keys.
|
|
84
|
+
* Called automatically on configured interval, but can be called manually.
|
|
85
|
+
*/
|
|
86
|
+
cleanup(): void;
|
|
87
|
+
/**
|
|
88
|
+
* Get current statistics for monitoring.
|
|
89
|
+
*/
|
|
90
|
+
getStats(): {
|
|
91
|
+
totalKeys: number;
|
|
92
|
+
totalRequests: number;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Stop the automatic cleanup timer.
|
|
96
|
+
* Call this when disposing of the rate limiter.
|
|
97
|
+
*/
|
|
98
|
+
dispose(): void;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Default shared rate limiter instance for simple single-process scenarios.
|
|
102
|
+
*
|
|
103
|
+
* WARNING: This singleton shares state across all usages in the same process.
|
|
104
|
+
* For most use cases, create a new SessionRateLimiter instance per session store.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* // Preferred: Create instance per store
|
|
108
|
+
* this.rateLimiter = new SessionRateLimiter({ windowMs: 60000, maxRequests: 100 });
|
|
109
|
+
*
|
|
110
|
+
* // Only use default for simple single-tenant scenarios
|
|
111
|
+
* import { defaultSessionRateLimiter } from './session-rate-limiter';
|
|
112
|
+
*/
|
|
113
|
+
export declare const defaultSessionRateLimiter: SessionRateLimiter;
|
|
114
|
+
//# sourceMappingURL=session-rate-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-rate-limiter.d.ts","sourceRoot":"","sources":["../../src/session/session-rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoC;IAC7D,OAAO,CAAC,YAAY,CAA+B;gBAEvC,MAAM,GAAE,wBAA6B;IAajD;;;;;OAKG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;IAuCnC;;;;;;OAMG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAWhC;;;;;OAKG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIxB;;;OAGG;IACH,OAAO,IAAI,IAAI;IAcf;;OAEG;IACH,QAAQ,IAAI;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE;IAWxD;;;OAGG;IACH,OAAO,IAAI,IAAI;CAOhB;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,yBAAyB,oBAA2B,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class TransportIdGenerator {
|
|
2
|
+
/**
|
|
3
|
+
* Create a transport session ID.
|
|
4
|
+
* Always generates JWT-style IDs for distributed session support.
|
|
5
|
+
*
|
|
6
|
+
* @param _mode - Deprecated parameter, kept for backwards compatibility
|
|
7
|
+
* @returns A JWT-style transport session ID (UUID without dashes)
|
|
8
|
+
*/
|
|
9
|
+
static createId(_mode?: 'jwt'): string;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=session.transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.transport.d.ts","sourceRoot":"","sources":["../../src/session/session.transport.ts"],"names":[],"mappings":"AAGA,qBAAa,oBAAoB;IAC/B;;;;;;OAMG;IACH,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM;CAIvC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { SessionUser } from '../common/session-user.types';
|
|
2
|
+
/** Session mode identifier. */
|
|
3
|
+
export type SessionMode = 'mcp';
|
|
4
|
+
/**
|
|
5
|
+
* How a single provider's access token is represented inside the session payload.
|
|
6
|
+
*/
|
|
7
|
+
export type ProviderEmbedMode = 'store-only' | 'encrypted' | 'plain' | 'ref';
|
|
8
|
+
/** AES-256-GCM encrypted blob, base64url fields. */
|
|
9
|
+
export type EncBlob = {
|
|
10
|
+
alg: 'A256GCM';
|
|
11
|
+
iv: string;
|
|
12
|
+
tag: string;
|
|
13
|
+
data: string;
|
|
14
|
+
};
|
|
15
|
+
export type ProviderSnapshot = {
|
|
16
|
+
id: string;
|
|
17
|
+
exp?: number;
|
|
18
|
+
payload?: Record<string, unknown>;
|
|
19
|
+
apps?: Array<{
|
|
20
|
+
id: string;
|
|
21
|
+
toolIds?: string[];
|
|
22
|
+
}>;
|
|
23
|
+
embedMode: ProviderEmbedMode;
|
|
24
|
+
token?: string;
|
|
25
|
+
tokenEnc?: {
|
|
26
|
+
alg: 'A256GCM';
|
|
27
|
+
iv: string;
|
|
28
|
+
tag: string;
|
|
29
|
+
data: string;
|
|
30
|
+
};
|
|
31
|
+
refreshTokenEnc?: {
|
|
32
|
+
alg: 'A256GCM';
|
|
33
|
+
iv: string;
|
|
34
|
+
tag: string;
|
|
35
|
+
data: string;
|
|
36
|
+
};
|
|
37
|
+
secretRefId?: string;
|
|
38
|
+
refreshRefId?: string;
|
|
39
|
+
};
|
|
40
|
+
/** Arguments required to create a session from verified auth data. */
|
|
41
|
+
export type CreateSessionArgs = {
|
|
42
|
+
token: string;
|
|
43
|
+
sessionId?: string;
|
|
44
|
+
claims: Record<string, unknown>;
|
|
45
|
+
user: SessionUser;
|
|
46
|
+
authorizedProviders?: Record<string, ProviderSnapshot>;
|
|
47
|
+
authorizedProviderIds?: string[];
|
|
48
|
+
authorizedApps?: Record<string, {
|
|
49
|
+
id: string;
|
|
50
|
+
toolIds: string[];
|
|
51
|
+
}>;
|
|
52
|
+
authorizedAppIds?: string[];
|
|
53
|
+
authorizedResources?: string[];
|
|
54
|
+
scopes?: string[];
|
|
55
|
+
authorizedTools?: Record<string, {
|
|
56
|
+
executionPath: [string, string];
|
|
57
|
+
details?: Record<string, unknown>;
|
|
58
|
+
}>;
|
|
59
|
+
authorizedToolIds?: string[];
|
|
60
|
+
authorizedPrompts?: Record<string, {
|
|
61
|
+
executionPath: [string, string];
|
|
62
|
+
details?: Record<string, unknown>;
|
|
63
|
+
}>;
|
|
64
|
+
authorizedPromptIds?: string[];
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=session.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.types.d.ts","sourceRoot":"","sources":["../../src/session/session.types.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAE3D,+BAA+B;AAC/B,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC;AAEhC;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,YAAY,GACZ,WAAW,GACX,OAAO,GACP,KAAK,CAAC;AAEV,oDAAoD;AACpD,MAAM,MAAM,OAAO,GAAG;IAAE,GAAG,EAAE,SAAS,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACjD,SAAS,EAAE,iBAAiB,CAAC;IAG7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE;QAAE,GAAG,EAAE,SAAS,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,eAAe,CAAC,EAAE;QAAE,GAAG,EAAE,SAAS,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAG5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,sEAAsE;AACtE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,IAAI,EAAE,WAAW,CAAC;IAElB,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACvD,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACnE,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IACzG,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IAC3G,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { ProviderSnapshot } from './session.types';
|
|
2
|
+
import type { TokenStore } from './token.store';
|
|
3
|
+
import type { TokenVault } from './token.vault';
|
|
4
|
+
export type TokenRefreshCtx = {
|
|
5
|
+
/** The provider we're refreshing for. */
|
|
6
|
+
providerId: string;
|
|
7
|
+
/** Caller-provided session facade (only what a refresher may need). */
|
|
8
|
+
session: {
|
|
9
|
+
id: string;
|
|
10
|
+
scopeId: string;
|
|
11
|
+
/** Current snapshot (mutable by the session after refresh). */
|
|
12
|
+
authorizedProviders: Record<string, ProviderSnapshot>;
|
|
13
|
+
/** Optional helper if the refresher wants to call other providers. */
|
|
14
|
+
getToken?: (pid: string, opts?: {
|
|
15
|
+
refreshSkewSec?: number;
|
|
16
|
+
forceRefresh?: boolean;
|
|
17
|
+
}) => Promise<string | undefined>;
|
|
18
|
+
};
|
|
19
|
+
/** Current access token (if known); may be undefined/expired. */
|
|
20
|
+
accessToken?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Refresh token (if accessible by the embedding mode).
|
|
23
|
+
* For `ref` mode this is usually `undefined`; the refresher should use `store`/`vault`.
|
|
24
|
+
*/
|
|
25
|
+
refreshToken?: string;
|
|
26
|
+
/** The snapshot we're refreshing (same as authorizedProviders[providerId]). */
|
|
27
|
+
snapshot: ProviderSnapshot;
|
|
28
|
+
/**
|
|
29
|
+
* External storage interfaces, present for `ref` mode to avoid revealing plaintext tokens.
|
|
30
|
+
* - `store` holds opaque encrypted blobs
|
|
31
|
+
* - `vault` handles AEAD encryption/decryption of secrets
|
|
32
|
+
*/
|
|
33
|
+
store?: TokenStore;
|
|
34
|
+
vault?: TokenVault;
|
|
35
|
+
};
|
|
36
|
+
export type TokenRefreshResult = {
|
|
37
|
+
/** New access token (if rotated). */
|
|
38
|
+
accessToken?: string;
|
|
39
|
+
/** New refresh token (optional). */
|
|
40
|
+
refreshToken?: string;
|
|
41
|
+
/** New absolute expiry (seconds since epoch preferred; ms also accepted). */
|
|
42
|
+
exp: number;
|
|
43
|
+
/** Optional opaque payload returned by the AS (id_token claims, etc.). */
|
|
44
|
+
payload?: Record<string, unknown>;
|
|
45
|
+
};
|
|
46
|
+
export type TokenRefresher = (ctx: TokenRefreshCtx) => Promise<TokenRefreshResult>;
|
|
47
|
+
/** Convert seconds/ms epoch or Date to epoch seconds. */
|
|
48
|
+
export declare function toEpochSeconds(exp?: number | Date): number | undefined;
|
|
49
|
+
/** Returns true if `exp` will occur within `skewSec` from now (or already past). */
|
|
50
|
+
export declare function isSoonExpiring(exp?: number | Date, skewSec?: number): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Synchronous check against a provider snapshot's `exp` field.
|
|
53
|
+
* Note: In `ref` mode the exact expiry may live in the store; this helper
|
|
54
|
+
* intentionally remains synchronous and only uses the snapshot's `exp`.
|
|
55
|
+
*/
|
|
56
|
+
export declare function isSoonExpiringProvider(sessionLike: {
|
|
57
|
+
authorizedProviders: Record<string, ProviderSnapshot>;
|
|
58
|
+
}, providerId: string, skewSec?: number): boolean;
|
|
59
|
+
/** Best-effort extraction of `exp` from a JWT without verification. */
|
|
60
|
+
export declare function tryJwtExp(token?: string): number | undefined;
|
|
61
|
+
//# sourceMappingURL=token.refresh.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.refresh.d.ts","sourceRoot":"","sources":["../../src/session/token.refresh.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAOhD,MAAM,MAAM,eAAe,GAAG;IAC5B,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAC;IAEnB,uEAAuE;IACvE,OAAO,EAAE;QACP,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,+DAA+D;QAC/D,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;QACtD,sEAAsE;QACtE,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;YAAE,cAAc,CAAC,EAAE,MAAM,CAAC;YAAC,YAAY,CAAC,EAAE,OAAO,CAAA;SAAE,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;KACrH,CAAC;IAEF,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,+EAA+E;IAC/E,QAAQ,EAAE,gBAAgB,CAAC;IAE3B;;;;OAIG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6EAA6E;IAC7E,GAAG,EAAE,MAAM,CAAC;IACZ,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAMnF,yDAAyD;AACzD,wBAAgB,cAAc,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,SAAS,CAKtE;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,SAAK,GAAG,OAAO,CAKzE;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE;IAAE,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;CAAE,EACtE,UAAU,EAAE,MAAM,EAClB,OAAO,SAAK,GACX,OAAO,CAIT;AAMD,uEAAuE;AACvE,wBAAgB,SAAS,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAW5D"}
|