Files
fm_be/docs/password-reset.md
2026-07-16 22:16:45 +07:00

2.3 KiB

Password Reset

Endpoints

POST /api/v1/auth/forgot-password

Request:

{
  "data": {
    "type": "auth_forgot_password",
    "attributes": {
      "email": "user@example.com"
    }
  }
}

Response (200 always for valid payload):

{
  "data": {
    "type": "auth_forgot_password",
    "attributes": {
      "message": "If the account exists, a password reset link has been sent."
    }
  }
}

POST /api/v1/auth/reset-password

Request:

{
  "data": {
    "type": "auth_reset_password",
    "attributes": {
      "token": "<raw-token>",
      "new_password": "StrongPassphrase123!",
      "confirm_password": "StrongPassphrase123!"
    }
  }
}

Success response (200):

{
  "data": {
    "type": "auth_reset_password",
    "attributes": {
      "message": "Password has been reset successfully. Please log in again."
    }
  }
}

Invalid/expired/used token response (400):

{
  "errors": [
    {
      "status": "400",
      "title": "Invalid reset link",
      "detail": "This reset link is invalid or expired."
    }
  ]
}

Environment Variables

  • AUTH_PASSWORD_RESET_URL frontend reset page URL; backend appends ?token=...
  • AUTH_PASSWORD_RESET_TTL reset token TTL (default 20m, enforced 15-30m range)
  • AUTH_FORGOT_PASSWORD_EMAIL_COOLDOWN cooldown per email identifier (default 2m)
  • AUTH_FORGOT_PASSWORD_MIN_DURATION minimum forgot-password response duration (default 150ms)
  • AUTH_FORGOT_PASSWORD_IP_RATE_MAX per-IP max attempts in window (default 10)
  • AUTH_FORGOT_PASSWORD_IP_RATE_WINDOW per-IP window duration (default 15m)

Security Decisions

  • Uses crypto/rand for reset token entropy.
  • Stores only SHA-256 token hashes in DB (password_reset_tokens.token_hash).
  • Raw token is only delivered via email link.
  • Tokens are single-use (used_at) and expire (expires_at).
  • New forgot-password request invalidates previous active reset tokens for that user.
  • Successful reset invalidates all active reset tokens for the user.
  • Successful reset revokes active sessions by incrementing the MySQL-backed user session version used in JWT claims.
  • Forgot-password response is generic to prevent account enumeration.
  • Forgot-password throttling is applied per IP and per email identifier.