Skip to content

feat: Implement proper password reset flow #199

@Xhristin3

Description

@Xhristin3

Problem Statement

The API has no password reset mechanism (forgot-password + reset-password endpoints). Users who forget their password have no way to recover their account. The auth controller (api/src/auth/auth.controller.ts) only exposes register and login. No email integration exists.

Evidence

// api/src/auth/auth.controller.ts — no reset-password endpoints
@Controller("auth") export class AuthController {
  @Post("register") register(...) { ... }
  @Post("login") login(...) { ... }
}

Impact

Zero account recovery capability. Users locked out permanently if they forget their password. No admin override for password resets. This makes the system unusable for real user accounts.

Proposed Solution

  1. Add POST /auth/forgot-password — accepts email, sends reset token (via email service)
  2. Add POST /auth/reset-password — accepts reset token + new password, updates hash
  3. Store reset tokens in password_reset_tokens table with TTL (1 hour) and one-time-use enforcement
  4. Rate limit both endpoints aggressively (3 attempts per hour per email)

Technical Requirements

  • Reset tokens must be cryptographically random (crypto.randomBytes)
  • Reset tokens must be hashed in DB (SHA-256)
  • Tokens must expire after 1 hour
  • One-time use enforced
  • Email address must not leak whether it exists (always return success message)

Acceptance Criteria

  • POST /auth/forgot-password returns success regardless of whether email exists
  • POST /auth/reset-password with valid token updates password
  • POST /auth/reset-password with expired token returns error
  • POST /auth/reset-password with used token returns error
  • Old JWT tokens invalidated after password reset
  • Rate limited at 3 attempts/hour/email

File Map

  • api/src/auth/auth.controller.ts — add endpoints
  • api/src/auth/auth.service.ts — add reset logic
  • api/src/auth/password-reset.service.ts — new service
  • database/migrations/2026061502_add_password_reset_tokens.up.sql
  • database/migrations/2026061502_add_password_reset_tokens.down.sql

Dependencies

  • Blocked by: REPO-003 (need DB) or REPO-004 (connection pool)

Testing Strategy

  • Unit: Test token generation, hashing, expiry validation
  • Unit: Test one-time-use enforcement
  • Integration: Test full forgot-password → reset-password → login flow
  • Test anti-enumeration (email existence not leaked)

Security Considerations

Reset tokens must be single-use, time-limited, rate-limited, and stored hashed. Email must never reveal whether it exists. Password change must invalidate all existing sessions. Reset URL must be served over HTTPS.


Labels: feature, security, high impact
Priority: High | Difficulty: Intermediate | Estimated Effort: 2d


Labels: feature,security,high impact
Priority: High | Difficulty: Intermediate | Estimated Effort: 2d
Backlog ID: REPO-016

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions