Authentication

Password

Reset a forgotten password or change it while logged in.

Flow Summary

The current password module has two paths:

Forgot Password Flow

Step 1. Request reset OTP
POST /api/v1/auth/forgot-password

Step 2. Verify OTP
POST /api/v1/auth/verify-otp

Step 3. Reset password
POST /api/v1/auth/reset-password

Logged-in Password Change

Step 1. Update password
POST /api/v1/auth/update-password

In development environments, the OTP is currently hardcoded to 123456.

1. Request Password Reset

POST /api/v1/auth/forgot-password

This endpoint is public. Send either phone details or an email address.

Phone request

{
  "phone_code": "855",
  "country_code": "KH",
  "phone_number": "012345678"
}

Email request

{
  "email": "user@example.com"
}

Success response

{
  "status_code": 200,
  "message": "OTP sent successfully",
  "data": {
    "session_id": "9b7f1b4d-7c75-4d14-bec8-0d03b0f809d6",
    "expires_at": 0
  }
}

Notes

  • At least one of phone_number or email is required.
  • The handler trims and normalizes phone input before service validation.
  • The OTP session is stored in Redis for 10 minutes.
  • The response DTO includes expires_at, but the current service does not populate it, so it returns 0.
  • Existing users only: unknown phone numbers or unknown emails return 404.
  • Inactive accounts are rejected even if the identifier exists.

2. Verify OTP For Password Reset

POST /api/v1/auth/verify-otp

This is the same shared OTP endpoint used by registration. For password reset, pass the session_id returned by forgot-password.

Request

{
  "phone_code": "855",
  "country_code": "KH",
  "phone_number": "012345678",
  "otp_code": "123456",
  "session_id": "9b7f1b4d-7c75-4d14-bec8-0d03b0f809d6"
}

Email-based resets can send email instead of the phone fields.

Success response

{
  "status_code": 200,
  "message": "OTP verified successfully",
  "data": {
    "success": true,
    "message": "OTP verified successfully",
    "session_id": "2f264af8-98c4-4a3d-89bc-5958c5ba6931",
    "expires_at": "0001-01-01T00:00:00Z"
  }
}

Notes

  • The old OTP session is deleted after a successful verification.
  • The returned session_id is a verification session, not the original OTP session.
  • The verification session is stored in Redis for 15 minutes.
  • The response schema includes expires_at, but the current service does not set it, so it serializes as the zero timestamp.

3. Reset Password

POST /api/v1/auth/reset-password

This endpoint is public, but it requires the verified session_id returned by verify-otp.

Request

{
  "session_id": "2f264af8-98c4-4a3d-89bc-5958c5ba6931",
  "new_password": "Secret123!"
}

Success response

{
  "status_code": 200,
  "message": "Password reset successfully",
  "data": null
}

Password rules

  • Minimum length: 6 characters
  • Spaces are not allowed
  • confirm_password is not part of this API

Notes

  • The service hashes the new password before saving it.
  • After a successful reset, the verification session is deleted.
  • The service revokes all existing user tokens after reset, so the user must log in again.

4. Update Password While Logged In

POST /api/v1/auth/update-password

This route is protected and requires:

Authorization: Bearer <access_token>

Request

{
  "old_password": "OldSecret123!",
  "new_password": "NewSecret123!",
  "confirm_password": "NewSecret123!"
}

Success response

{
  "status_code": 200,
  "message": "Password changed successfully",
  "data": null
}

Password rules

  • old_password must match the current password
  • new_password must be at least 6 characters
  • new_password must not contain spaces
  • new_password must match confirm_password
  • new_password must not be the same as old_password

Common failures

  • 400: invalid request body
  • 400: new password and confirm password do not match
  • 400: new password is too short or contains spaces
  • 401: old password is wrong
  • 404: user not found

Integration Notes

  1. Use the forgot-password flow for signed-out recovery.
  2. verify-otp in this flow is tied to the password-reset session returned by forgot-password.
  3. After password reset revokes existing tokens, issue a new access token with Connect Token.
Copyright © 2026