Skip to content

Handle malformed auth recovery request bodies#193

Merged
ralyodio merged 1 commit into
profullstack:masterfrom
morganschp:fix-auth-recovery-invalid-json
May 23, 2026
Merged

Handle malformed auth recovery request bodies#193
ralyodio merged 1 commit into
profullstack:masterfrom
morganschp:fix-auth-recovery-invalid-json

Conversation

@morganschp
Copy link
Copy Markdown
Contributor

Summary

  • Reuse safeParseBody in forgot-password, reset-password, resend-confirmation, and auth-confirmed routes so malformed/empty/non-object JSON returns 400 instead of falling into 500 handlers.
  • Keep the auth-confirmed webhook secret check before body parsing.
  • Add regression tests proving malformed JSON does not call Supabase or send email side effects.

Fixes #192

Verification

  • ./node_modules/.bin/vitest run src/app/api/auth/forgot-password/route.test.ts src/app/api/auth/reset-password/route.test.ts src/app/api/auth/resend-confirmation/route.test.ts src/app/api/auth/confirmed/route.test.ts
  • ./node_modules/.bin/eslint src/app/api/auth/forgot-password/route.ts src/app/api/auth/reset-password/route.ts src/app/api/auth/resend-confirmation/route.ts src/app/api/auth/confirmed/route.ts src/app/api/auth/forgot-password/route.test.ts src/app/api/auth/reset-password/route.test.ts src/app/api/auth/resend-confirmation/route.test.ts src/app/api/auth/confirmed/route.test.ts
  • ./node_modules/.bin/tsc --noEmit --pretty false
  • git diff --check -- src/app/api/auth/forgot-password/route.ts src/app/api/auth/reset-password/route.ts src/app/api/auth/resend-confirmation/route.ts src/app/api/auth/confirmed/route.ts src/app/api/auth/forgot-password/route.test.ts src/app/api/auth/reset-password/route.test.ts src/app/api/auth/resend-confirmation/route.test.ts src/app/api/auth/confirmed/route.test.ts

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 23, 2026

Greptile Summary

This PR replaces raw request.json() calls with the existing safeParseBody utility in four auth routes (forgot-password, reset-password, resend-confirmation, confirmed), converting malformed/empty/non-object JSON bodies from unhandled 500 errors into explicit 400 responses. Regression tests are added for all four routes to verify no Supabase or email side effects occur on bad input.

  • confirmed/route.ts correctly keeps the webhook secret (AUTH_WEBHOOK_SECRET) check before calling safeParseBody, preserving the intended authorization ordering.
  • safeParseBody also quietly passes JSON arrays through (since typeof [] === \"object\"), spreading them to numeric-keyed objects via stripProtoPollution; the three Zod-validated routes reject these naturally, and the confirmed webhook treats them as a no-op skip — benign but worth noting if a stricter check is ever wanted.

Confidence Score: 5/5

Safe to merge — the changes are narrow, well-tested, and harden error handling without altering any successful-path logic.

Each route now returns a deterministic 400 for malformed input instead of falling into the catch-all 500 handler. The webhook secret check in the confirmed route is unchanged and still runs before body parsing. Regression tests cover all four routes and assert that downstream side effects do not fire on bad input.

No files require special attention. src/lib/sanitize.ts (not changed here) silently accepts JSON arrays; this does not affect the routes in this PR but would be worth addressing if safeParseBody is reused in contexts that must distinguish arrays from objects.

Important Files Changed

Filename Overview
src/app/api/auth/confirmed/route.ts Replaces raw request.json() with safeParseBody; adds AuthWebhookPayload local type; webhook secret check correctly remains before body parsing.
src/app/api/auth/forgot-password/route.ts Replaces request.json() with safeParseBody; adds null guard returning 400 before Zod validation; straightforward and correct.
src/app/api/auth/resend-confirmation/route.ts Replaces request.json() with safeParseBody; rate-limit check correctly stays before body parsing; null guard returns 400 for malformed input.
src/app/api/auth/reset-password/route.ts Replaces request.json() with safeParseBody; adds null guard returning 400; no behavioral changes beyond malformed-body handling.
src/app/api/auth/confirmed/route.test.ts Adds makeRawRequest helper and malformed-JSON regression test; AUTH_WEBHOOK_SECRET is set in beforeEach, so the new test's auth flow is correctly exercised.
src/app/api/auth/forgot-password/route.test.ts New test file covering valid email, invalid email, and malformed JSON; asserts Supabase is not called on bad input.
src/app/api/auth/reset-password/route.test.ts New test file covering valid password update, invalid password, and malformed JSON; asserts Supabase updateUser is not called on bad input.
src/app/api/auth/resend-confirmation/route.test.ts Extends existing test file with makeRawRequest helper and malformed-JSON regression; mocks are set up correctly.

Reviews (1): Last reviewed commit: "Handle malformed auth recovery bodies" | Re-trigger Greptile

@ralyodio ralyodio merged commit 55a5da3 into profullstack:master May 23, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: auth recovery APIs return 500 on malformed JSON

2 participants