(FusionAuth 1.33.0. Update) How to Update the Password Reset Functionality for Users that Have Two-Factor On?
-
Overview
Password reset functionality has changed for users that have two-factor on in the
1.33.0
release. I am trying to accomplish the two following user flows that were previously possible, and are possible in other systems I've tried:- User is logged in and wants to change their password
- User is resetting their password using the reset password email
The two API's I'm using to achieve these are apart of the Change a User's Password API.
- (Logged in flow)
POST /api/user/change-password
- (Email flow)
POST /api/user/change-password/{changePasswordId}
Each of these API's has a new requirement for a
trustToken
that was introduced in the1.33.0
release. The only way that I've seen to obtain atrustToken
is during the login flow, even if I'm making the change using API Key Authentication. ThetrustToken
seems to not be available when I need to make a call to the API.User flows
I'm not sure how to obtain my two desired user flows:
User is logged in and wants to change their password
The desired flow is that the user logs in and navigates to their account settings and updates their password by entering their old password and a new password. If a user refreshes the page, they will still be logged in but I will no longer have the trust token. Currently I don't have to store any data during the login process, this is all handle through cookies that are added by FusionAuth and inaccessible by client side JavaScript. What is the recommended path for achieving this user flow?
User is resetting their password using the reset password email
The desired flow for this is that a user puts in their email into a field and they receive an email with a reset password link. When they click on the link it takes them to a page where they enter a new password, then they can log in with their new password.
During this flow the user isn't able to log in to the application, so they are unable to retrieve a
trustToken
. What is the recommended path for achieving this user flow?
Thanks in advance for any help.
-
When the Change Password API returns
400
indicating that trust is required, you'll need to obtain a trust token.{ "generalErrors" : [ { "code" : "[TrustTokenRequired]", "message" : "This request requires a Trust Token. Use the Start Two-Factor API to obtain a Trust Token required to complete this request." } ] }
To obtain a trust token, complete a Two Factor login.
POST /api/two-factor/start
POST /api/two-factor/login
The completion of the Two Factor Login will return a
trustToken
value in the response body. This token can be used to complete the Change Password API.If you want to scope the
trustToken
returned by the Two Factor Login request for use by the Change Password API, you may provide atrustChallenge
in the request body on the Start API. When you do this, the same value must be provided when you use thetrustToken
on the Change Password API. In this way you can ensure that thetrustToken
may only be used for the intended purpose.It looks like the APIs may not have this example outlined, we'll review the doc and see what needs to be updated.
-
Thanks for the reply. This was very helpful!
This allowed me to get much further, but now I'm running into a separate issue completing the flow. When I provide the trust token to the
POST /api/user/change-password
it is still giving me the[TrustTokenRequired]
error code — the same one you have in your message. I'm not sure what I'm doing wrong. Here is the full flow that I'm doing:POST /api/two-factor/start
POST /api/two-factor/login
POST /api/user/change-password
Note: The version I'm updating to is 1.35.0, two versions after the Change Password API changed.
Two-factor Start
POST /api/two-factor/start
Headers
{ "Authorization": "API_KEY", "Accept": "application/json" }
Body
{ "loginId": "testemail@test.com" }
Response
200
{ "code": "CODE", "methods": [ { "authenticator": { "algorithm": "HmacSHA1", "codeLength": 6, "timeStep": 30 }, "id": "METHOD_ID", "method": "authenticator" } ], "twoFactorId": "TWO_FACTOR_ID" }
Two-factor Login
POST /api/two-factor/login
Headers
{ "Authorization": "API_KEY", "Accept": "application/json" }
Body
{ "code": "CODE", "twoFactorId": "TWO_FACTOR_ID", }
Response
200
{ "token": "TOKEN", "tokenExpirationInstant": TOKEN_EXPIRATION_INSTANT, "trustToken": "TRUST_TOKEN", "user": { "active": true, "connectorId": "CONECTOR_ID", "data": { "companyId": "COMAPNY_ID" }, "email": "EMAIL", "firstName": "FIRST_NAME", "id": "ID", "insertInstant": INSERT_INSTANCE, "lastLoginInstant": LAST_LOGIN_INSTANCE, "lastName": "LAST_NAME", "lastUpdateInstant": LAST_UPDATE_INSTANCE, "passwordChangeRequired": PASSWORD_CHANGE_REQUIRED, "passwordLastUpdateInstant": PASSWORD_LAST_UPDATE_INSTANT, "registrations": [ { "applicationId": "APPLICATION_ID", "id": "ID", "insertInstant": INSERT_ID, "lastLoginInstant": LAST_LOGIN_INSTANT, "lastUpdateInstant": LAST_UPDATE_INSTANT, "roles": [ "ROLE_NAME" ], "usernameStatus": "ACTIVE", "verified": true } ], "tenantId": "TENENT_ID", "twoFactor": { "methods": [ { "authenticator": { "algorithm": "HmacSHA1", "codeLength": 6, "timeStep": 30 }, "id": "ID", "method": "authenticator" } ] }, "usernameStatus": "ACTIVE", "verified": true } }
Change Password
POST /api/user/change-password
Headers
{ "Authorization": "API_KEY", "Accept": "application/json" }
Body
TheTRUST_TOKEN
supplied is the one returned from the previousPOST /api/two-factor/login
call{ "loginId": "testemail@test.com", "currentPassword": "CURRENT_PASSWORD", "password": "NEW_PASSWORD", "trustToken": "TRUST_TOKEN" }
Response
400
{ "generalErrors": [ { "code": "[TrustTokenRequired]", "message": "This request requires a Trust Token. Use the Start Two-Factor API to obtain a Trust Token required to complete this request." } ] }
-
If I include a
trustChallenge
it works. -
@stephen Thanks for the update.
That is correct, if you do provide a
trustChallenge
on the Two Factor Start API, it must be used in along with thetrustToken
.This allows you the option to bind a
trustToken
to a particular request.Are you indicating that it now works as you expect, or that you did not provide a
trustChallenge
during the Two Factor Start API, and it is still saying it is required when completing the Change Password API? In your example you only show you are sending aloginId
, so if that is the case let me know. -
@robotdan Thanks for the response.
This is not working as I expected. When I didn't provide a
trustChallenge
to the Two Factor Start API, I couldn't get the Change Password API to work. The message indicated that I needed to provide atrustToken
, even though I was passing this into the API.The workaround I found is that it worked when I provided a
trustChallenge
in the Two Factor Start API and the Change Password API. -