IAM - Password reset¶
- Status: Implemented
- Prefix:
RST - Module: iam
- Feature: password-reset
- Related: Sign-in, Change password, SMTP settings
Purpose¶
A person who cannot sign in requests a one-time email link and sets a new password without knowing the current one. Platform SMTP delivers the message. Success ends every session for that user.
Users and permissions¶
Any visitor on the tenant app may request a reset for an email address. Only an active workspace user who owns that email receives a link. Operators and admin-portal accounts are out of scope.
Requirements¶
| ID | Priority | Requirement |
|---|---|---|
| RST-01 | Must | POST /api/auth/forgot-password with a valid email always returns 200 and the same generic message whether or not the account exists, so the response does not reveal registration. |
| RST-02 | Must | When the email matches an active user, the API stores a single-use hashed token that expires in 15 minutes, invalidates any earlier unused tokens for that user, and asks the mail binder to send the password-reset template with a link to /reset-password?token=…. |
| RST-03 | Must | When the email is unknown, the user is locked, or SMTP is not configured, no usable token is left for the client and the response stays the generic success message. |
| RST-04 | Must | POST /api/auth/reset-password with a valid unused unexpired token and a password that passes the registration strength rule replaces the hash, deletes every session for that user, marks the token used, and returns 200. |
| RST-05 | Must | An expired, used, or unknown token is rejected with 400 and the password is unchanged. |
| RST-06 | Must | A new password that fails the registration strength rule is rejected with 400 before the hash is replaced. |
| RST-07 | Must | Sign-in shows a Forgot password link to /forgot-password. That page asks for email, posts forgot-password, and shows the generic confirmation. |
| RST-08 | Must | /reset-password?token=… asks for the new password twice, posts reset-password, and on success sends the person to sign-in with a success notice. |
| RST-09 | Should | When the two new-password fields differ, the reset form shows a mismatch message and does not call the API. |
Screens¶
- Sign-in: "Forgot password?" links to
/forgot-password. - Forgot password (
/forgot-password): email field, submit, link back to sign-in. After submit, show that if an account exists, instructions were sent. - Reset password (
/reset-password): new password, confirm password, submit. Token comes from the query string. Success navigates to/sign-inwith noticePassword reset successfully. Please sign in.
Business rules¶
- Token is 32 random bytes, stored only as SHA-256 (base64url). The raw token appears only in the email link.
- TTL is 15 minutes from creation. One successful use consumes the token.
- Password strength matches registration: at least 8 characters, with a letter, a number, and an uppercase letter.
- Mail is sent through the apps/api binder and
SmtpSettingsServiceusingrenderPasswordResetEmail. IAM does not importapi-system. - Reset link base URL is
WEB_APP_ORIGIN(defaulthttp://localhost:4200). - Locked users do not receive a reset email.
Acceptance criteria¶
- RST-01: Given any well-formed email, when forgot-password is posted, then the response is 200 with the generic message.
- RST-02: Given an active user and a working mail binder, when forgot-password is posted for that email, then a hashed token exists, earlier unused tokens for that user are gone, and the binder receives the reset URL.
- RST-03: Given an unknown email, when forgot-password is posted, then no token is created and the response is still the generic success.
- RST-04: Given a valid token, when reset-password is posted with a valid new password, then the hash matches the new password, all sessions for that user are deleted, and the token cannot be reused.
- RST-05: Given an expired or used token, when reset-password is posted, then the response is 400 and the password is unchanged.
- RST-06: Given a valid token, when the new password is too weak, then the response is 400 and the hash is unchanged.
- RST-07: Given the sign-in screen, when the person opens Forgot password and submits an email, then forgot-password is called and the confirmation is shown.
- RST-08: Given a reset link with a token, when the person submits matching valid passwords, then they land on sign-in with the success notice.
- RST-09: Given the reset form, when the two password fields differ, then a mismatch message is shown and no API call is made.
Not yet implemented¶
Out of scope¶
- Operator / admin-portal password reset.
- An admin setting another user's password.
- Rate limiting beyond single-use short-lived tokens.
Open questions¶
- None.