@blokjs/runner 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Blok.d.ts +19 -0
- package/dist/Blok.js +184 -0
- package/dist/Blok.js.map +1 -0
- package/dist/BlokResponse.d.ts +16 -0
- package/dist/BlokResponse.js +28 -0
- package/dist/BlokResponse.js.map +1 -0
- package/dist/Configuration.d.ts +37 -0
- package/dist/Configuration.js +248 -0
- package/dist/Configuration.js.map +1 -0
- package/dist/ConfigurationResolver.d.ts +7 -0
- package/dist/ConfigurationResolver.js +15 -0
- package/dist/ConfigurationResolver.js.map +1 -0
- package/dist/DefaultLogger.d.ts +65 -0
- package/dist/DefaultLogger.js +101 -0
- package/dist/DefaultLogger.js.map +1 -0
- package/dist/LocalStorage.d.ts +7 -0
- package/dist/LocalStorage.js +56 -0
- package/dist/LocalStorage.js.map +1 -0
- package/dist/MemoryUsage.d.ts +22 -0
- package/dist/MemoryUsage.js +83 -0
- package/dist/MemoryUsage.js.map +1 -0
- package/dist/NodeMap.d.ts +7 -0
- package/dist/NodeMap.js +13 -0
- package/dist/NodeMap.js.map +1 -0
- package/dist/ResolverBase.d.ts +8 -0
- package/dist/ResolverBase.js +18 -0
- package/dist/ResolverBase.js.map +1 -0
- package/dist/Runner.d.ts +25 -0
- package/dist/Runner.js +32 -0
- package/dist/Runner.js.map +1 -0
- package/dist/RunnerNode.d.ts +9 -0
- package/dist/RunnerNode.js +8 -0
- package/dist/RunnerNode.js.map +1 -0
- package/dist/RunnerNodeBase.d.ts +4 -0
- package/dist/RunnerNodeBase.js +3 -0
- package/dist/RunnerNodeBase.js.map +1 -0
- package/dist/RunnerSteps.d.ts +14 -0
- package/dist/RunnerSteps.js +110 -0
- package/dist/RunnerSteps.js.map +1 -0
- package/dist/RuntimeAdapterNode.d.ts +19 -0
- package/dist/RuntimeAdapterNode.js +87 -0
- package/dist/RuntimeAdapterNode.js.map +1 -0
- package/dist/RuntimeRegistry.d.ts +61 -0
- package/dist/RuntimeRegistry.js +87 -0
- package/dist/RuntimeRegistry.js.map +1 -0
- package/dist/TriggerBase.d.ts +119 -0
- package/dist/TriggerBase.js +413 -0
- package/dist/TriggerBase.js.map +1 -0
- package/dist/adapters/BunRuntimeAdapter.d.ts +38 -0
- package/dist/adapters/BunRuntimeAdapter.js +169 -0
- package/dist/adapters/BunRuntimeAdapter.js.map +1 -0
- package/dist/adapters/DockerRuntimeAdapter.d.ts +85 -0
- package/dist/adapters/DockerRuntimeAdapter.js +298 -0
- package/dist/adapters/DockerRuntimeAdapter.js.map +1 -0
- package/dist/adapters/HttpRuntimeAdapter.d.ts +58 -0
- package/dist/adapters/HttpRuntimeAdapter.js +152 -0
- package/dist/adapters/HttpRuntimeAdapter.js.map +1 -0
- package/dist/adapters/NodeJsRuntimeAdapter.d.ts +23 -0
- package/dist/adapters/NodeJsRuntimeAdapter.js +67 -0
- package/dist/adapters/NodeJsRuntimeAdapter.js.map +1 -0
- package/dist/adapters/RuntimeAdapter.d.ts +42 -0
- package/dist/adapters/RuntimeAdapter.js +2 -0
- package/dist/adapters/RuntimeAdapter.js.map +1 -0
- package/dist/adapters/WasmRuntimeAdapter.d.ts +69 -0
- package/dist/adapters/WasmRuntimeAdapter.js +279 -0
- package/dist/adapters/WasmRuntimeAdapter.js.map +1 -0
- package/dist/cache/NodeResultCache.d.ts +286 -0
- package/dist/cache/NodeResultCache.js +499 -0
- package/dist/cache/NodeResultCache.js.map +1 -0
- package/dist/cache/index.d.ts +1 -0
- package/dist/cache/index.js +2 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cost/CostEstimator.d.ts +57 -0
- package/dist/cost/CostEstimator.js +171 -0
- package/dist/cost/CostEstimator.js.map +1 -0
- package/dist/cost/index.d.ts +4 -0
- package/dist/cost/index.js +3 -0
- package/dist/cost/index.js.map +1 -0
- package/dist/cost/pricing.d.ts +24 -0
- package/dist/cost/pricing.js +169 -0
- package/dist/cost/pricing.js.map +1 -0
- package/dist/defineNode.d.ts +155 -0
- package/dist/defineNode.js +191 -0
- package/dist/defineNode.js.map +1 -0
- package/dist/graphql/GraphQLSchemaGenerator.d.ts +129 -0
- package/dist/graphql/GraphQLSchemaGenerator.js +425 -0
- package/dist/graphql/GraphQLSchemaGenerator.js.map +1 -0
- package/dist/hmr/FileWatcher.d.ts +62 -0
- package/dist/hmr/FileWatcher.js +185 -0
- package/dist/hmr/FileWatcher.js.map +1 -0
- package/dist/hmr/HmrDevConsole.d.ts +13 -0
- package/dist/hmr/HmrDevConsole.js +46 -0
- package/dist/hmr/HmrDevConsole.js.map +1 -0
- package/dist/hmr/HotReloadManager.d.ts +84 -0
- package/dist/hmr/HotReloadManager.js +195 -0
- package/dist/hmr/HotReloadManager.js.map +1 -0
- package/dist/hmr/index.d.ts +39 -0
- package/dist/hmr/index.js +38 -0
- package/dist/hmr/index.js.map +1 -0
- package/dist/index.d.ts +107 -0
- package/dist/index.js +107 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/APMIntegration.d.ts +141 -0
- package/dist/integrations/APMIntegration.js +212 -0
- package/dist/integrations/APMIntegration.js.map +1 -0
- package/dist/integrations/AzureMonitorIntegration.d.ts +118 -0
- package/dist/integrations/AzureMonitorIntegration.js +254 -0
- package/dist/integrations/AzureMonitorIntegration.js.map +1 -0
- package/dist/integrations/CloudWatchIntegration.d.ts +135 -0
- package/dist/integrations/CloudWatchIntegration.js +293 -0
- package/dist/integrations/CloudWatchIntegration.js.map +1 -0
- package/dist/integrations/SentryIntegration.d.ts +153 -0
- package/dist/integrations/SentryIntegration.js +200 -0
- package/dist/integrations/SentryIntegration.js.map +1 -0
- package/dist/integrations/index.d.ts +19 -0
- package/dist/integrations/index.js +16 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/marketplace/RuntimeAutoScaler.d.ts +148 -0
- package/dist/marketplace/RuntimeAutoScaler.js +366 -0
- package/dist/marketplace/RuntimeAutoScaler.js.map +1 -0
- package/dist/marketplace/RuntimeCatalog.d.ts +174 -0
- package/dist/marketplace/RuntimeCatalog.js +339 -0
- package/dist/marketplace/RuntimeCatalog.js.map +1 -0
- package/dist/marketplace/RuntimeDiscovery.d.ts +86 -0
- package/dist/marketplace/RuntimeDiscovery.js +219 -0
- package/dist/marketplace/RuntimeDiscovery.js.map +1 -0
- package/dist/marketplace/RuntimeHealthMonitor.d.ts +100 -0
- package/dist/marketplace/RuntimeHealthMonitor.js +241 -0
- package/dist/marketplace/RuntimeHealthMonitor.js.map +1 -0
- package/dist/marketplace/RuntimeMetricsDashboard.d.ts +113 -0
- package/dist/marketplace/RuntimeMetricsDashboard.js +293 -0
- package/dist/marketplace/RuntimeMetricsDashboard.js.map +1 -0
- package/dist/monitoring/CircuitBreaker.d.ts +107 -0
- package/dist/monitoring/CircuitBreaker.js +238 -0
- package/dist/monitoring/CircuitBreaker.js.map +1 -0
- package/dist/monitoring/DistributedTracer.d.ts +125 -0
- package/dist/monitoring/DistributedTracer.js +230 -0
- package/dist/monitoring/DistributedTracer.js.map +1 -0
- package/dist/monitoring/HealthCheck.d.ts +54 -0
- package/dist/monitoring/HealthCheck.js +102 -0
- package/dist/monitoring/HealthCheck.js.map +1 -0
- package/dist/monitoring/PerformanceProfiler.d.ts +63 -0
- package/dist/monitoring/PerformanceProfiler.js +229 -0
- package/dist/monitoring/PerformanceProfiler.js.map +1 -0
- package/dist/monitoring/PrometheusBootstrap.d.ts +30 -0
- package/dist/monitoring/PrometheusBootstrap.js +71 -0
- package/dist/monitoring/PrometheusBootstrap.js.map +1 -0
- package/dist/monitoring/PrometheusMetricsBridge.d.ts +60 -0
- package/dist/monitoring/PrometheusMetricsBridge.js +216 -0
- package/dist/monitoring/PrometheusMetricsBridge.js.map +1 -0
- package/dist/monitoring/RateLimiter.d.ts +58 -0
- package/dist/monitoring/RateLimiter.js +128 -0
- package/dist/monitoring/RateLimiter.js.map +1 -0
- package/dist/monitoring/StructuredLogger.d.ts +131 -0
- package/dist/monitoring/StructuredLogger.js +207 -0
- package/dist/monitoring/StructuredLogger.js.map +1 -0
- package/dist/monitoring/TracingBootstrap.d.ts +69 -0
- package/dist/monitoring/TracingBootstrap.js +129 -0
- package/dist/monitoring/TracingBootstrap.js.map +1 -0
- package/dist/monitoring/TriggerMetricsCollector.d.ts +94 -0
- package/dist/monitoring/TriggerMetricsCollector.js +174 -0
- package/dist/monitoring/TriggerMetricsCollector.js.map +1 -0
- package/dist/monitoring/index.d.ts +9 -0
- package/dist/monitoring/index.js +10 -0
- package/dist/monitoring/index.js.map +1 -0
- package/dist/openapi/OpenAPIGenerator.d.ts +192 -0
- package/dist/openapi/OpenAPIGenerator.js +373 -0
- package/dist/openapi/OpenAPIGenerator.js.map +1 -0
- package/dist/openapi/index.d.ts +20 -0
- package/dist/openapi/index.js +20 -0
- package/dist/openapi/index.js.map +1 -0
- package/dist/security/ABAC.d.ts +224 -0
- package/dist/security/ABAC.js +380 -0
- package/dist/security/ABAC.js.map +1 -0
- package/dist/security/AuditLogger.d.ts +242 -0
- package/dist/security/AuditLogger.js +317 -0
- package/dist/security/AuditLogger.js.map +1 -0
- package/dist/security/AuthMiddleware.d.ts +163 -0
- package/dist/security/AuthMiddleware.js +274 -0
- package/dist/security/AuthMiddleware.js.map +1 -0
- package/dist/security/EncryptionAtRest.d.ts +206 -0
- package/dist/security/EncryptionAtRest.js +236 -0
- package/dist/security/EncryptionAtRest.js.map +1 -0
- package/dist/security/OAuthProvider.d.ts +334 -0
- package/dist/security/OAuthProvider.js +719 -0
- package/dist/security/OAuthProvider.js.map +1 -0
- package/dist/security/PIIDetector.d.ts +233 -0
- package/dist/security/PIIDetector.js +354 -0
- package/dist/security/PIIDetector.js.map +1 -0
- package/dist/security/RBAC.d.ts +143 -0
- package/dist/security/RBAC.js +285 -0
- package/dist/security/RBAC.js.map +1 -0
- package/dist/security/SecretManager.d.ts +652 -0
- package/dist/security/SecretManager.js +1146 -0
- package/dist/security/SecretManager.js.map +1 -0
- package/dist/security/TLSConfig.d.ts +305 -0
- package/dist/security/TLSConfig.js +550 -0
- package/dist/security/TLSConfig.js.map +1 -0
- package/dist/security/index.d.ts +79 -0
- package/dist/security/index.js +80 -0
- package/dist/security/index.js.map +1 -0
- package/dist/testing/TestHarness.d.ts +189 -0
- package/dist/testing/TestHarness.js +272 -0
- package/dist/testing/TestHarness.js.map +1 -0
- package/dist/testing/TestLogger.d.ts +103 -0
- package/dist/testing/TestLogger.js +153 -0
- package/dist/testing/TestLogger.js.map +1 -0
- package/dist/testing/WorkflowTestRunner.d.ts +172 -0
- package/dist/testing/WorkflowTestRunner.js +355 -0
- package/dist/testing/WorkflowTestRunner.js.map +1 -0
- package/dist/testing/index.d.ts +21 -0
- package/dist/testing/index.js +22 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/tracing/InMemoryRunStore.d.ts +44 -0
- package/dist/tracing/InMemoryRunStore.js +341 -0
- package/dist/tracing/InMemoryRunStore.js.map +1 -0
- package/dist/tracing/PostgresRunStore.d.ts +82 -0
- package/dist/tracing/PostgresRunStore.js +640 -0
- package/dist/tracing/PostgresRunStore.js.map +1 -0
- package/dist/tracing/RunStore.d.ts +38 -0
- package/dist/tracing/RunStore.js +2 -0
- package/dist/tracing/RunStore.js.map +1 -0
- package/dist/tracing/RunTracker.d.ts +75 -0
- package/dist/tracing/RunTracker.js +374 -0
- package/dist/tracing/RunTracker.js.map +1 -0
- package/dist/tracing/SqliteRunStore.d.ts +53 -0
- package/dist/tracing/SqliteRunStore.js +703 -0
- package/dist/tracing/SqliteRunStore.js.map +1 -0
- package/dist/tracing/TraceRouter.d.ts +47 -0
- package/dist/tracing/TraceRouter.js +904 -0
- package/dist/tracing/TraceRouter.js.map +1 -0
- package/dist/tracing/TracingLogger.d.ts +21 -0
- package/dist/tracing/TracingLogger.js +62 -0
- package/dist/tracing/TracingLogger.js.map +1 -0
- package/dist/tracing/createStore.d.ts +30 -0
- package/dist/tracing/createStore.js +75 -0
- package/dist/tracing/createStore.js.map +1 -0
- package/dist/tracing/index.d.ts +13 -0
- package/dist/tracing/index.js +9 -0
- package/dist/tracing/index.js.map +1 -0
- package/dist/tracing/sanitize.d.ts +7 -0
- package/dist/tracing/sanitize.js +95 -0
- package/dist/tracing/sanitize.js.map +1 -0
- package/dist/tracing/types.d.ts +178 -0
- package/dist/tracing/types.js +3 -0
- package/dist/tracing/types.js.map +1 -0
- package/dist/types/Average.d.ts +11 -0
- package/dist/types/Average.js +2 -0
- package/dist/types/Average.js.map +1 -0
- package/dist/types/Condition.d.ts +8 -0
- package/dist/types/Condition.js +2 -0
- package/dist/types/Condition.js.map +1 -0
- package/dist/types/Conditions.d.ts +5 -0
- package/dist/types/Conditions.js +2 -0
- package/dist/types/Conditions.js.map +1 -0
- package/dist/types/Config.d.ts +12 -0
- package/dist/types/Config.js +2 -0
- package/dist/types/Config.js.map +1 -0
- package/dist/types/Flow.d.ts +5 -0
- package/dist/types/Flow.js +2 -0
- package/dist/types/Flow.js.map +1 -0
- package/dist/types/GlobalOptions.d.ts +11 -0
- package/dist/types/GlobalOptions.js +2 -0
- package/dist/types/GlobalOptions.js.map +1 -0
- package/dist/types/Inputs.d.ts +5 -0
- package/dist/types/Inputs.js +2 -0
- package/dist/types/Inputs.js.map +1 -0
- package/dist/types/JsonLikeObject.d.ts +3 -0
- package/dist/types/JsonLikeObject.js +2 -0
- package/dist/types/JsonLikeObject.js.map +1 -0
- package/dist/types/Mapper.d.ts +5 -0
- package/dist/types/Mapper.js +2 -0
- package/dist/types/Mapper.js.map +1 -0
- package/dist/types/Node.d.ts +10 -0
- package/dist/types/Node.js +2 -0
- package/dist/types/Node.js.map +1 -0
- package/dist/types/ParamsDictionary.d.ts +3 -0
- package/dist/types/ParamsDictionary.js +2 -0
- package/dist/types/ParamsDictionary.js.map +1 -0
- package/dist/types/Properties.d.ts +5 -0
- package/dist/types/Properties.js +2 -0
- package/dist/types/Properties.js.map +1 -0
- package/dist/types/Targets.d.ts +5 -0
- package/dist/types/Targets.js +2 -0
- package/dist/types/Targets.js.map +1 -0
- package/dist/types/Trigger.d.ts +5 -0
- package/dist/types/Trigger.js +2 -0
- package/dist/types/Trigger.js.map +1 -0
- package/dist/types/TriggerHttp.d.ts +7 -0
- package/dist/types/TriggerHttp.js +2 -0
- package/dist/types/TriggerHttp.js.map +1 -0
- package/dist/types/TriggerResponse.d.ts +6 -0
- package/dist/types/TriggerResponse.js +2 -0
- package/dist/types/TriggerResponse.js.map +1 -0
- package/dist/types/Triggers.d.ts +5 -0
- package/dist/types/Triggers.js +2 -0
- package/dist/types/Triggers.js.map +1 -0
- package/dist/types/TryCatch.d.ts +6 -0
- package/dist/types/TryCatch.js +2 -0
- package/dist/types/TryCatch.js.map +1 -0
- package/dist/visualization/NodeDependencyGraph.d.ts +76 -0
- package/dist/visualization/NodeDependencyGraph.js +418 -0
- package/dist/visualization/NodeDependencyGraph.js.map +1 -0
- package/dist/visualization/WorkflowVisualizer.d.ts +144 -0
- package/dist/visualization/WorkflowVisualizer.js +446 -0
- package/dist/visualization/WorkflowVisualizer.js.map +1 -0
- package/package.json +95 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encryption at Rest for Blok Framework
|
|
3
|
+
*
|
|
4
|
+
* Provides AES-256-GCM encryption and decryption for data at rest:
|
|
5
|
+
* - Symmetric encryption using AES-256-GCM (authenticated encryption)
|
|
6
|
+
* - Key derivation via PBKDF2 with configurable iterations and salt length
|
|
7
|
+
* - JSON object encryption/decryption with type safety
|
|
8
|
+
* - Key rotation support for seamless secret re-keying
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { EncryptionAtRest } from "@blokjs/runner";
|
|
13
|
+
*
|
|
14
|
+
* const encryption = new EncryptionAtRest({
|
|
15
|
+
* algorithm: "aes-256-gcm",
|
|
16
|
+
* keyDerivation: { iterations: 100_000, saltLength: 16, digest: "sha512" },
|
|
17
|
+
* encoding: "base64",
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* // Encrypt a string
|
|
21
|
+
* const payload = encryption.encrypt("sensitive data", "my-secret-key");
|
|
22
|
+
*
|
|
23
|
+
* // Decrypt it back
|
|
24
|
+
* const plaintext = encryption.decrypt(payload, "my-secret-key");
|
|
25
|
+
*
|
|
26
|
+
* // Encrypt/decrypt JSON objects
|
|
27
|
+
* const encrypted = encryption.encryptObject({ userId: 42, email: "a@b.com" }, "key");
|
|
28
|
+
* const obj = encryption.decryptObject<{ userId: number; email: string }>(encrypted, "key");
|
|
29
|
+
*
|
|
30
|
+
* // Rotate encryption key
|
|
31
|
+
* const reEncrypted = encryption.rotateKey(encrypted, "old-key", "new-key");
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
import { createCipheriv, createDecipheriv, pbkdf2Sync, randomBytes, } from "node:crypto";
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Constants
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
/** AES-256-GCM requires a 256-bit (32 byte) key */
|
|
39
|
+
const KEY_LENGTH_BYTES = 32;
|
|
40
|
+
/** GCM recommended IV length is 12 bytes (96 bits) */
|
|
41
|
+
const IV_LENGTH_BYTES = 12;
|
|
42
|
+
/** GCM authentication tag length in bytes */
|
|
43
|
+
const AUTH_TAG_LENGTH_BYTES = 16;
|
|
44
|
+
const DEFAULT_KEY_DERIVATION = {
|
|
45
|
+
iterations: 100_000,
|
|
46
|
+
saltLength: 16,
|
|
47
|
+
digest: "sha512",
|
|
48
|
+
};
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Implementation
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
/**
|
|
53
|
+
* Provides AES-256-GCM encryption and decryption for data at rest.
|
|
54
|
+
*
|
|
55
|
+
* All encrypted payloads are self-describing: they embed the IV, auth tag,
|
|
56
|
+
* and algorithm so that decryption does not require out-of-band metadata.
|
|
57
|
+
*
|
|
58
|
+
* Keys are derived from a passphrase via PBKDF2 with a per-encryption random
|
|
59
|
+
* salt. The salt is prepended to the ciphertext so it can be recovered
|
|
60
|
+
* during decryption.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const enc = new EncryptionAtRest();
|
|
65
|
+
* const payload = enc.encrypt("hello", "passphrase");
|
|
66
|
+
* const plain = enc.decrypt(payload, "passphrase");
|
|
67
|
+
* console.log(plain); // "hello"
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export class EncryptionAtRest {
|
|
71
|
+
algorithm;
|
|
72
|
+
keyDerivation;
|
|
73
|
+
encoding;
|
|
74
|
+
/**
|
|
75
|
+
* Create a new EncryptionAtRest instance.
|
|
76
|
+
*
|
|
77
|
+
* @param config - Optional configuration overrides
|
|
78
|
+
*/
|
|
79
|
+
constructor(config) {
|
|
80
|
+
this.algorithm = config?.algorithm ?? "aes-256-gcm";
|
|
81
|
+
this.keyDerivation = {
|
|
82
|
+
...DEFAULT_KEY_DERIVATION,
|
|
83
|
+
...config?.keyDerivation,
|
|
84
|
+
};
|
|
85
|
+
this.encoding = config?.encoding ?? "base64";
|
|
86
|
+
}
|
|
87
|
+
// -----------------------------------------------------------------------
|
|
88
|
+
// Public API
|
|
89
|
+
// -----------------------------------------------------------------------
|
|
90
|
+
/**
|
|
91
|
+
* Encrypt a plaintext string using AES-256-GCM.
|
|
92
|
+
*
|
|
93
|
+
* A fresh random IV and PBKDF2 salt are generated for every call, meaning
|
|
94
|
+
* encrypting the same plaintext twice with the same key will produce
|
|
95
|
+
* different ciphertexts.
|
|
96
|
+
*
|
|
97
|
+
* @param plaintext - The string to encrypt
|
|
98
|
+
* @param key - Passphrase from which the encryption key is derived
|
|
99
|
+
* @returns An {@link EncryptedPayload} containing everything needed for decryption
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* const payload = encryption.encrypt("my secret", "passphrase");
|
|
104
|
+
* // payload.ciphertext, payload.iv, payload.tag are all present
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
encrypt(plaintext, key) {
|
|
108
|
+
const salt = randomBytes(this.keyDerivation.saltLength);
|
|
109
|
+
const derivedKey = this.deriveKey(key, salt);
|
|
110
|
+
const iv = randomBytes(IV_LENGTH_BYTES);
|
|
111
|
+
const cipher = createCipheriv(this.algorithm, derivedKey, iv, {
|
|
112
|
+
authTagLength: AUTH_TAG_LENGTH_BYTES,
|
|
113
|
+
});
|
|
114
|
+
const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
115
|
+
const tag = cipher.getAuthTag();
|
|
116
|
+
// Prepend the salt to the ciphertext so it can be recovered on decrypt
|
|
117
|
+
const ciphertextWithSalt = Buffer.concat([salt, encrypted]);
|
|
118
|
+
return {
|
|
119
|
+
iv: iv.toString(this.encoding),
|
|
120
|
+
ciphertext: ciphertextWithSalt.toString(this.encoding),
|
|
121
|
+
tag: tag.toString(this.encoding),
|
|
122
|
+
algorithm: this.algorithm,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Decrypt an {@link EncryptedPayload} back to the original plaintext.
|
|
127
|
+
*
|
|
128
|
+
* @param payload - The encrypted payload produced by {@link encrypt}
|
|
129
|
+
* @param key - The same passphrase that was used for encryption
|
|
130
|
+
* @returns The original plaintext string
|
|
131
|
+
* @throws {Error} If the key is wrong or the payload has been tampered with
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* const plaintext = encryption.decrypt(payload, "passphrase");
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
decrypt(payload, key) {
|
|
139
|
+
const iv = Buffer.from(payload.iv, this.encoding);
|
|
140
|
+
const tag = Buffer.from(payload.tag, this.encoding);
|
|
141
|
+
const ciphertextWithSalt = Buffer.from(payload.ciphertext, this.encoding);
|
|
142
|
+
// Extract the salt from the beginning of the ciphertext
|
|
143
|
+
const salt = ciphertextWithSalt.subarray(0, this.keyDerivation.saltLength);
|
|
144
|
+
const ciphertext = ciphertextWithSalt.subarray(this.keyDerivation.saltLength);
|
|
145
|
+
const derivedKey = this.deriveKey(key, salt);
|
|
146
|
+
const decipher = createDecipheriv(this.algorithm, derivedKey, iv, {
|
|
147
|
+
authTagLength: AUTH_TAG_LENGTH_BYTES,
|
|
148
|
+
});
|
|
149
|
+
decipher.setAuthTag(tag);
|
|
150
|
+
const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
151
|
+
return decrypted.toString("utf8");
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Encrypt a JSON-serializable object.
|
|
155
|
+
*
|
|
156
|
+
* The object is serialized to JSON and then encrypted. The result is a
|
|
157
|
+
* single Base64/hex string that encodes the full {@link EncryptedPayload}
|
|
158
|
+
* as JSON.
|
|
159
|
+
*
|
|
160
|
+
* @typeParam T - Type of the object being encrypted
|
|
161
|
+
* @param obj - The object to encrypt
|
|
162
|
+
* @param key - Passphrase from which the encryption key is derived
|
|
163
|
+
* @returns A single encoded string representing the encrypted object
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```typescript
|
|
167
|
+
* const token = encryption.encryptObject({ userId: 1 }, "key");
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
encryptObject(obj, key) {
|
|
171
|
+
const json = JSON.stringify(obj);
|
|
172
|
+
const payload = this.encrypt(json, key);
|
|
173
|
+
return Buffer.from(JSON.stringify(payload)).toString(this.encoding);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Decrypt a string produced by {@link encryptObject} back to the original
|
|
177
|
+
* typed object.
|
|
178
|
+
*
|
|
179
|
+
* @typeParam T - Expected type of the decrypted object
|
|
180
|
+
* @param ciphertext - The encoded string produced by {@link encryptObject}
|
|
181
|
+
* @param key - The same passphrase that was used for encryption
|
|
182
|
+
* @returns The original object
|
|
183
|
+
* @throws {Error} If decryption or JSON parsing fails
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```typescript
|
|
187
|
+
* const obj = encryption.decryptObject<{ userId: number }>(token, "key");
|
|
188
|
+
* console.log(obj.userId); // 1
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
decryptObject(ciphertext, key) {
|
|
192
|
+
const payloadJson = Buffer.from(ciphertext, this.encoding).toString("utf8");
|
|
193
|
+
const payload = JSON.parse(payloadJson);
|
|
194
|
+
const json = this.decrypt(payload, key);
|
|
195
|
+
return JSON.parse(json);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Re-encrypt data with a new key (key rotation).
|
|
199
|
+
*
|
|
200
|
+
* This is a convenience method that decrypts with the old key and
|
|
201
|
+
* re-encrypts with the new key in a single call. It works with the
|
|
202
|
+
* encoded strings produced by {@link encryptObject}.
|
|
203
|
+
*
|
|
204
|
+
* @param data - The encoded ciphertext string to re-encrypt
|
|
205
|
+
* @param oldKey - The current passphrase
|
|
206
|
+
* @param newKey - The new passphrase to encrypt with
|
|
207
|
+
* @returns A new encoded ciphertext string encrypted under the new key
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```typescript
|
|
211
|
+
* const rotated = encryption.rotateKey(existingCiphertext, "old-pass", "new-pass");
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
rotateKey(data, oldKey, newKey) {
|
|
215
|
+
const payloadJson = Buffer.from(data, this.encoding).toString("utf8");
|
|
216
|
+
const payload = JSON.parse(payloadJson);
|
|
217
|
+
const plaintext = this.decrypt(payload, oldKey);
|
|
218
|
+
const newPayload = this.encrypt(plaintext, newKey);
|
|
219
|
+
return Buffer.from(JSON.stringify(newPayload)).toString(this.encoding);
|
|
220
|
+
}
|
|
221
|
+
// -----------------------------------------------------------------------
|
|
222
|
+
// Private helpers
|
|
223
|
+
// -----------------------------------------------------------------------
|
|
224
|
+
/**
|
|
225
|
+
* Derive a fixed-length encryption key from a passphrase and salt using
|
|
226
|
+
* PBKDF2.
|
|
227
|
+
*
|
|
228
|
+
* @param passphrase - The user-supplied passphrase
|
|
229
|
+
* @param salt - Random salt bytes
|
|
230
|
+
* @returns A Buffer of {@link KEY_LENGTH_BYTES} bytes
|
|
231
|
+
*/
|
|
232
|
+
deriveKey(passphrase, salt) {
|
|
233
|
+
return pbkdf2Sync(passphrase, salt, this.keyDerivation.iterations, KEY_LENGTH_BYTES, this.keyDerivation.digest);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=EncryptionAtRest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EncryptionAtRest.js","sourceRoot":"","sources":["../../src/security/EncryptionAtRest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth 2.0 / OpenID Connect Authentication Provider for Blok
|
|
3
|
+
*
|
|
4
|
+
* Provides standards-compliant OIDC authentication with:
|
|
5
|
+
* - OIDC Discovery (/.well-known/openid-configuration)
|
|
6
|
+
* - JWKS-based public key retrieval and caching
|
|
7
|
+
* - JWT verification using RS256 (RSA) and ES256 (ECDSA) via Node.js crypto
|
|
8
|
+
* - Token claims validation (exp, nbf, iss, aud)
|
|
9
|
+
* - Token introspection for opaque tokens (RFC 7662)
|
|
10
|
+
* - LRU token cache with TTL-based expiry
|
|
11
|
+
*
|
|
12
|
+
* Uses only Node.js built-in modules (node:crypto, node:buffer).
|
|
13
|
+
* No external JWT libraries required.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const oidcProvider = new OAuthOIDCProvider({
|
|
18
|
+
* issuerUrl: "https://auth.example.com",
|
|
19
|
+
* clientId: "my-app",
|
|
20
|
+
* audience: "https://api.example.com",
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* const auth = new AuthMiddleware({
|
|
24
|
+
* providers: [oidcProvider],
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import type { AuthIdentity, AuthProvider, AuthRequest, AuthResult } from "./AuthMiddleware";
|
|
29
|
+
/**
|
|
30
|
+
* Configuration for the OAuth 2.0 / OIDC authentication provider
|
|
31
|
+
*/
|
|
32
|
+
export interface OAuthOIDCConfig {
|
|
33
|
+
/** OIDC issuer URL (e.g. "https://auth.example.com") */
|
|
34
|
+
issuerUrl: string;
|
|
35
|
+
/** OAuth 2.0 client ID */
|
|
36
|
+
clientId: string;
|
|
37
|
+
/** OAuth 2.0 client secret (required for token introspection) */
|
|
38
|
+
clientSecret?: string;
|
|
39
|
+
/** Expected audience claim value */
|
|
40
|
+
audience?: string;
|
|
41
|
+
/** Allowed JWT signing algorithms (default: ["RS256", "ES256"]) */
|
|
42
|
+
allowedAlgorithms?: string[];
|
|
43
|
+
/** JWKS URI override (auto-discovered from OIDC metadata when omitted) */
|
|
44
|
+
jwksUri?: string;
|
|
45
|
+
/** JWT claim that contains user roles (default: "roles") */
|
|
46
|
+
rolesClaim?: string;
|
|
47
|
+
/** JWT claim that contains scopes (default: "scope") */
|
|
48
|
+
scopesClaim?: string;
|
|
49
|
+
/** Clock skew tolerance in seconds for exp/nbf checks (default: 30) */
|
|
50
|
+
clockToleranceSec?: number;
|
|
51
|
+
/** Whether to cache the JWKS key set (default: true) */
|
|
52
|
+
cacheJWKS?: boolean;
|
|
53
|
+
/** Whether to cache the OIDC discovery document (default: true) */
|
|
54
|
+
cacheDiscovery?: boolean;
|
|
55
|
+
/** Token introspection endpoint override (auto-discovered when omitted) */
|
|
56
|
+
introspectionEndpoint?: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* OpenID Connect Discovery document as defined in the OIDC specification
|
|
60
|
+
*
|
|
61
|
+
* @see https://openid.net/specs/openid-connect-discovery-1_0.html
|
|
62
|
+
*/
|
|
63
|
+
export interface OIDCDiscoveryDocument {
|
|
64
|
+
/** Issuer identifier */
|
|
65
|
+
issuer: string;
|
|
66
|
+
/** URL of the authorization endpoint */
|
|
67
|
+
authorization_endpoint: string;
|
|
68
|
+
/** URL of the token endpoint */
|
|
69
|
+
token_endpoint: string;
|
|
70
|
+
/** URL of the userinfo endpoint */
|
|
71
|
+
userinfo_endpoint: string;
|
|
72
|
+
/** URL of the JWKS endpoint */
|
|
73
|
+
jwks_uri: string;
|
|
74
|
+
/** Supported OAuth 2.0 scopes */
|
|
75
|
+
scopes_supported: string[];
|
|
76
|
+
/** Supported OAuth 2.0 response types */
|
|
77
|
+
response_types_supported: string[];
|
|
78
|
+
/** Supported OpenID Connect claims */
|
|
79
|
+
claims_supported: string[];
|
|
80
|
+
/** Token introspection endpoint (optional, RFC 7662) */
|
|
81
|
+
introspection_endpoint?: string;
|
|
82
|
+
/** Additional fields that may appear in the discovery document */
|
|
83
|
+
[key: string]: unknown;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* JSON Web Key as defined in RFC 7517
|
|
87
|
+
*/
|
|
88
|
+
export interface JWK {
|
|
89
|
+
/** Key type (e.g. "RSA", "EC") */
|
|
90
|
+
kty: string;
|
|
91
|
+
/** Key ID */
|
|
92
|
+
kid: string;
|
|
93
|
+
/** Key usage (e.g. "sig") */
|
|
94
|
+
use?: string;
|
|
95
|
+
/** Algorithm (e.g. "RS256", "ES256") */
|
|
96
|
+
alg?: string;
|
|
97
|
+
/** RSA modulus (base64url-encoded) */
|
|
98
|
+
n?: string;
|
|
99
|
+
/** RSA exponent (base64url-encoded) */
|
|
100
|
+
e?: string;
|
|
101
|
+
/** EC x-coordinate (base64url-encoded) */
|
|
102
|
+
x?: string;
|
|
103
|
+
/** EC y-coordinate (base64url-encoded) */
|
|
104
|
+
y?: string;
|
|
105
|
+
/** EC curve name (e.g. "P-256") */
|
|
106
|
+
crv?: string;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* JSON Web Key Set as defined in RFC 7517
|
|
110
|
+
*/
|
|
111
|
+
export interface JWKS {
|
|
112
|
+
/** Array of JSON Web Keys */
|
|
113
|
+
keys: JWK[];
|
|
114
|
+
}
|
|
115
|
+
/** Statistics returned by TokenCache.getStats() */
|
|
116
|
+
export interface TokenCacheStats {
|
|
117
|
+
/** Number of entries currently in the cache */
|
|
118
|
+
size: number;
|
|
119
|
+
/** Maximum number of entries allowed */
|
|
120
|
+
maxSize: number;
|
|
121
|
+
/** Total number of cache hits */
|
|
122
|
+
hits: number;
|
|
123
|
+
/** Total number of cache misses */
|
|
124
|
+
misses: number;
|
|
125
|
+
/** Total number of entries evicted due to TTL or capacity */
|
|
126
|
+
evictions: number;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* LRU-style token cache with TTL-based expiry.
|
|
130
|
+
*
|
|
131
|
+
* Caches validated token identities keyed by a SHA-256 hash of the raw token.
|
|
132
|
+
* When the cache exceeds its maximum size the least-recently-used entry is
|
|
133
|
+
* evicted.
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```typescript
|
|
137
|
+
* const cache = new TokenCache(500);
|
|
138
|
+
* const hash = cache.hashToken(rawJwt);
|
|
139
|
+
*
|
|
140
|
+
* // Store after validation
|
|
141
|
+
* cache.set(hash, identity, 3600_000);
|
|
142
|
+
*
|
|
143
|
+
* // Retrieve on subsequent requests
|
|
144
|
+
* const cached = cache.get(hash);
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
export declare class TokenCache {
|
|
148
|
+
private cache;
|
|
149
|
+
private readonly maxSize;
|
|
150
|
+
private hits;
|
|
151
|
+
private misses;
|
|
152
|
+
private evictions;
|
|
153
|
+
constructor(maxSize?: number);
|
|
154
|
+
/**
|
|
155
|
+
* Retrieve a cached identity by token hash.
|
|
156
|
+
* Returns `undefined` if the entry is missing or has expired.
|
|
157
|
+
* Moves the entry to the end of the map (most-recently-used).
|
|
158
|
+
*/
|
|
159
|
+
get(tokenHash: string): AuthIdentity | undefined;
|
|
160
|
+
/**
|
|
161
|
+
* Store an identity in the cache.
|
|
162
|
+
*
|
|
163
|
+
* @param tokenHash - SHA-256 hex hash of the raw token
|
|
164
|
+
* @param identity - Validated identity to cache
|
|
165
|
+
* @param ttlMs - Time-to-live in milliseconds
|
|
166
|
+
*/
|
|
167
|
+
set(tokenHash: string, identity: AuthIdentity, ttlMs: number): void;
|
|
168
|
+
/**
|
|
169
|
+
* Invalidate (remove) a specific entry by token hash
|
|
170
|
+
*/
|
|
171
|
+
invalidate(tokenHash: string): boolean;
|
|
172
|
+
/**
|
|
173
|
+
* Remove all entries from the cache and reset statistics
|
|
174
|
+
*/
|
|
175
|
+
clear(): void;
|
|
176
|
+
/**
|
|
177
|
+
* Return cache performance statistics
|
|
178
|
+
*/
|
|
179
|
+
getStats(): TokenCacheStats;
|
|
180
|
+
/**
|
|
181
|
+
* Compute a SHA-256 hex digest suitable for use as a cache key
|
|
182
|
+
*/
|
|
183
|
+
static hashToken(token: string): string;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* OAuth 2.0 / OpenID Connect Authentication Provider
|
|
187
|
+
*
|
|
188
|
+
* Validates JWT access tokens issued by an OIDC-compliant identity provider.
|
|
189
|
+
* Automatically discovers OIDC metadata and JWKS endpoints, verifies token
|
|
190
|
+
* signatures using RS256 or ES256, and validates standard claims.
|
|
191
|
+
*
|
|
192
|
+
* For opaque (non-JWT) tokens, falls back to RFC 7662 token introspection
|
|
193
|
+
* when an introspection endpoint is configured or discovered.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```typescript
|
|
197
|
+
* const provider = new OAuthOIDCProvider({
|
|
198
|
+
* issuerUrl: "https://accounts.google.com",
|
|
199
|
+
* clientId: "my-client-id",
|
|
200
|
+
* audience: "https://api.example.com",
|
|
201
|
+
* });
|
|
202
|
+
*
|
|
203
|
+
* const result = await provider.authenticate({
|
|
204
|
+
* headers: { authorization: "Bearer eyJhbGciOi..." },
|
|
205
|
+
* });
|
|
206
|
+
*
|
|
207
|
+
* if (result.authenticated) {
|
|
208
|
+
* console.log("Authenticated:", result.identity?.sub);
|
|
209
|
+
* }
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
export declare class OAuthOIDCProvider implements AuthProvider {
|
|
213
|
+
readonly name = "oauth-oidc";
|
|
214
|
+
private config;
|
|
215
|
+
/** Cached OIDC discovery document */
|
|
216
|
+
private discoveryCache;
|
|
217
|
+
/** Cached JWKS keyset */
|
|
218
|
+
private jwksCache;
|
|
219
|
+
/** Pre-imported Node.js KeyObjects keyed by kid */
|
|
220
|
+
private keyObjectCache;
|
|
221
|
+
/** Token result cache */
|
|
222
|
+
private tokenCache;
|
|
223
|
+
constructor(config: OAuthOIDCConfig);
|
|
224
|
+
/**
|
|
225
|
+
* Authenticate an incoming request by extracting and verifying the
|
|
226
|
+
* Bearer token from the Authorization header.
|
|
227
|
+
*/
|
|
228
|
+
authenticate(request: AuthRequest): Promise<AuthResult>;
|
|
229
|
+
/**
|
|
230
|
+
* Fetch and parse the OIDC discovery document from the issuer's
|
|
231
|
+
* `/.well-known/openid-configuration` endpoint.
|
|
232
|
+
*
|
|
233
|
+
* The result is cached when `cacheDiscovery` is enabled (default).
|
|
234
|
+
*
|
|
235
|
+
* @param issuerUrl - The OIDC issuer URL
|
|
236
|
+
* @returns Parsed OIDC discovery document
|
|
237
|
+
*/
|
|
238
|
+
discoverConfiguration(issuerUrl: string): Promise<OIDCDiscoveryDocument>;
|
|
239
|
+
/**
|
|
240
|
+
* Fetch the JSON Web Key Set from the specified URI.
|
|
241
|
+
*
|
|
242
|
+
* The result is cached when `cacheJWKS` is enabled (default).
|
|
243
|
+
*
|
|
244
|
+
* @param jwksUri - URL of the JWKS endpoint
|
|
245
|
+
* @returns The parsed JWKS
|
|
246
|
+
*/
|
|
247
|
+
fetchJWKS(jwksUri: string): Promise<JWKS>;
|
|
248
|
+
/**
|
|
249
|
+
* Introspect an opaque token via the RFC 7662 token introspection endpoint.
|
|
250
|
+
*
|
|
251
|
+
* Requires `clientId` and `clientSecret` for Basic authentication.
|
|
252
|
+
*
|
|
253
|
+
* @param token - The raw token string
|
|
254
|
+
* @param introspectionEndpoint - URL of the introspection endpoint
|
|
255
|
+
* @returns Resolved AuthIdentity when the token is active, otherwise `null`
|
|
256
|
+
*/
|
|
257
|
+
introspectToken(token: string, introspectionEndpoint: string): Promise<AuthIdentity | null>;
|
|
258
|
+
/**
|
|
259
|
+
* Verify a JWT access token using the issuer's public keys.
|
|
260
|
+
*
|
|
261
|
+
* 1. Decodes the JWT header to determine `alg` and `kid`.
|
|
262
|
+
* 2. Resolves the JWKS (via discovery or explicit config).
|
|
263
|
+
* 3. Selects the matching JWK by `kid`.
|
|
264
|
+
* 4. Verifies the signature using RS256 or ES256.
|
|
265
|
+
* 5. Validates standard claims (exp, nbf, iss, aud).
|
|
266
|
+
*
|
|
267
|
+
* @param token - Raw JWT string
|
|
268
|
+
* @returns Resolved AuthIdentity on success, `null` on failure
|
|
269
|
+
*/
|
|
270
|
+
private verifyJWT;
|
|
271
|
+
/**
|
|
272
|
+
* Verify a JWT signature using the given algorithm and public key.
|
|
273
|
+
*
|
|
274
|
+
* @param alg - JWT algorithm (RS256 or ES256)
|
|
275
|
+
* @param key - Node.js KeyObject containing the public key
|
|
276
|
+
* @param signingInput - The `header.payload` string that was signed
|
|
277
|
+
* @param signature - Raw signature bytes
|
|
278
|
+
* @returns `true` if the signature is valid
|
|
279
|
+
*/
|
|
280
|
+
private verifySignature;
|
|
281
|
+
/**
|
|
282
|
+
* Convert a raw ECDSA signature (r || s, 64 bytes for P-256) to
|
|
283
|
+
* DER-encoded format expected by Node.js crypto.
|
|
284
|
+
*
|
|
285
|
+
* @param raw - Raw ECDSA signature bytes
|
|
286
|
+
* @returns DER-encoded signature buffer
|
|
287
|
+
*/
|
|
288
|
+
private rawEcdsaToDer;
|
|
289
|
+
/**
|
|
290
|
+
* Resolve a Node.js KeyObject for the given algorithm and key ID.
|
|
291
|
+
*
|
|
292
|
+
* Performs OIDC discovery and JWKS fetch as needed, then selects the
|
|
293
|
+
* appropriate JWK and imports it into a native KeyObject.
|
|
294
|
+
*/
|
|
295
|
+
private resolvePublicKey;
|
|
296
|
+
/**
|
|
297
|
+
* Select a JWK from the key set that matches the algorithm and key ID.
|
|
298
|
+
*/
|
|
299
|
+
private selectKey;
|
|
300
|
+
/**
|
|
301
|
+
* Import a JWK into a Node.js KeyObject using `crypto.createPublicKey`.
|
|
302
|
+
*/
|
|
303
|
+
private importJWK;
|
|
304
|
+
/**
|
|
305
|
+
* Validate standard JWT claims: exp, nbf, iss, aud.
|
|
306
|
+
*
|
|
307
|
+
* @returns An error message string if validation fails, `null` otherwise
|
|
308
|
+
*/
|
|
309
|
+
private validateClaims;
|
|
310
|
+
/**
|
|
311
|
+
* Extract roles from token claims using the configured claim names.
|
|
312
|
+
*
|
|
313
|
+
* Checks the `rolesClaim` first (e.g. "roles"), then falls back
|
|
314
|
+
* to parsing space-delimited scopes from `scopesClaim` (e.g. "scope").
|
|
315
|
+
*/
|
|
316
|
+
private extractRoles;
|
|
317
|
+
/**
|
|
318
|
+
* Resolve the JWKS URI, either from explicit config or via OIDC discovery
|
|
319
|
+
*/
|
|
320
|
+
private resolveJwksUri;
|
|
321
|
+
/**
|
|
322
|
+
* Resolve the token introspection endpoint from OIDC discovery
|
|
323
|
+
*/
|
|
324
|
+
private resolveIntrospectionEndpoint;
|
|
325
|
+
/**
|
|
326
|
+
* Clear all internal caches (discovery, JWKS, token cache).
|
|
327
|
+
* Useful during key rotation or configuration changes.
|
|
328
|
+
*/
|
|
329
|
+
clearCaches(): void;
|
|
330
|
+
/**
|
|
331
|
+
* Return statistics from the token cache
|
|
332
|
+
*/
|
|
333
|
+
getTokenCacheStats(): TokenCacheStats;
|
|
334
|
+
}
|