Password
Flow Summary
The current password module has two paths:
Forgot Password Flow
Step 1. Request reset OTPPOST /api/v1/auth/forgot-password
Step 2. Verify OTPPOST /api/v1/auth/verify-otp
Step 3. Reset passwordPOST /api/v1/auth/reset-password
Logged-in Password Change
Step 1. Update passwordPOST /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_numberoremailis 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 returns0. - 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_idis 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_passwordis 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_passwordmust match the current passwordnew_passwordmust be at least 6 charactersnew_passwordmust not contain spacesnew_passwordmust matchconfirm_passwordnew_passwordmust not be the same asold_password
Common failures
400: invalid request body400: new password and confirm password do not match400: new password is too short or contains spaces401: old password is wrong404: user not found
Integration Notes
- Use the forgot-password flow for signed-out recovery.
verify-otpin this flow is tied to the password-reset session returned byforgot-password.- After password reset revokes existing tokens, issue a new access token with Connect Token.