securenow 4.0.3 → 4.0.6

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.
@@ -0,0 +1,320 @@
1
+ # Next.js Body Capture - Choosing the Right Approach
2
+
3
+ ## 🎯 Two Approaches Available
4
+
5
+ SecureNow offers two ways to capture request bodies in Next.js:
6
+
7
+ 1. **Wrapper Approach** (Recommended ✅)
8
+ 2. **Middleware Approach** (Use with caution ⚠️)
9
+
10
+ ---
11
+
12
+ ## ✅ Wrapper Approach (RECOMMENDED)
13
+
14
+ ### How It Works
15
+
16
+ Wrap individual API route handlers to capture bodies **inside the handler**:
17
+
18
+ ```typescript
19
+ import { withSecureNow } from 'securenow/nextjs-wrapper';
20
+
21
+ export const POST = withSecureNow(async (request: Request) => {
22
+ const body = await request.json();
23
+ return Response.json({ success: true });
24
+ });
25
+ ```
26
+
27
+ ### ✅ Pros
28
+
29
+ - **Zero middleware conflicts** - Doesn't interfere with NextAuth or other middleware
30
+ - **Never blocks requests** - Runs after routing is complete
31
+ - **Per-route control** - Wrap only the routes you need
32
+ - **Non-invasive** - Your middleware stays unchanged
33
+ - **Safe** - Runs inside your handler, can't prevent handler execution
34
+ - **Background capture** - Doesn't delay responses
35
+
36
+ ### ❌ Cons
37
+
38
+ - Requires wrapping each route individually (but only the ones you want!)
39
+ - Slightly more verbose (one extra line per route)
40
+
41
+ ### When to Use
42
+
43
+ - ✅ You have NextAuth or other middleware
44
+ - ✅ You want zero conflicts
45
+ - ✅ You want fine-grained control
46
+ - ✅ You prioritize reliability
47
+ - ✅ **This is the recommended approach for most users**
48
+
49
+ ### Setup
50
+
51
+ **Step 1:** Enable in .env.local
52
+ ```bash
53
+ SECURENOW_CAPTURE_BODY=1
54
+ ```
55
+
56
+ **Step 2:** Wrap your API routes
57
+ ```typescript
58
+ // app/api/login/route.ts
59
+ import { withSecureNow } from 'securenow/nextjs-wrapper';
60
+
61
+ export const POST = withSecureNow(async (request: Request) => {
62
+ const body = await request.json();
63
+ // Your logic...
64
+ return Response.json({ success: true });
65
+ });
66
+ ```
67
+
68
+ **That's it!** No middleware.ts needed.
69
+
70
+ 📚 **Full guide:** See `NEXTJS-WRAPPER-APPROACH.md`
71
+
72
+ ---
73
+
74
+ ## ⚠️ Middleware Approach (Use with Caution)
75
+
76
+ ### How It Works
77
+
78
+ Export SecureNow's middleware to capture bodies **before your handlers**:
79
+
80
+ ```typescript
81
+ // middleware.ts
82
+ export { middleware } from 'securenow/nextjs-middleware';
83
+
84
+ export const config = {
85
+ matcher: '/api/:path*',
86
+ };
87
+ ```
88
+
89
+ ### ✅ Pros
90
+
91
+ - One-time setup (no per-route wrapping)
92
+ - Applies to all routes automatically
93
+
94
+ ### ❌ Cons
95
+
96
+ - **Can conflict with NextAuth** and other middleware
97
+ - **May block requests** from reaching handlers
98
+ - **All-or-nothing** - applies to all matched routes
99
+ - **Runs before routing** - can interfere with request flow
100
+ - **May cause "Response body disturbed or locked" errors**
101
+
102
+ ### When to Use
103
+
104
+ - You have no other middleware
105
+ - You want to capture ALL routes
106
+ - You're okay with potential conflicts
107
+ - **Not recommended if you use NextAuth or have complex middleware**
108
+
109
+ ### Known Issues
110
+
111
+ **Conflicts with NextAuth:**
112
+ ```typescript
113
+ // ❌ This can cause conflicts
114
+ export { middleware } from 'securenow/nextjs-middleware';
115
+
116
+ // If you also use NextAuth, you'll need complex middleware composition
117
+ ```
118
+
119
+ **Solution:** Use the wrapper approach instead!
120
+
121
+ 📚 **Full guide:** See `NEXTJS-BODY-CAPTURE.md` (but consider wrapper approach first)
122
+
123
+ ---
124
+
125
+ ## 🔄 Comparison Table
126
+
127
+ | Feature | Wrapper Approach | Middleware Approach |
128
+ |---------|-----------------|---------------------|
129
+ | **Setup complexity** | Per-route wrapping | One-time setup |
130
+ | **Middleware conflicts** | ✅ None | ⚠️ Possible |
131
+ | **NextAuth compatibility** | ✅ Perfect | ❌ Can conflict |
132
+ | **Request blocking** | ✅ Never | ⚠️ Possible |
133
+ | **Control granularity** | ✅ Per-route | ❌ All-or-nothing |
134
+ | **Error impact** | ✅ Isolated | ⚠️ Can block all routes |
135
+ | **Recommended for** | ✅ Most users | ⚠️ Simple apps only |
136
+
137
+ ---
138
+
139
+ ## 🎯 Our Recommendation
140
+
141
+ ### For Most Users (Especially with NextAuth)
142
+
143
+ **Use the Wrapper Approach:**
144
+
145
+ ```typescript
146
+ // middleware.ts - Your auth logic (no securenow!)
147
+ export async function middleware(request) {
148
+ // Just your middleware - no securenow imports
149
+ const token = await getToken({ req: request });
150
+ if (!token) return NextResponse.redirect('/login');
151
+ return NextResponse.next();
152
+ }
153
+
154
+ // app/api/protected/route.ts - Wrap individual routes
155
+ import { withSecureNow } from 'securenow/nextjs-wrapper';
156
+
157
+ export const POST = withSecureNow(async (request: Request) => {
158
+ // Your handler - no conflicts!
159
+ const body = await request.json();
160
+ return Response.json({ success: true });
161
+ });
162
+ ```
163
+
164
+ **Why?**
165
+ - ✅ Zero conflicts
166
+ - ✅ Your middleware stays clean
167
+ - ✅ Per-route control
168
+ - ✅ Never blocks requests
169
+
170
+ ### For Simple Apps (No Other Middleware)
171
+
172
+ **You can use Middleware Approach:**
173
+
174
+ ```typescript
175
+ // middleware.ts
176
+ export { middleware } from 'securenow/nextjs-middleware';
177
+
178
+ export const config = {
179
+ matcher: '/api/:path*',
180
+ };
181
+ ```
182
+
183
+ **Why?**
184
+ - ✅ One-time setup
185
+ - ✅ Auto-applies to all routes
186
+ - ⚠️ But be aware of potential conflicts if you add other middleware later
187
+
188
+ ---
189
+
190
+ ## 📊 Real-World Scenarios
191
+
192
+ ### Scenario 1: NextAuth + SecureNow
193
+
194
+ **❌ Middleware Approach - Can Cause Issues:**
195
+ ```typescript
196
+ // middleware.ts
197
+ import { getToken } from 'next-auth/jwt';
198
+ import { middleware as securenowMiddleware } from 'securenow/nextjs-middleware';
199
+
200
+ export async function middleware(request) {
201
+ // Complex composition needed - prone to conflicts
202
+ await securenowMiddleware(request);
203
+ const token = await getToken({ req: request });
204
+ // ...
205
+ }
206
+ ```
207
+
208
+ **✅ Wrapper Approach - Clean & Safe:**
209
+ ```typescript
210
+ // middleware.ts - Just NextAuth
211
+ export async function middleware(request) {
212
+ const token = await getToken({ req: request });
213
+ if (!token) return NextResponse.redirect('/login');
214
+ return NextResponse.next();
215
+ }
216
+
217
+ // app/api/*/route.ts - Add SecureNow per route
218
+ import { withSecureNow } from 'securenow/nextjs-wrapper';
219
+ export const POST = withSecureNow(handler);
220
+ ```
221
+
222
+ ### Scenario 2: Rate Limiting + SecureNow
223
+
224
+ **❌ Middleware Approach:**
225
+ ```typescript
226
+ // Multiple middleware = conflicts
227
+ ```
228
+
229
+ **✅ Wrapper Approach:**
230
+ ```typescript
231
+ // middleware.ts - Just rate limiting
232
+ export async function middleware(request) {
233
+ await checkRateLimit(request);
234
+ return NextResponse.next();
235
+ }
236
+
237
+ // routes - Add SecureNow
238
+ export const POST = withSecureNow(handler);
239
+ ```
240
+
241
+ ### Scenario 3: Simple API (No Other Middleware)
242
+
243
+ **✅ Either Approach Works:**
244
+
245
+ **Option A - Wrapper:**
246
+ ```typescript
247
+ export const POST = withSecureNow(handler);
248
+ ```
249
+
250
+ **Option B - Middleware:**
251
+ ```typescript
252
+ export { middleware } from 'securenow/nextjs-middleware';
253
+ ```
254
+
255
+ Both work fine when you have no other middleware!
256
+
257
+ ---
258
+
259
+ ## 🚀 Migration Guide
260
+
261
+ ### From Middleware to Wrapper
262
+
263
+ **Before:**
264
+ ```typescript
265
+ // middleware.ts
266
+ export { middleware } from 'securenow/nextjs-middleware';
267
+ export const config = { matcher: '/api/:path*' };
268
+ ```
269
+
270
+ **After:**
271
+ ```typescript
272
+ // middleware.ts - Delete securenow import!
273
+ // (Keep your other middleware like NextAuth)
274
+
275
+ // app/api/login/route.ts
276
+ import { withSecureNow } from 'securenow/nextjs-wrapper';
277
+ export const POST = withSecureNow(async (request) => {
278
+ // Your handler
279
+ });
280
+
281
+ // app/api/register/route.ts
282
+ import { withSecureNow } from 'securenow/nextjs-wrapper';
283
+ export const POST = withSecureNow(async (request) => {
284
+ // Your handler
285
+ });
286
+ ```
287
+
288
+ **Result:** No more conflicts! 🎉
289
+
290
+ ---
291
+
292
+ ## ✅ Summary
293
+
294
+ ### Quick Decision Guide
295
+
296
+ **Do you have NextAuth or other middleware?**
297
+ - Yes → Use **Wrapper Approach** ✅
298
+ - No → Either works, but wrapper is safer
299
+
300
+ **Do you want per-route control?**
301
+ - Yes → Use **Wrapper Approach** ✅
302
+ - No → Middleware works
303
+
304
+ **Do you prioritize zero conflicts?**
305
+ - Yes → Use **Wrapper Approach** ✅
306
+ - Not critical → Middleware works
307
+
308
+ **Do you experience "Response body disturbed" errors?**
309
+ - Yes → Switch to **Wrapper Approach** ✅
310
+
311
+ ### Bottom Line
312
+
313
+ **For 90% of users:** Use the **Wrapper Approach**
314
+
315
+ It's safer, more flexible, and conflict-free!
316
+
317
+ 📚 **Full documentation:**
318
+ - Wrapper: `NEXTJS-WRAPPER-APPROACH.md`
319
+ - Middleware: `NEXTJS-BODY-CAPTURE.md`
320
+
@@ -0,0 +1,368 @@
1
+ # Next.js Body Capture - Self-Sufficient Solution
2
+
3
+ ## 🚀 Enable Body Capture in Next.js (2 Steps)
4
+
5
+ ### Step 1: Enable in Environment
6
+
7
+ ```bash
8
+ # .env.local
9
+ SECURENOW_CAPTURE_BODY=1
10
+ ```
11
+
12
+ ### Step 2: Create middleware.ts
13
+
14
+ **Just ONE line!** Create `middleware.ts` in your project root:
15
+
16
+ ```typescript
17
+ export { middleware } from 'securenow/nextjs-middleware';
18
+
19
+ export const config = {
20
+ matcher: '/api/:path*', // Apply to API routes
21
+ };
22
+ ```
23
+
24
+ **That's it!** 🎉 Bodies are now captured with sensitive data automatically redacted.
25
+
26
+ ---
27
+
28
+ ## ✨ Why This Works
29
+
30
+ **Self-sufficient design:**
31
+ - ✅ **One-line import** - No code to write
32
+ - ✅ **All logic in package** - Redaction, parsing, size limits
33
+ - ✅ **Zero configuration** - Works with defaults
34
+ - ✅ **Doesn't lock request stream** - Uses `request.clone()`
35
+ - ✅ **Safe by default** - 20+ sensitive fields redacted
36
+
37
+ **No customer code changes needed!** Just import and configure where to apply.
38
+
39
+ ---
40
+
41
+ ## 📊 What Gets Captured
42
+
43
+ ### ✅ JSON Requests
44
+
45
+ ```json
46
+ POST /api/users
47
+ Content-Type: application/json
48
+
49
+ {
50
+ "username": "john",
51
+ "password": "secret123" ← Automatically redacted
52
+ }
53
+ ```
54
+
55
+ **Captured:**
56
+ ```json
57
+ {
58
+ "username": "john",
59
+ "password": "[REDACTED]"
60
+ }
61
+ ```
62
+
63
+ ### ✅ GraphQL Requests
64
+
65
+ ```graphql
66
+ POST /api/graphql
67
+ Content-Type: application/graphql
68
+
69
+ mutation Login {
70
+ login(email: "john@example.com", password: "secret") ← Redacted
71
+ }
72
+ ```
73
+
74
+ **Captured:**
75
+ ```graphql
76
+ mutation Login {
77
+ login(email: "john@example.com", password: "[REDACTED]")
78
+ }
79
+ ```
80
+
81
+ ### ✅ Form Data
82
+
83
+ ```http
84
+ POST /api/contact
85
+ Content-Type: application/x-www-form-urlencoded
86
+
87
+ name=John&email=john@example.com&message=Hello
88
+ ```
89
+
90
+ **Captured:**
91
+ ```json
92
+ {
93
+ "name": "John",
94
+ "email": "john@example.com",
95
+ "message": "Hello"
96
+ }
97
+ ```
98
+
99
+ ---
100
+
101
+ ## ⚙️ Configuration
102
+
103
+ ### Matcher Patterns
104
+
105
+ **Apply to all API routes:**
106
+ ```typescript
107
+ export const config = {
108
+ matcher: '/api/:path*',
109
+ };
110
+ ```
111
+
112
+ **Apply to specific routes:**
113
+ ```typescript
114
+ export const config = {
115
+ matcher: ['/api/login', '/api/register', '/api/graphql'],
116
+ };
117
+ ```
118
+
119
+ **Apply to everything except static files:**
120
+ ```typescript
121
+ export const config = {
122
+ matcher: '/((?!_next/static|_next/image|favicon.ico).*)',
123
+ };
124
+ ```
125
+
126
+ **Apply to multiple patterns:**
127
+ ```typescript
128
+ export const config = {
129
+ matcher: ['/api/:path*', '/graphql'],
130
+ };
131
+ ```
132
+
133
+ ### Environment Variables
134
+
135
+ ```bash
136
+ # Max body size (default: 10KB)
137
+ SECURENOW_MAX_BODY_SIZE=20480
138
+
139
+ # Custom sensitive fields to redact
140
+ SECURENOW_SENSITIVE_FIELDS=email,phone,address
141
+
142
+ # Enable debug logging
143
+ OTEL_LOG_LEVEL=debug
144
+ ```
145
+
146
+ ---
147
+
148
+ ## 🔒 Security Features
149
+
150
+ ### Automatic Redaction (20+ Fields)
151
+
152
+ These are **always redacted**:
153
+ ```
154
+ password, passwd, pwd, secret, token, api_key, apikey,
155
+ access_token, auth, credentials, mysql_pwd, stripeToken,
156
+ card, cardnumber, cvv, cvc, ccv, ssn, pin
157
+ ```
158
+
159
+ ### Custom Sensitive Fields
160
+
161
+ Add your own:
162
+ ```bash
163
+ SECURENOW_SENSITIVE_FIELDS=credit_card,phone_number,dob
164
+ ```
165
+
166
+ Now these are also redacted automatically!
167
+
168
+ ### Size Protection
169
+
170
+ Bodies larger than `SECURENOW_MAX_BODY_SIZE` show:
171
+ ```
172
+ [TOO LARGE: 50000 bytes]
173
+ ```
174
+
175
+ ---
176
+
177
+ ## 🎯 File Structure
178
+
179
+ ```
180
+ your-nextjs-app/
181
+ ├── middleware.ts ← Create this (1 line import!)
182
+ ├── instrumentation.ts ← Already created by installer
183
+ ├── .env.local ← Set SECURENOW_CAPTURE_BODY=1
184
+ ├── app/
185
+ │ └── api/
186
+ │ ├── login/route.ts ← Bodies auto-captured
187
+ │ ├── users/route.ts ← Bodies auto-captured
188
+ │ └── graphql/route.ts ← Bodies auto-captured
189
+ └── ...
190
+ ```
191
+
192
+ ---
193
+
194
+ ## 🧪 Testing
195
+
196
+ ### Test Body Capture
197
+
198
+ 1. **Create middleware.ts:**
199
+ ```typescript
200
+ export { middleware } from 'securenow/nextjs-middleware';
201
+ export const config = { matcher: '/api/:path*' };
202
+ ```
203
+
204
+ 2. **Enable in .env.local:**
205
+ ```bash
206
+ SECURENOW_CAPTURE_BODY=1
207
+ ```
208
+
209
+ 3. **Make a test request:**
210
+ ```bash
211
+ curl -X POST http://localhost:3000/api/test \
212
+ -H "Content-Type: application/json" \
213
+ -d '{"username":"test","password":"secret123"}'
214
+ ```
215
+
216
+ 4. **Check SigNoz:**
217
+ - Find the `/api/test` trace
218
+ - Look for `http.request.body` attribute
219
+ - Verify password shows `[REDACTED]`
220
+
221
+ ### Debug Mode
222
+
223
+ ```bash
224
+ OTEL_LOG_LEVEL=debug npm run dev
225
+ ```
226
+
227
+ You'll see:
228
+ ```
229
+ [securenow] 📝 Body capture enabled
230
+ [securenow] 📚 Import middleware from securenow/nextjs-middleware
231
+ ```
232
+
233
+ ---
234
+
235
+ ## 🎓 Complete Setup Example
236
+
237
+ ### 1. instrumentation.ts (auto-created by installer)
238
+
239
+ ```typescript
240
+ import { registerSecureNow } from 'securenow/nextjs';
241
+
242
+ export function register() {
243
+ registerSecureNow();
244
+ }
245
+ ```
246
+
247
+ ### 2. middleware.ts (create this for body capture)
248
+
249
+ ```typescript
250
+ export { middleware } from 'securenow/nextjs-middleware';
251
+
252
+ export const config = {
253
+ matcher: '/api/:path*',
254
+ };
255
+ ```
256
+
257
+ ### 3. .env.local
258
+
259
+ ```bash
260
+ # Required
261
+ SECURENOW_APPID=my-nextjs-app
262
+ SECURENOW_INSTANCE=http://your-signoz:4318
263
+
264
+ # Optional: Enable body capture
265
+ SECURENOW_CAPTURE_BODY=1
266
+ SECURENOW_MAX_BODY_SIZE=20480
267
+ SECURENOW_SENSITIVE_FIELDS=email,phone
268
+ ```
269
+
270
+ ### 4. Done! ✅
271
+
272
+ ```bash
273
+ npm run dev
274
+ ```
275
+
276
+ ---
277
+
278
+ ## 💡 Why Two Files?
279
+
280
+ **instrumentation.ts** - OpenTelemetry setup (required)
281
+ - Sets up tracing infrastructure
282
+ - Auto-captures IP, headers, geo data
283
+ - Runs for all requests
284
+
285
+ **middleware.ts** - Body capture (optional)
286
+ - Intercepts requests to clone and read body
287
+ - Only needed if you want body capture
288
+ - Can be applied selectively to routes
289
+
290
+ **Separation = flexibility!** You can have tracing without body capture.
291
+
292
+ ---
293
+
294
+ ## ⚡ Performance
295
+
296
+ **Overhead per request:**
297
+ - **Without middleware:** 0ms (just tracing)
298
+ - **With middleware:** < 1ms (clone + parse + redact)
299
+
300
+ **The middleware:**
301
+ - Uses `request.clone()` - doesn't lock original
302
+ - Runs async - doesn't block request
303
+ - Fails gracefully - errors don't break app
304
+
305
+ ---
306
+
307
+ ## ❓ FAQ
308
+
309
+ ### Q: Is this truly self-sufficient?
310
+
311
+ **A:** Yes! Just export the middleware:
312
+ ```typescript
313
+ export { middleware } from 'securenow/nextjs-middleware';
314
+ ```
315
+
316
+ All logic (parsing, redaction, size limits) is in the package.
317
+
318
+ ### Q: Do I need to write any redaction code?
319
+
320
+ **A:** No! 20+ sensitive fields are redacted automatically. Just add custom ones if needed via env vars.
321
+
322
+ ### Q: Can I customize the redaction?
323
+
324
+ **A:** Yes, via environment variables:
325
+ ```bash
326
+ SECURENOW_SENSITIVE_FIELDS=my_custom_field,another_field
327
+ ```
328
+
329
+ ### Q: Will this slow down my app?
330
+
331
+ **A:** No! < 1ms overhead. Uses `request.clone()` so original is unaffected.
332
+
333
+ ### Q: Can I apply to specific routes only?
334
+
335
+ **A:** Yes! Use the matcher config:
336
+ ```typescript
337
+ export const config = {
338
+ matcher: ['/api/login', '/api/graphql'],
339
+ };
340
+ ```
341
+
342
+ ### Q: What if I don't want body capture?
343
+
344
+ **A:** Don't create `middleware.ts`! Just use `instrumentation.ts` for tracing without bodies.
345
+
346
+ ---
347
+
348
+ ## 🎉 Summary
349
+
350
+ **Enable body capture:**
351
+
352
+ 1. ```bash
353
+ SECURENOW_CAPTURE_BODY=1 # in .env.local
354
+ ```
355
+
356
+ 2. ```typescript
357
+ export { middleware } from 'securenow/nextjs-middleware'; # in middleware.ts
358
+ ```
359
+
360
+ **Result:**
361
+ - ✅ All request bodies captured
362
+ - ✅ Sensitive data redacted
363
+ - ✅ JSON, GraphQL, Form supported
364
+ - ✅ No customer code changes
365
+ - ✅ Package handles everything
366
+
367
+ **Self-sufficient design** - customers just import and configure! 🚀
368
+