FusionAuth
    • Home
    • Categories
    • Recent
    • Popular
    • Pricing
    • Contact us
    • Docs
    • Login

    (FusionAuth 1.33.0. Update) How to Update the Password Reset Functionality for Users that Have Two-Factor On?

    Scheduled Pinned Locked Moved Unsolved
    Q&A
    2
    6
    4.5k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      stephen
      last edited by

      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:

      1. User is logged in and wants to change their password
      2. 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.

      1. (Logged in flow) POST /api/user/change-password
      2. (Email flow) POST /api/user/change-password/{changePasswordId}

      Each of these API's has a new requirement for a trustToken that was introduced in the 1.33.0 release. The only way that I've seen to obtain a trustToken is during the login flow, even if I'm making the change using API Key Authentication. The trustToken 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.

      robotdanR 1 Reply Last reply Reply Quote 0
      • robotdanR
        robotdan @stephen
        last edited by robotdan

        @stephen

        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.

        1. POST /api/two-factor/start
        2. 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 a trustChallenge in the request body on the Start API. When you do this, the same value must be provided when you use the trustToken on the Change Password API. In this way you can ensure that the trustToken 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.

        S 1 Reply Last reply Reply Quote 1
        • S
          stephen @robotdan
          last edited by

          @robotdan

          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:

          1. POST /api/two-factor/start
          2. POST /api/two-factor/login
          3. 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
          The TRUST_TOKEN supplied is the one returned from the previous POST /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."
              }
            ]
          }
          
          S 1 Reply Last reply Reply Quote 0
          • S
            stephen @stephen
            last edited by

            @robotdan

            If I include a trustChallenge it works.

            robotdanR 1 Reply Last reply Reply Quote 0
            • robotdanR
              robotdan @stephen
              last edited by

              @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 the trustToken.

              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 a loginId, so if that is the case let me know.

              S 1 Reply Last reply Reply Quote 0
              • S
                stephen @robotdan
                last edited by

                @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 a trustToken, 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.

                1 Reply Last reply Reply Quote 0
                • P pedroparente referenced this topic on
                • First post
                  Last post