Build a Password Reset Flow With the API
On this page
If you build your own login pages with the Login API, build your own forgot password pages as well. This guide shows the API calls behind each step of the forgot password workflow.
Prerequisites#
- A forgot password template on the TenantA logical container for Users, Applications, and settings that is isolated from other Tenants. for each identity type your users log in with. See Choose the Forgot Password Templates. To deliver the change password Id yourself, skip the templates and see Send the Message Yourself.
- An API key for the steps that run on your server.
Point the Message at Your Page#
The default forgot password templates link to the FusionAuth change password page. Edit the email and message templates to link to your own page instead, and pass the change password Id in the URL:
https://app.example.com/reset-password?id=${changePasswordId}
For the other template variables, see the email template reference and the message template reference.
Start the Workflow#
When the user submits your forgot password form, call the Forgot Password API. Your browser code can call the API without an API key:
POST /api/user/forgot-password
Content-Type: application/json
{
"applicationId": "e9fdb985-9173-4e01-9d73-ac2d60d1dc8e",
"loginId": "richard@example.com",
"loginIdTypes": ["email", "phoneNumber", "username"],
"state": {
"redirect": "/settings"
}
}
loginIdTypes defaults to email and username. Add phoneNumber to let users recover by text message. FusionAuth sends a text message when the login Id matches a phone number, and an email otherwise.
applicationId selects the Application's templates, when the Application has templates. FusionAuth returns state when the user completes the workflow, so your page can return the user to the right place.
Without an API key, the API returns an empty 200 response whether or not the user exists. With an API key, the API returns 404 for an unknown user and 422 for a user with no email address or phone number. Show the same confirmation to the user for all of these responses, so your page doesn't reveal which accounts exist. See Account Enumeration.
A 403 response means the workflow is off for that identity type. See Turn Off Forgot Password.
Send the Message Yourself#
To deliver the change password Id through your own email or messaging system, call the API from your server with an API key, and set sendForgotPasswordMessage to false:
{
"loginId": "richard@example.com",
"sendForgotPasswordMessage": false
}
FusionAuth creates the Id without sending a message, and returns the Id in the response:
{
"changePasswordId": "YkQY5Gsyo4RlfmDciBGRmvfj3RmatUqrbjoIZ19fmw4"
}
Keep the Id on your server until you send the Id to the user. Anyone who holds the Id can set the user's password.
Check the Change Password Id#
When the user opens the link, check the Id before you show the new password form. Call the Validate Password Change API:
GET /api/user/change-password/YkQY5Gsyo4RlfmDciBGRmvfj3RmatUqrbjoIZ19fmw4
The response tells your page what to show:
200: show the new password form.404: the Id expired or was already used. Ask the user to start again.400with the[TrustTokenRequired]error: the user has MFA enabled. Complete an MFA challenge first, as shown in Handle Users With MFA.
The check doesn't use up the Id.
Change the Password#
Send the Id and the new password to the Change Password API:
POST /api/user/change-password
Content-Type: application/json
{
"changePasswordId": "YkQY5Gsyo4RlfmDciBGRmvfj3RmatUqrbjoIZ19fmw4",
"password": "a-new-password"
}
When the password breaks a Tenant password rule, the API returns 400 with field errors for password, and the Id still works. Show the errors and let the user try again.
On success, the API returns a one-time password and the state from the first request:
{
"oneTimePassword": "A2o6I0Bylr2yzNPu4Y_ld0jE-BkG9RfEX8QORl9fe6U",
"state": {
"redirect": "/settings"
}
}
Log the User In#
To log the user in without asking for the new password, send the one-time password to the Login API from your server:
{
"applicationId": "e9fdb985-9173-4e01-9d73-ac2d60d1dc8e",
"oneTimePassword": "A2o6I0Bylr2yzNPu4Y_ld0jE-BkG9RfEX8QORl9fe6U"
}
The response contains the user's access token, as for any other login. To ask the user to log in again instead, skip this step.
Handle Users With MFA#
A user with MFA enabled must pass an MFA challenge before FusionAuth accepts a new password. The challenge produces a trust token, which you send with the new password. Run these steps on your server, because the first step needs an API key:
- Call the Start Multi-Factor API with the user's login Id and a long, random
trustChallenge. Keep thetrustChallengeon your server. The response contains atwoFactorIdand the user's MFA methods. - Ask the user for a code. For an email or SMS method, send the code first with the Send a Multi-Factor Code API. An authenticator app user reads the code from the app.
- Call the Complete a Multi-Factor Login API with the
twoFactorIdand the code. The response contains atrustToken. - Call the Change Password API with the
trustTokenand the sametrustChallengefrom the first step:
{
"changePasswordId": "YkQY5Gsyo4RlfmDciBGRmvfj3RmatUqrbjoIZ19fmw4",
"password": "a-new-password",
"trustChallenge": "c2FtcGxlLXRydXN0LWNoYWxsZW5nZQ",
"trustToken": "WbWqpLXGQb7RVMd2Re1PK5gGtJSnYzFZbIGNsfD9yQk"
}
Without the matching trustChallenge, the API rejects the trust token with the [TrustTokenRequired] error. For more about trust tokens, see Trust Tokens and Trust Challenges.
Test the Flow#
To confirm that the flow works:
- Submit your forgot password form for a test user.
- Open the link in the email or text message.
- Set a new password.
- Log in with the new password.
- Open the link again. Your page shows that the Id expired.
Repeat the test with a user who has MFA enabled, and with a phone number if your users recover by text message.
Related
Learn how FusionAuth lets users reset a forgotten password by email or text message, and how recovery interacts with MFA, sessions, and account lockout.
API documentation for the FusionAuth Change a User's Password API.
Learn how to let users reset a forgotten password by email or text message on the FusionAuth hosted login pages.
Learn how to turn off the forgot password workflow for a FusionAuth tenant and hide the forgot password link on the hosted login pages.