@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/AUTHENTICATION_EXAMPLE.md +453 -0
- package/CACHING.md +282 -0
- package/CONFIGURATION.md +545 -0
- package/DEVELOPMENT.md +385 -0
- package/JOSE_UTILITIES.md +204 -0
- package/KEYS_GENERATION.md +359 -0
- package/QUICK_START.md +334 -0
- package/README.md +73 -0
- package/package.json +44 -0
- package/server/app.js +370 -0
- package/server/example-jwks.json +12 -0
- package/server/generate-demo-token.js +232 -0
- package/src/index.js +9 -0
- package/src/services/pathValidator.js +175 -0
- package/src/utils/index.js +145 -0
- package/src/xAuth.js +36 -0
- package/test/integration.test.js +259 -0
- package/test/utils.test.js +195 -0
- package/test/xAuth.test.js +439 -0
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.
|