feat(auth): email-based password reset + in-settings password change #77

Merged
nrupard merged 1 commit from feat/password-reset into main 2026-05-12 16:52:26 +02:00
Owner

Adds a complete password recovery path for standalone deployments. The login page exposes a "Forgot password?" link that takes the user to /forgot, where they enter the email address attached to their account. The server hashes a 32-byte single-use token, stores the hash with a 60-minute TTL, and emails the raw token as a /reset/{token} link. Submitting that page sets a new Argon2id hash, burns every outstanding token for the user, and invalidates all existing sessions so any hijacked cookie stops working.

Outbound mail is configured via the conventional SMTP_HOST / SMTP_PORT / SMTP_TLS / SMTP_USERNAME / SMTP_PASSWORD / SMTP_FROM environment variables, matching common SMTP-relay configuration in other apps. SMTP_TLS accepts tls / starttls / none (plus boolean aliases). LETS_CHAT_BASE_URL controls the host used to build links inside outbound mail. Any required variable missing disables the mailer, in which case /forgot and /reset/{token} return 404 and the "Forgot password?" link becomes a dead end (mirrors the 2FA-when-no-secret-key pattern).

The /forgot endpoint always returns the same 200 notice so the page cannot be used to enumerate registered accounts, and the SMTP send happens off the response path so a slow relay does not gate the user-visible response.

Registration now collects an optional email address, and the existing profile form lets users add or change their email post-registration. Settings gains a "Change password" form (standalone only) that requires the current password and uses redirect query parameters to surface short error codes for "incorrect current password", "passwords do not match", "too short", and "same as current". Both flows reuse db::auth::set_password_hash so the underlying credential update is consolidated.

The compose.dev.yml SMTP block is committed as a commented template; copy and fill the values locally to enable the reset flow against a real relay.

Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

Adds a complete password recovery path for standalone deployments. The login page exposes a "Forgot password?" link that takes the user to /forgot, where they enter the email address attached to their account. The server hashes a 32-byte single-use token, stores the hash with a 60-minute TTL, and emails the raw token as a /reset/{token} link. Submitting that page sets a new Argon2id hash, burns every outstanding token for the user, and invalidates all existing sessions so any hijacked cookie stops working. Outbound mail is configured via the conventional SMTP_HOST / SMTP_PORT / SMTP_TLS / SMTP_USERNAME / SMTP_PASSWORD / SMTP_FROM environment variables, matching common SMTP-relay configuration in other apps. SMTP_TLS accepts tls / starttls / none (plus boolean aliases). LETS_CHAT_BASE_URL controls the host used to build links inside outbound mail. Any required variable missing disables the mailer, in which case /forgot and /reset/{token} return 404 and the "Forgot password?" link becomes a dead end (mirrors the 2FA-when-no-secret-key pattern). The /forgot endpoint always returns the same 200 notice so the page cannot be used to enumerate registered accounts, and the SMTP send happens off the response path so a slow relay does not gate the user-visible response. Registration now collects an optional email address, and the existing profile form lets users add or change their email post-registration. Settings gains a "Change password" form (standalone only) that requires the current password and uses redirect query parameters to surface short error codes for "incorrect current password", "passwords do not match", "too short", and "same as current". Both flows reuse db::auth::set_password_hash so the underlying credential update is consolidated. The compose.dev.yml SMTP block is committed as a commented template; copy and fill the values locally to enable the reset flow against a real relay. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(auth): email-based password reset + in-settings password change
Some checks failed
Check / clippy + fmt + tests (pull_request) Failing after 31s
06ddf6214a
Adds a complete password recovery path for standalone deployments. The login page exposes a "Forgot password?" link that takes the user to /forgot, where they enter the email address attached to their account. The server hashes a 32-byte single-use token, stores the hash with a 60-minute TTL, and emails the raw token as a /reset/{token} link. Submitting that page sets a new Argon2id hash, burns every outstanding token for the user, and invalidates all existing sessions so any hijacked cookie stops working.

Outbound mail is configured via the conventional SMTP_HOST / SMTP_PORT / SMTP_TLS / SMTP_USERNAME / SMTP_PASSWORD / SMTP_FROM environment variables, matching common SMTP-relay configuration in other apps. SMTP_TLS accepts tls / starttls / none (plus boolean aliases). LETS_CHAT_BASE_URL controls the host used to build links inside outbound mail. Any required variable missing disables the mailer, in which case /forgot and /reset/{token} return 404 and the "Forgot password?" link becomes a dead end (mirrors the 2FA-when-no-secret-key pattern).

The /forgot endpoint always returns the same 200 notice so the page cannot be used to enumerate registered accounts, and the SMTP send happens off the response path so a slow relay does not gate the user-visible response.

Registration now collects an optional email address, and the existing profile form lets users add or change their email post-registration. Settings gains a "Change password" form (standalone only) that requires the current password and uses redirect query parameters to surface short error codes for "incorrect current password", "passwords do not match", "too short", and "same as current". Both flows reuse db::auth::set_password_hash so the underlying credential update is consolidated.

The compose.dev.yml SMTP block is committed as a commented template; copy and fill the values locally to enable the reset flow against a real relay.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
nrupard deleted branch feat/password-reset 2026-05-12 16:52:27 +02:00
Sign in to join this conversation.
No reviewers
No labels
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
psa-systems/lets-chat!77
No description provided.