netlify-labs / react-netlify-identity

a tiny (4kb) React hook for using Netlify Identity, no UI. SEEKING MAINTAINERS
https://netlify-gotrue-in-react.netlify.com/
156 stars 25 forks source link

How to implement recover account? #39

Closed dorelljames closed 4 years ago

dorelljames commented 4 years ago

In my Recover page, I have a function component that takes the user password. This is given that the token is catched from runRoutes. I basically followed the implementation recovery action guide from here.

The thing that I can't figure out is whether recoverAccount and updateUser is the way to go? Problem is updateUser fails.

recoverAccount(true)
      .then((userFromToken) => {
        console.log("userFromToken", userFromToken);

        // --> This doesn't work. It says, user is not logged in.
        updateUser({ password })
          .then((updatedUser) => {
            setFormState("user_updated");
            console.log("Updated user %s", updatedUser);
          })
          .catch((error) => {
            console.log("Failed to update user: %o", error);
          });
      })
      .catch((error) => {
        console.log(error);
      });

Alternatively, I used verifyToken and setUser which is not recommended. The same updateUser function call doesn't seem to work.

dorelljames commented 4 years ago

In the meantime, this is how I solved it. It feels hacky though. 😅 To call updateUser, you need to login but you can't use loginUser as it requires a password (old password) which you don't have, so it's setUser to the rescue.

recoverAccount(true)
      .then(async (userFromToken) => {
        // Force set user here to login
        await setUser(userFromToken);

        if (user) {
          updateUser({ password })
            .then((updatedUser) => {
              console.log("Updated user %s", updatedUser);
            })
            .catch((error) => {
              console.log("Failed to update user: %o", error);
            });
        }'
      })
      .catch((error) => {
        console.log(error);
      });
markfazzio commented 4 years ago

@dorelljames I tried your approach and it did not work for me, I keep getting the "user not found" error. I am able to use the token with recoverAccount() and get a successful user response, which I use inside setUser(recoveredUser). But it fails when I go to updateUser() with the error I mentioned above. When I log out the user from useIdentityContext() it is undefined, so I know that setUser() is not working properly. I did not add an await to setUser as it is not a promise. Here is my code:


            if (password !== '' && password === confirmPassword) {
              await recoverAccount(true)
                .then(async user => {
                  setUser(user);
                  await updateUser({ password })
                    .then(updatedUser => {
                      setMessage('Password updated successfully!');
                      setSuccessMode(true);
                    })
                    .catch(error => {
                      console.log('Failed to update user:', error);
                      setMessage(
                        'Password cannot be updated. Please try getting a new recovery link.'
                      );
                    });
                })
                .catch(err => {
                  console.log('Error running recoverAccount()', err);
                });
            } else {
              setMessage('Passwords do not match.');
            }
dorelljames commented 4 years ago

Just for anyone who might stumble on this issue and have tried my suggestion, I'd just add it here that the original workaround I used above is no longer the thing I'm using. recoverAccount(true) sets the user in ReactNetlifyIdentityAPI context after which you could call updateUser function passing in the password to update the user's password. If it helps, you might find this gist helpful. Best of luck.

dorelljames commented 4 years ago

Closing this. Please refer to solution at issue #42. Thanks