You can add a model-based password-reset flow to a Turnkey application that uses SysUserAuthentication; this page is for developers who need to merge, configure, and adapt the Password Reset package.
What this package provides
MDriven Turnkey does not include a fixed built-in password-reset feature. The Password Reset package is a model pattern that you merge into your model and adapt to your application's login and email requirements.
When used with the standard authentication pattern, the package provides:
- A public ViewModel named
ResetPasswordPage, where a user can request a password-reset email. Do not assign access groups to this page, because a user must be able to open it before signing in. - A server-side ViewModel named
SS_ResetPassword. It runs every 20 seconds and sends reset instructions for pending tickets. - A public page where the user supplies and confirms a new password. The page also presents information when a ticket has expired and allows the user to request another ticket when appropriate.
- A
ResetPasswordTicketmodel class that records the reset request, its authorization code, expiry, URL, email-send time, and state history.
For example, a user who cannot sign in opens your application's Forgot password? action. The action opens ResetPasswordPage. The user requests a reset, which creates a ticket. SS_ResetPassword sends the ticket URL by email. The user follows that URL and sets a new password before the ticket expires.
Prerequisites
Before you add the package, confirm the following:
- Your model uses SysUserAuthentication for registration and sign-in. The password-reset pattern extends the user model with password-hashing and password-setting behavior.
- An email server is available for the MDrivenServer/Turnkey environment. The server-side ViewModel cannot deliver reset instructions until those settings are configured.
- You have decided which application action or link users will use to open
ResetPasswordPage.
This package resets an application user's password. It does not reset an MDrivenServer administrator account. If you have lost access to a self-hosted MDrivenServer, follow Documentation:MDrivenServer, Lost password or locked out instead. For container-specific administrator recovery, see Documentation:Deploying MDriven Server and Turnkey with Docker.
Add and configure the package
Merge the model pattern
- Open your model in MDriven Designer.
- In TK Live View, merge the Password Reset pattern into the model.
- Review the imported content before modifying it. A package is a container for a section of the model, so keeping the imported content in its PasswordReset package makes later maintenance easier.
- If your model requires it, set the PasswordReset package's Default superclass. Do this before adapting classes that should inherit from that superclass.
- Confirm that the imported
ResetPasswordTicketclass and the ViewModelsResetPasswordPageandSS_ResetPasswordare present.
When merging into a model that already contains classes or ViewModels with the same names, review the merge result carefully. Model merges combine matching class content and may skip incoming ViewModels with names already present. See Documentation:Model Examples Old for merge behavior and the downloadable password-reset template.
Configure email delivery
- Open the MDrivenServer control panel.
- Select Running and then Model.
- Edit the email settings for the deployed model.
- Open the
SS_ResetPasswordViewModel. - Update the expression in its
fromcolumn so that it evaluates to the sender email address to use for reset messages. - Deploy the updated model and test delivery to a controlled email address.
The sender address is model configuration, while the server email settings provide the delivery configuration. Both must be correct. A reset request can create a ticket even when mail delivery is not configured, but the user will not receive the reset URL.
Add the entry point
- Create an action in an appropriate public location, such as a Forgot password? link near your login UI.
- Configure the action to open the
ResetPasswordPageViewModel. - Ensure that
ResetPasswordPagehas no access groups. - Test the action while signed out. A signed-out user must be able to reach the request page.
Keep the page public, but do not use a user identity supplied through a URL or page input to access account data directly. The reset flow should use the ticket's unique authorization code to identify the requested reset.
How a reset ticket works
A ResetPasswordTicket represents one password-reset request. It has a unique authorization code and a time limit. The ticket URL directs the user to the password-setting page, where the model validates the ticket before allowing a password change.
The pattern's default ticket expiry is 120 minutes. Change that behavior in ResetPasswordTicket.OnCreate if your application requires a different expiry period, then test both valid and expired links.
| Item | Purpose | Example |
|---|---|---|
ResetAuthorizationCode
|
Unique token that identifies a reset ticket. | A reset URL contains the ticket code so the application can locate the requested ticket. |
Expires
|
Date and time when the ticket is no longer valid. | A ticket created at 10:00 with the default expiry becomes invalid at 12:00. |
ResetPasswordURL
|
URL sent to the user for setting a new password. | The email contains this URL rather than a password. |
Sent
|
Date and time when the reset email was sent. | Use it to distinguish a created request from a delivered reset instruction attempt. |
ResetLog
|
Text log of reset-request state changes. | The model can record ticket creation, sending, expiry, and completion. |
ResetPasswordTicket reference
Attributes
| Attribute | Type | Description |
|---|---|---|
Expires
|
DateTime?
|
Expiry date and time for the ticket. |
ResetAuthorizationCode
|
String?
|
Unique token used to identify the user's reset-password ticket. |
ResetLog
|
Text?
|
Log used to track state changes in the password-reset process. |
ResetPasswordURL
|
String?
|
URL used to open the password-reset flow for this ticket. |
Sent
|
DateTime?
|
Date and time when the email containing the reset URL was sent. |
vNewPassword
|
String?
|
Transient value that captures the new password supplied by the user. |
vNewPasswordConfirm
|
String?
|
Transient confirmation value used to verify the new password entry. |
/CanNewTicketBeSent
|
Boolean
|
Derived value that determines whether a new ticket can be sent by checking for existing tickets waiting to be sent or already sent. |
/IsValid
|
Boolean
|
Derived value that indicates whether the ticket has not expired. |
/ShowDoneUI
|
Boolean
|
Derived value used to show the completion UI after the password has been reset. |
/ShowResetUI
|
Boolean
|
Derived value used to show the UI that accepts the new-password fields. |
Methods
| Method | Arguments / return type | Behavior |
|---|---|---|
AddToLog
|
aText â Text
|
Adds text to ResetLog so that the ticket retains a process history.
|
GetExpiresInMinutes
|
Returns Integer
|
Returns the number of minutes remaining before the ticket expires. |
OnCreate
|
â | Initializes ResetAuthorizationCode, ResetPasswordURL, and Expires. The default expiry is 120 minutes.
|
OnStateChange
|
â | Captures ticket state changes in ResetLog.
|
SysUser behavior used by the package
The package uses the SysUser password behavior supplied by SysUserAuthentication. Password values are hashed before they are stored in PasswordHash.
| Method | Arguments / return type | Behavior |
|---|---|---|
GetResetPasswordTicket
|
Returns ResetPasswordTicket
|
Expires password-reset requests that have passed their expiry time. It returns the user's sent ticket when one is available; otherwise, it creates a new ticket. |
HashPassword
|
pwd: String; returns String
|
Hashes a password value. |
SetPassword
|
pwd: String
|
Sets PasswordHash by using HashPassword.
|
Do not replace SetPassword with direct assignment of a plaintext password. The pattern is designed to store a password hash, not the password supplied in vNewPassword.
Test the complete flow
Test with a non-administrator application user and a mailbox you control.
- Sign out of the application.
- Open the action that navigates to
ResetPasswordPage. - Request a password reset.
- Confirm that a
ResetPasswordTicketis created and that its log records the expected state change. - Wait for the
SS_ResetPasswordcycle, which runs every 20 seconds, and confirm that the email arrives. - Open the URL in the email before expiry. Enter matching values for the new password and confirmation.
- Sign in with the new password.
- Request another reset, allow it to expire, and verify that the expired-ticket UI explains that a new ticket is required.
If email does not arrive, first verify the MDrivenServer email settings and the from expression in SS_ResetPassword. If a link is rejected unexpectedly, inspect the ticket's Expires, /IsValid, and ResetLog values.
Adapt the pattern deliberately
The imported pattern is intended to be changed to fit your application. Common changes include:
- Changing the expiry calculation in
OnCreate. - Changing the text and sender address of reset instructions in
SS_ResetPassword. - Placing the public reset action in your own login experience.
- Adjusting the public reset and completion UI while retaining the ticket validation and password-hashing behavior.
When you customize the flow, retest valid links, expired links, duplicate requests, email delivery, and sign-in with the changed password.
