@xenterprises/fastify-xauth-jwks 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CACHING.md ADDED
@@ -0,0 +1,282 @@
1
+ # xAuthJWSK Caching Documentation
2
+
3
+ xAuthJWSK implements intelligent two-level caching for optimal performance:
4
+
5
+ ## 1. JWKS Caching (Automatic)
6
+
7
+ JWKS endpoints are cached by the `jose` library to reduce external API calls.
8
+
9
+ ### Configuration
10
+
11
+ ```javascript
12
+ {
13
+ paths: {
14
+ admin: {
15
+ pathPattern: "/admin",
16
+ jwksUrl: "https://your-auth.com/.well-known/jwks.json",
17
+ // JWKS caching configuration
18
+ jwksCooldownDuration: 30000, // 30 seconds (default)
19
+ jwksCacheMaxAge: 1800000, // 30 minutes (default)
20
+ }
21
+ }
22
+ }
23
+ ```
24
+
25
+ ### Parameters
26
+
27
+ - **`jwksCooldownDuration`** (ms): Minimum time between JWKS endpoint refetches
28
+ - Default: 30 seconds
29
+ - Use case: Prevents hammering the JWKS endpoint if validation fails
30
+
31
+ - **`jwksCacheMaxAge`** (ms): Maximum time to cache JWKS keys
32
+ - Default: 30 minutes (1800000ms)
33
+ - Use case: Balance between freshness and performance
34
+
35
+ ### Example: High-Traffic Setup
36
+
37
+ ```javascript
38
+ {
39
+ paths: {
40
+ api: {
41
+ pathPattern: "/api",
42
+ jwksUrl: "https://your-auth.com/.well-known/jwks.json",
43
+ jwksCooldownDuration: 60000, // 1 minute
44
+ jwksCacheMaxAge: 3600000, // 1 hour
45
+ }
46
+ }
47
+ }
48
+ ```
49
+
50
+ ## 2. JWT Payload Caching (Optional)
51
+
52
+ JWT payloads are optionally cached to avoid redundant verification of the same token.
53
+
54
+ ### Configuration
55
+
56
+ ```javascript
57
+ {
58
+ paths: {
59
+ admin: {
60
+ pathPattern: "/admin",
61
+ jwksUrl: "https://your-auth.com/.well-known/jwks.json",
62
+ // JWT payload caching configuration
63
+ enablePayloadCache: true, // enabled by default
64
+ payloadCacheTTL: 300000, // 5 minutes (default)
65
+ }
66
+ }
67
+ }
68
+ ```
69
+
70
+ ### Parameters
71
+
72
+ - **`enablePayloadCache`** (boolean): Enable/disable JWT payload caching
73
+ - Default: `true`
74
+ - Use case: Set to `false` for maximum freshness or if tokens change frequently
75
+
76
+ - **`payloadCacheTTL`** (ms): Time to live for cached JWT payloads
77
+ - Default: 5 minutes (300000ms)
78
+ - Must be shorter than or equal to JWT token expiration
79
+ - Use case: Tokens are typically short-lived (15 mins), so 5-10 mins is ideal
80
+
81
+ ### Example: High-Security Setup
82
+
83
+ ```javascript
84
+ {
85
+ paths: {
86
+ admin: {
87
+ pathPattern: "/admin",
88
+ jwksUrl: "https://your-auth.com/.well-known/jwks.json",
89
+ enablePayloadCache: true,
90
+ payloadCacheTTL: 60000, // 1 minute (very fresh)
91
+ }
92
+ }
93
+ }
94
+ ```
95
+
96
+ ## 3. Cache Management
97
+
98
+ Each validator exposes cache management methods:
99
+
100
+ ### Get Cache Statistics
101
+
102
+ ```javascript
103
+ const validator = fastify.xAuth.validators.admin;
104
+ const stats = validator.getPayloadCacheStats();
105
+
106
+ console.log(stats);
107
+ // {
108
+ // size: 42, // number of cached tokens
109
+ // enabled: true, // cache enabled?
110
+ // ttl: 300000 // cache TTL in ms
111
+ // }
112
+ ```
113
+
114
+ ### Clear Cache Manually
115
+
116
+ ```javascript
117
+ const validator = fastify.xAuth.validators.admin;
118
+ validator.clearPayloadCache(); // clears all cached payloads
119
+ ```
120
+
121
+ ### Access Configuration
122
+
123
+ ```javascript
124
+ const validator = fastify.xAuth.validators.admin;
125
+ console.log(validator.config);
126
+ // {
127
+ // jwksCooldownDuration: 30000,
128
+ // jwksCacheMaxAge: 1800000,
129
+ // enablePayloadCache: true,
130
+ // payloadCacheTTL: 300000
131
+ // }
132
+ ```
133
+
134
+ ## Performance Recommendations
135
+
136
+ ### High-Traffic Applications (>1000 req/s)
137
+
138
+ ```javascript
139
+ {
140
+ paths: {
141
+ api: {
142
+ pathPattern: "/api",
143
+ jwksUrl: "https://your-auth.com/.well-known/jwks.json",
144
+ // Aggressive caching
145
+ jwksCooldownDuration: 60000, // 1 minute
146
+ jwksCacheMaxAge: 3600000, // 1 hour
147
+ enablePayloadCache: true,
148
+ payloadCacheTTL: 600000, // 10 minutes
149
+ }
150
+ }
151
+ }
152
+ ```
153
+
154
+ **Expected impact:**
155
+ - JWKS requests: ~60-100 per day (instead of per second)
156
+ - Token verifications: Cached payloads skip signature verification
157
+ - Latency: ~1ms cached vs ~10-50ms uncached
158
+
159
+ ### Medium-Traffic Applications (100-1000 req/s)
160
+
161
+ ```javascript
162
+ {
163
+ paths: {
164
+ api: {
165
+ pathPattern: "/api",
166
+ jwksUrl: "https://your-auth.com/.well-known/jwks.json",
167
+ // Balanced caching (recommended defaults)
168
+ jwksCooldownDuration: 30000, // 30 seconds
169
+ jwksCacheMaxAge: 1800000, // 30 minutes
170
+ enablePayloadCache: true,
171
+ payloadCacheTTL: 300000, // 5 minutes
172
+ }
173
+ }
174
+ }
175
+ ```
176
+
177
+ ### Low-Traffic / High-Security (< 100 req/s)
178
+
179
+ ```javascript
180
+ {
181
+ paths: {
182
+ admin: {
183
+ pathPattern: "/admin",
184
+ jwksUrl: "https://your-auth.com/.well-known/jwks.json",
185
+ // Minimal caching for fresh tokens
186
+ jwksCooldownDuration: 10000, // 10 seconds
187
+ jwksCacheMaxAge: 300000, // 5 minutes
188
+ enablePayloadCache: true,
189
+ payloadCacheTTL: 60000, // 1 minute
190
+ }
191
+ }
192
+ }
193
+ ```
194
+
195
+ ## Cache Invalidation
196
+
197
+ ### Automatic TTL Expiration
198
+
199
+ Cached payloads automatically expire after `payloadCacheTTL` milliseconds. Expired entries are removed on next access.
200
+
201
+ ### Manual Invalidation
202
+
203
+ Clear cache when you need to force token re-verification:
204
+
205
+ ```javascript
206
+ // Clear specific path cache
207
+ fastify.xAuth.validators.admin.clearPayloadCache();
208
+
209
+ // Clear all path caches
210
+ for (const validator of Object.values(fastify.xAuth.validators)) {
211
+ validator.clearPayloadCache();
212
+ }
213
+ ```
214
+
215
+ ## Monitoring
216
+
217
+ Monitor cache effectiveness:
218
+
219
+ ```javascript
220
+ const monitorCache = () => {
221
+ for (const [name, validator] of Object.entries(fastify.xAuth.validators)) {
222
+ const stats = validator.getPayloadCacheStats();
223
+ console.log(`${name}: ${stats.size} cached tokens`);
224
+ }
225
+ };
226
+
227
+ // Check every minute
228
+ setInterval(monitorCache, 60000);
229
+ ```
230
+
231
+ ## Troubleshooting
232
+
233
+ ### Tokens not being validated immediately
234
+
235
+ If token permissions change, the cache may still return old payloads. Solution:
236
+
237
+ 1. Reduce `payloadCacheTTL` to match permission change frequency
238
+ 2. Manually clear cache when permissions update: `clearPayloadCache()`
239
+ 3. Disable cache if updates are very frequent: `enablePayloadCache: false`
240
+
241
+ ### JWKS endpoint being hammered
242
+
243
+ If seeing many requests to JWKS endpoint:
244
+
245
+ 1. Increase `jwksCacheMaxAge` (max 1 hour recommended)
246
+ 2. Increase `jwksCooldownDuration` (min 30 seconds)
247
+ 3. Ensure JWKS endpoint is returning proper Cache-Control headers
248
+
249
+ ### Memory growth
250
+
251
+ Large `payloadCache` size indicates many unique tokens. Solutions:
252
+
253
+ 1. Reduce `payloadCacheTTL` to expire entries faster
254
+ 2. Disable cache: `enablePayloadCache: false`
255
+ 3. Manually clear periodically: `validator.clearPayloadCache()`
256
+
257
+ ## Best Practices
258
+
259
+ 1. **Match TTL to token lifetime**: If tokens live 15 minutes, cache should be 5-10 minutes
260
+ 2. **Monitor cache size**: Watch for memory growth in `getPayloadCacheStats()`
261
+ 3. **Test in production**: Verify cache hit rates work for your traffic patterns
262
+ 4. **Clear on deployments**: Reset cache when deploying auth changes
263
+ 5. **Use defaults**: The defaults are optimized for most use cases
264
+
265
+ ## Technical Details
266
+
267
+ ### JWKS Cache
268
+
269
+ - Implemented by `jose.createRemoteJWKSet()`
270
+ - Automatically fetches new keys if current key ID not found
271
+ - Respects HTTP cache headers from endpoint
272
+
273
+ ### Payload Cache
274
+
275
+ - Simple Map-based LRU-like cache (expires by TTL)
276
+ - Token string is the cache key
277
+ - Stores full JWT payload + expiration timestamp
278
+ - Automatic cleanup on access (lazy deletion)
279
+
280
+ ### No External Dependencies
281
+
282
+ All caching is built-in using standard JavaScript Map and timers. No external cache library required.