Bug: Password reset confirm returns HTTP 200 for invalid tokens #138

Closed
opened 2026-03-21 20:53:53 +00:00 by forgejo_admin · 0 comments

Type

Bug

Lineage

plan-wkq → Phase 11 (Girls Tryout — March 24)
Discovered during UX testing of password reset flow (basketball-api #132)

Repo

forgejo_admin/basketball-api + forgejo_admin/westside-app

What Broke

POST /api/password-reset/confirm returns HTTP 200 with {"message":"Invalid or expired reset token."} for invalid/expired tokens. The frontend checks status code only, sees 200, and shows "Your password has been updated" — even though nothing happened. A parent with an expired link thinks they reset their password, tries to sign in, and fails.

Repro Steps

  1. Go to /reset-password?token=any-invalid-token
  2. Enter new password + confirm
  3. Click "Update Password"
  4. See success message "Your password has been updated"
  5. Try to sign in — password unchanged, login fails

Expected Behavior

  • Backend: return HTTP 400 for invalid/expired/used tokens
  • Frontend: check response status, show error message for non-2xx responses

Environment

  • Cluster/namespace: basketball-api + westsidekingsandqueens
  • Service version: basketball-api PR #133, westside-app PR #63

Acceptance Criteria

  • POST /api/password-reset/confirm returns HTTP 400 for invalid/expired/used tokens
  • Frontend shows error message when API returns non-2xx
  • Frontend shows "link expired" with link back to /forgot-password to request a new one
  • Valid tokens still work and show success

File Targets

basketball-api:

  • src/basketball_api/routes/password_reset.py — change invalid token response from 200 to 400

westside-app:

  • src/routes/reset-password/+page.svelte — check res.ok before showing success, show error state on failure

Constraints

  • Keep returning 200 for the /request endpoint (no user enumeration)
  • Only fix the /confirm endpoint — invalid tokens are not a security enumeration risk

Checklist

  • PR opened
  • Tests updated
  • No unrelated changes
  • basketball-api #132 — parent feature
  • basketball-api #133 — backend PR that introduced the bug
  • westside-app #63 — frontend PR that doesn't check response
### Type Bug ### Lineage `plan-wkq` → Phase 11 (Girls Tryout — March 24) Discovered during UX testing of password reset flow (basketball-api #132) ### Repo `forgejo_admin/basketball-api` + `forgejo_admin/westside-app` ### What Broke `POST /api/password-reset/confirm` returns HTTP 200 with `{"message":"Invalid or expired reset token."}` for invalid/expired tokens. The frontend checks status code only, sees 200, and shows "Your password has been updated" — even though nothing happened. A parent with an expired link thinks they reset their password, tries to sign in, and fails. ### Repro Steps 1. Go to `/reset-password?token=any-invalid-token` 2. Enter new password + confirm 3. Click "Update Password" 4. See success message "Your password has been updated" 5. Try to sign in — password unchanged, login fails ### Expected Behavior - Backend: return HTTP 400 for invalid/expired/used tokens - Frontend: check response status, show error message for non-2xx responses ### Environment - Cluster/namespace: basketball-api + westsidekingsandqueens - Service version: basketball-api PR #133, westside-app PR #63 ### Acceptance Criteria - [ ] `POST /api/password-reset/confirm` returns HTTP 400 for invalid/expired/used tokens - [ ] Frontend shows error message when API returns non-2xx - [ ] Frontend shows "link expired" with link back to `/forgot-password` to request a new one - [ ] Valid tokens still work and show success ### File Targets **basketball-api:** - `src/basketball_api/routes/password_reset.py` — change invalid token response from 200 to 400 **westside-app:** - `src/routes/reset-password/+page.svelte` — check `res.ok` before showing success, show error state on failure ### Constraints - Keep returning 200 for the `/request` endpoint (no user enumeration) - Only fix the `/confirm` endpoint — invalid tokens are not a security enumeration risk ### Checklist - [ ] PR opened - [ ] Tests updated - [ ] No unrelated changes ### Related - basketball-api #132 — parent feature - basketball-api #133 — backend PR that introduced the bug - westside-app #63 — frontend PR that doesn't check response
forgejo_admin 2026-03-21 21:04:35 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo_admin/basketball-api#138
No description provided.