Auto-Create Email/Password Users?

Hi, i am using the realm-web sdk to login or register my users. At the moment, i am using to forms: one for login and one for register new users. I want to merge the forms into one. If the user exists, he will be logged in, otherwise a user will be created automatically and a confirmation email will be sent.

But that doesn’t seem to be possible via the email/password provider, does it? If i want to register a new user, i need to run app.emailPasswordAuth.registerUser(email, password) If i want to register a user, i need to run app.login(credentials)

How can I unite this? Can I check already after entering the email address if a user with this address already exists or would I have to create an extra function that is then executed by the system user? (Personally I would find this a bit cumbersome)

I would probably attempt a logIn with the email / password and if that fails, register the user and perform the logIn again.

Something along the lines of:

async function logInOrRegister(app, email, password) {
  const credentials = Realm.Credentials.emailPassword(email, password);
  try {
    // The await here is important to allow catching any error
    return await app.logIn(credentials);
  } catch (e) {
    await app.emailPasswordAuth.registerUser(email, password);
    return app.logIn(credentials);
  }
}
1 Like

Hi @kraenhansen

thank you for this idea. It works, but i have some problems with this. Assume that a user types a wrong password, i get the error: “Invalid username/password” - that is fine, since this error does not reveal any sensitive information. However, it is not possible to deduce whether the email address has already been confirmed or not.

After all, if the login fails, the register function is called immediately. From this I then get the error that the username already exists.

It is difficult for me to find out whether a user exists or not, is verified or not, because the error messages do not clearly indicate this. Is there a way to improve this? I would not like to switch back to two forms (login/register)

I believe this is by design, to make it more difficult to probe the login endpoint for email addresses that already have an account on an app.

The errors thrown have an error message from the server that you can use to build your logic around. I threw together a more complete example that includes requesting resending the confirmation email:

async function logInOrRegister(app, email, password) {
  if (app.currentUser) {
    await app.removeUser(app.currentUser);
  }
  const credentials = Realm.Credentials.emailPassword(email, password);
  try {
    // The await here is important to allow catching any error
    return await app.logIn(credentials);
  } catch (e) {
    console.log("Log in failed:", e.error);
    if (e.error === "confirmation required") {
      await app.emailPasswordAuth.resendConfirmationEmail(email);
      throw new Error("Confirmation mail has been sent");
    } else if (e.error === "invalid username/password") {
      try {
        await app.emailPasswordAuth.registerUser(email, password);
        return await app.logIn(credentials);
      } catch (e2) {
        console.log("Register followed by log in failed:", e2.error);
        if (e2.error === "confirmation required") {
          throw new Error("Confirmation mail has been sent");
        } else if (e2.error === "name already in use") {
          throw new Error("Invalid password!");
        } else {
          throw e2;
        }
      }
    } else {
      throw e;
    }
  }
}

I hope this helps.

1 Like

Hi @kraenhansen

thanks for your update. I will try that in my app. One more question about the login flow. With Firebase, after about 10 failed login attempts, the account is temporarily locked. Can something like this also be implemented in Realm to increase security? Is it possible to set up functions with triggers that count how often a login failed? Could you show me an example of this so I can get an idea of how to implement something like this? Thank you

Can something like this also be implemented in Realm to increase security?

I believe this is out of my expertise (I honestly don’t know - I’m working on the Realm JS SDK team).

Perhaps someone else on the forum knows?