Skip to content

Fix/forgot password 404 #253#288

Open
amarakaushik8-debug wants to merge 3 commits into
vishnukothakapu:mainfrom
amarakaushik8-debug:fix/forgot-password-404
Open

Fix/forgot password 404 #253#288
amarakaushik8-debug wants to merge 3 commits into
vishnukothakapu:mainfrom
amarakaushik8-debug:fix/forgot-password-404

Conversation

@amarakaushik8-debug

@amarakaushik8-debug amarakaushik8-debug commented May 31, 2026

Copy link
Copy Markdown

Program Description

I would like this to be approved under GSSoC'26.

What does this PR do?

Implements the forgot password and reset password flow. Previously, clicking
"Forgot Password?" on the login page returned a 404 error because the route
and pages did not exist. This PR creates the full password reset flow including
UI pages, API routes, database model, and email delivery.

Related Issue

Closes #253

Type of Change

  • Bug fix
  • New feature

How to Test

  1. Go to Get Started and click "Forgot Password?"
  2. Enter a registered email address and click "Send Reset Link".
  3. Check your inbox for a password reset email.
  4. Click the reset link in the email.
  5. Enter a new password and click "Reset Password".
  6. Verify you are redirected to /login and can log in with the new password.

Screenshots (if UI change)

Before:-
https://github.com/user-attachments/assets/3a15542e-75e9-41df-811e-92995ed9ad28

Now:-
Forgot Password Page:
https://github.com/user-attachments/assets/5d59aa22-482e-46da-b79e-3feb55b9e052

Reset Password Page:
https://github.com/user-attachments/assets/a653227b-8a60-4e3b-99af-59ee22ea9f32

Reset Email:
https://github.com/user-attachments/assets/0e41bca5-43de-45f2-b73f-61e35236d6da

Checklist

  • Code follows project conventions
  • Self-reviewed the changes
  • No console.log left behind
  • No new TypeScript errors

Note for Maintainers

SMTP credentials need to be configured in production environment variables
(SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, EMAIL_FROM) for password reset
emails to be delivered.

Summary by CodeRabbit

  • New Features
    • Added password reset functionality with email-based account recovery. Users can request a password reset, receive a secure reset link via email with a time-limited token, and set a new password. The process includes validation and account security measures.

@vercel

vercel Bot commented May 31, 2026

Copy link
Copy Markdown

@amarakaushik8-debug is attempting to deploy a commit to the vishnukothakapu's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@amarakaushik8-debug, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 39 minutes and 8 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: cb9e94ca-c413-461a-9a24-9d73e954b75e

📥 Commits

Reviewing files that changed from the base of the PR and between 5838ef1 and 9970dc9.

📒 Files selected for processing (3)
  • app/api/auth/reset-password/route.ts
  • app/forgot-password/page.tsx
  • app/reset-password/page.tsx
📝 Walkthrough

Walkthrough

This PR implements a complete password reset feature: adds a PasswordResetToken Prisma model for persistence, creates a forgot-password API endpoint that generates 1-hour tokens and sends reset emails, implements a reset-password API endpoint that validates tokens and updates passwords, and provides corresponding client-side pages for users to request and apply password resets.

Changes

Password Reset Feature

Layer / File(s) Summary
Password Reset Token Schema
prisma/schema.prisma
PasswordResetToken model stores reset tokens with unique constraint on token, email indexing for lookups, and 1-hour expiration tracking.
Forgotten Password API Endpoint
app/api/auth/forgot-password/route.ts
POST handler validates email, creates a unique cryptographic token with 1-hour expiry in the database, constructs a reset URL using NEXTAUTH_URL, sends a reset email, and returns generic success without revealing account existence.
Password Reset API Endpoint
app/api/auth/reset-password/route.ts
POST handler validates token and password, queries for a matching unexpired reset token, bcrypt-hashes the new password, updates the user, deletes the consumed token, and returns success or validation errors.
Forgotten Password Request Page
app/forgot-password/page.tsx
Client form component with email input that submits to the forgot-password API, displays errors on failure, and shows a "Check your email" confirmation view on success with a link back to login.
Password Reset Confirmation Page
app/reset-password/page.tsx
Client form component that extracts token from URL params, renders password + confirmation fields, validates matching passwords, submits to the reset-password API, displays success with 2-second auto-redirect to login, or shows validation errors with back-to-login navigation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • #253: [BUG] Login Attempt Returns 404 Error — This PR addresses the missing forgot-password and reset-password pages referenced in the bug report; the 404 errors when clicking "Forgot Password?" should be resolved by the new /forgot-password and /reset-password routes added in this PR.

Poem

🐰 A token takes flight on the midnight breeze,
Email whispers secrets through cyber trees,
Password renewed with cryptographic care,
Reset routes complete—recovery's there!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix/forgot password 404 #253' directly addresses the main objective of fixing the 404 error when accessing the forgot password functionality, matching the core issue requirement.
Linked Issues check ✅ Passed The PR implements all coding requirements from issue #253: forgot password page, reset password page, API endpoints for password reset flow, database model, and email delivery mechanism.
Out of Scope Changes check ✅ Passed All changes are focused on resolving the 404 error and implementing the password reset flow. The AI-based password strength check mentioned in issue #253 is not implemented, which is appropriate as a suggestion for future work.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
app/api/auth/forgot-password/route.ts (1)

24-26: ⚡ Quick win

Consider cleaning up existing tokens before creating a new one.

When a user requests multiple password resets, old tokens accumulate in the database. Deleting previous tokens for the same email prevents DB bloat and ensures only the latest token is valid.

♻️ Suggested fix
+    // Remove any existing tokens for this email
+    await prisma.passwordResetToken.deleteMany({ where: { email } });
+
     await prisma.passwordResetToken.create({
       data: { email, token, expires },
     });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/api/auth/forgot-password/route.ts` around lines 24 - 26, Before creating
a new password reset token, remove any existing tokens for that email to prevent
accumulation: call prisma.passwordResetToken.deleteMany({ where: { email } })
(or wrap deleteMany + create in prisma.$transaction([...]) for atomicity)
immediately before prisma.passwordResetToken.create({ data: { email, token,
expires } }) in the forgot-password route handler so only the newest token
remains valid.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/api/auth/reset-password/route.ts`:
- Around line 10-12: The current check only verifies token and password
truthiness; update the validation in the reset handler to enforce a minimum
password length (e.g., >= 8). Specifically, after extracting token and password,
change the existing conditional that uses (!token || !password) to also check
password.length and return NextResponse.json({ error: "Password too short" }, {
status: 400 }) when it fails; keep the same token missing behavior via the token
variable and NextResponse usage so the handler rejects weak passwords early.

In `@app/forgot-password/page.tsx`:
- Around line 38-40: Update the JSX text nodes that contain unescaped
apostrophes in the forgot-password page: find the <p
className="text-muted-foreground"> elements that render "If that email exists,
we've sent a password reset link." and the other paragraph rendering "we'll" and
replace raw apostrophes with HTML entities (use &apos; for '), so the displayed
text becomes "we&apos;ve" and "we&apos;ll" to satisfy ESLint's
unescaped-entities rule.
- Around line 17-24: Wrap the fetch in a try-catch-finally inside the submit
handler (the function that calls fetch in app/forgot-password/page.tsx) so
network or JSON parse errors are caught and loading is always cleared;
specifically, call fetch(...) and then await res.json() inside a try block,
check res.ok and handle non-2xx responses, catch any thrown error to set an
error state or show a message, and move setLoading(false) into a finally block
so loading cannot remain true after failures (refer to the const res = await
fetch(...) / const data = await res.json(); setLoading(false); sequence).

In `@app/reset-password/page.tsx`:
- Around line 26-33: The fetch call in app/reset-password/page.tsx that posts to
"/api/auth/reset-password" is not wrapped in try/catch, so network errors or
non-JSON responses can never reach the setLoading(false) line; wrap the
fetch/response parsing in a try block and move setLoading(false) to a finally
block so loading is always cleared, and in the catch set an error state (or
handle it) instead of letting the exception bubble. Specifically, update the
block around the fetch call and the subsequent await res.json() (the code using
token, password, const res = await fetch(...), const data = await res.json(),
and setLoading) to: perform fetch and check res.ok, attempt to parse JSON inside
a guarded try, handle parse failures gracefully, set an error message on
failure, and ensure setLoading(false) runs in finally.
- Around line 10-15: When the page reads the token from searchParams (const
token = searchParams.get("token")), handle the case token === null immediately:
set an error state (use setError with a user-friendly message like "Missing or
invalid reset token"), prevent rendering or disable the form/submit by using
that error state (and ensure loading/ success flows don't proceed), and avoid
calling the reset submit handler when token is null. Implement this by adding a
useEffect that checks token on mount and sets setError(true) / setError("...")
(or returns early from the component rendering) so components referencing
password, confirm, loading, success do not attempt a submission without a valid
token.

---

Nitpick comments:
In `@app/api/auth/forgot-password/route.ts`:
- Around line 24-26: Before creating a new password reset token, remove any
existing tokens for that email to prevent accumulation: call
prisma.passwordResetToken.deleteMany({ where: { email } }) (or wrap deleteMany +
create in prisma.$transaction([...]) for atomicity) immediately before
prisma.passwordResetToken.create({ data: { email, token, expires } }) in the
forgot-password route handler so only the newest token remains valid.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8527630a-3f6f-4855-89f3-94e3b38c0462

📥 Commits

Reviewing files that changed from the base of the PR and between f40f5c8 and 5838ef1.

📒 Files selected for processing (6)
  • app/api/auth/app/api/auth/reset-password/route.ts
  • app/api/auth/forgot-password/route.ts
  • app/api/auth/reset-password/route.ts
  • app/forgot-password/page.tsx
  • app/reset-password/page.tsx
  • prisma/schema.prisma

Comment thread app/api/auth/reset-password/route.ts Outdated
Comment thread app/forgot-password/page.tsx Outdated
Comment thread app/forgot-password/page.tsx
Comment thread app/reset-password/page.tsx
Comment thread app/reset-password/page.tsx Outdated
@amarakaushik8-debug

amarakaushik8-debug commented May 31, 2026

Copy link
Copy Markdown
Author

@vishnukothakapu please review it #288

@amarakaushik8-debug

Copy link
Copy Markdown
Author

@vishnukothakapu I would like this to be approved under GSSoC'26 pls

@vercel

vercel Bot commented Jun 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
linkid Error Error Jun 1, 2026 4:35am

@vedhapprakashni

Copy link
Copy Markdown
Collaborator

hey @amarakaushik8-debug

Critical Issues (must fix before merge)

  1. Ghost file: app/api/auth/app/api/auth/reset-password/route.ts
    The diff includes an empty file at a clearly broken path:

diff --git a/app/api/auth/app/api/auth/reset-password/route.ts b/app/api/auth/app/api/auth/reset-password/route.ts
new file mode 100644
index 0000000..e69de29

This path app/api/auth/app/api/auth/reset-password/ is a doubled nested path -obviously a mistake. This creates a useless empty file and a junk directory. It needs to be deleted from the PR.

  1. No CSRF protection on either API route
    Both forgot-password and reset-password API routes have zero CSRF protection. Every other mutation endpoint in the codebase uses x-csrf-token headers. These routes accept unauthenticated POST requests, making them vulnerable to:

CSRF attacks :a malicious site could trigger password resets for arbitrary users
Brute force :no rate limiting on token submission

Need to add CSRF token validation (at minimum for reset-password), or use the existing middleware pattern.

  1. No rate limiting on forgot-password endpoint
    The /api/auth/forgot-password route has no rate limiting. An attacker can spam it to:

Flood a user's inbox with reset emails
Enumerate valid email addresses by timing differences (though the response message is identical either way, timing leaks could still exist)
At minimum, add a check for existing unexpired tokens before creating new ones.

  1. Token not hashed in database
    The reset token is stored in plaintext:

const token = crypto.randomBytes(32).toString("hex");
await prisma.passwordResetToken.create({
data: { email, token, expires },
});

If the database is ever compromised, an attacker gets all valid reset tokens.
Best practice: store a hashed version (crypto.createHash('sha256').update(token).digest('hex')) and compare hashes on lookup.

  1. Broken indentation in reset-password/route.ts

    if (!token || !password) {
    return NextResponse.json({ error: "Missing fields" }, { status: 400 });
    }
    if (password.length < 8) {
    return NextResponse.json({ error: "Password must be at least 8 characters" }, { status: 400 });
    }

Lines 89-93 have completely broken indentation :the return and if blocks jump from 4-space indent to 2-space indent. This suggests copy-paste errors.

Minor Issues (should fix)

  1. No "Forgot password" link added to login page
    The PR creates the /forgot-password and /reset-password pages, but doesn't add a "Forgot password?" link to the login page. Users have no way to discover this feature. The whole point of issue [BUG] Login Attempt Returns 404 Error #253 was that clicking "Forgot Password" gave a 404 -so presumably a link already exists, but if it points to a different path, this PR doesn't fix the routing.

  2. Pages use raw HTML elements instead of project's UI components
    The existing login and register pages use the project's , , components from @/components/ui/. The new pages use raw , , and

    with Tailwind classes:

This creates a visual inconsistency -these pages will look completely different from the rest of the app. They should use the existing shadcn/ui components.
  1. sendSupportEmail may not exist or match the expected signature

The forgot-password route imports:
import { sendSupportEmail } from "@/lib/email";

Need to verify this function exists and accepts the { to, subject, html } signature used here. If the codebase's email utility has a different API, this will crash at runtime.

  1. No password strength validation alignment
    The reset-password route requires password.length < 8, but the register page may have different password requirements (e.g., requiring uppercase, numbers, etc.). These should be consistent.

fix and lmk.

@amarakaushik8-debug

Copy link
Copy Markdown
Author

Sure will review and let you know

@vishnukothakapu

Copy link
Copy Markdown
Owner

Hi @ArshiBansal,

The build is currently failing with the following TypeScript error:

Type error: File '/vercel/path0/app/api/auth/app/api/auth/reset-password/route.ts' is not a module.

It looks like the route file may have one of the following issues:

  • The file does not export any route handler (GET, POST, etc.).
  • The file path may be incorrect or accidentally nested (app/api/auth/app/api/auth/reset-password/route.ts).
  • The file may be empty or contain invalid exports.

Could you please review the reset-password/route.ts file, ensure it exports a valid route handler, and verify that it is located in the correct directory?

After fixing the issue, please push the updated changes.

Thanks!

@ArshiBansal

Copy link
Copy Markdown
Contributor

@vishnukothakapu yea sure

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Login Attempt Returns 404 Error

4 participants