Changing a user's realm password without sending an email

I’d like to update a user’s realm password without a reset email.
I already have a password reset email system working.

The current flow is:

  • User requests a password change.
  • This hits an endpoint that triggers an email to the user which contains a link to a password change form, with a unique token.
  • Submitting the password change form on that page hits another endpoint that changes the password field on a MongoDB user record. This is used to manage access to tokens, etc. via the API.
  • But now the password on the user record is updated and the password for the realm user is not. So the token I’m building to facilitate jwt login on Realm is not working.

How do I change the Realm password without the email verification or the user’s password?

The option I’m looking at right now:

  1. It kinda looks like I can call a reset password function like this

await app.emailPasswordAuth.resetPassword({ password: “newPassw0rd”, token, tokenId });

But I want to do that without the token section, something more like (userID, newPassword). Which seems to maybe be possible via the realm function editor. But also, ideally I’d perform this action from my node API, where I’m not importing realm, so I don’t have access to that app object. So if it’s even possible, I’d have to add a whole package just for this. None of this makes much sense.

Still not sure I’m headed the right direction, but I was able to get the custom function to work, so that’s something.

Here’s where I am:
From my react frontend, I import realm and initiate an app instance in a component.

import * as Realm from "realm-web";
const realmApp = new Realm.App({ id: REALM_APP_ID });

Then, in an action, I call the password reset function on that instance.
realmApp.emailPasswordAuth.callResetPasswordFunction(email, password, {});

What this does is interesting, and I would argue not terribly clear from the documentation. In the the Realm interface, if you click the ‘Functions’ option from the sidebar, which is under the ‘Build’ category header, you get a function editor. Here you can edit the function that is called when you call the password reset functions from your app. You enter your function and click save. Right now, my function is something like this.

exports = (stuff) => {
  // will not reset the password
  console.log("id: " + Object.keys(stuff))
  console.log("token: " + stuff.token)
  console.log("token id: " + stuff.tokenId)
  console.log("username: " + stuff.username)
  console.log("password: " + stuff.password)

  console.log("context: " + Object.keys(context.user))
  console.log("id: " + context.user.id)
  
  return { stuff };
};

(I just have a bunch of logs to explore some of the stuff you have access to in the function.)

Now if I call the .callResetPasswordFunction function from my app, and then I go back to the Realm web interface and checkout the ‘Logs’ I see a log from this call. Hit the caret to reveal the details and I see my logs.

Now I’m just trying to verify that the password was changed. I introduced some bugs in the auth system along the way here.

I thought I had this half way working the other day, but now I’m getting an error:

Error: Request failed (POST https://stitch.mongodb.com/api/client/v2.0/app/funky-radish-twdxv/auth/providers/local-userpass/reset/call): user not found (status 404)
    at _callee22$ (bundle.dom.es.js:2668)
    at tryCatch (runtime.js:63)
    at Generator.invoke [as _invoke] (runtime.js:293)
    at Generator.next (runtime.js:118)
    at asyncGeneratorStep (asyncToGenerator.js:3)
    at _next (asyncToGenerator.js:25)

The custom function is configured to use the System user right now. So what user could not be found?

But also, when I call this function with one specific email, it does succeed. And I’m able to collect logs from the custom function. It is returning the email and username as well as a token ID and a token.
a690cb8b10afefe8b12fde200aea8cebc5ea1ae371a37f9bc4feaad983d2c4afa9b04601ae95f6f15cf699290e3a9524fc28f3363cac72173fe9bae46144915c

However, the password for that account does not seem to have changed.
After resetting the password, when I attempt to login through my standard jwt login, it just creates a new account with the same email.
I’ve adjusted the return statement on the custom function to
return { status: "success" };

Basically back to square one here.

I have one account which seems to allow my custom resetEmail function to run on it. But then when I create a token via my API with the new password or even the old password, JWT login just ends up creating a new user with the same name. I can’t figure out how to validate realm users to make sure that an error gets thrown if an email is already in the system. And I can’t figure out how to access that old user.

@Ryan_Goodwin Are you able to find a way?