Should my promise be rejected if the user account already exists?

Viewed 23

I want to understand some best practices about handling user login and sign up requests.

For example, if the user tries to sign up with their email, and their account already exists, what should happen? Should my server reject the request? Or should I fulfill the request with some status code, and handle it on client side?

Currently, my code below will fulfill the request and send a custom message and i handle it from the client

app.post('/signup', (req, res) => {
  const email = req.body.email
  const plainTextPassword = req.body.password;

  //check if user already exists 
  User.find({ email: email }, (err, existingUser) => {
    //account doesnt exist
    if (existingUser.length === 0) {
      bcrypt.hash(plainTextPassword, saltRounds, async (err, hash) => {
        try {
          const user = new User({
            email: email,
            password: hash
          });
          let result = await user.save();
          if (result) {
            res.send(result)
          }

        } catch (e) {
          res.send(e);
        }
      })
    } else {
      //notify user that account exists
      res.json("account exists")
    }
  })

})

where can i read more about this type of practices? thanks

1 Answers

HTTP has some conventions for this, but there is still a lot of flexibility in how you choose to signal this. Also, a lot of devs frankly ignore these conventions and make up insane crap all the time, like returning 200 OK even for completely broken requests -- and as long as their own code is the only consumer, it usually doesn't matter. You can and should do better, but the software police will not come after you if you don't.


HTTP defines a bunch of status codes that servers can use.

One way to handle this would be to return 409 Conflict, which in this scenario would be interpreted as "you're asking me to create an account for an identifier that is already claimed."

That's honest, but does have one drawback: it allows an evil person to figure out which email accounts have already signed up with you. So, although I'd say this is the perfect response code, you probably must not use it because it violates the privacy of your users.

400 Bad Request is less honest (you usually want to reserve this for requests that are badly shaped -- missing data or wrong data types) and has the same problem as 409: it lets an attacker confirm whether a particular identifier is already claimed.

So, when it comes to setting up user accounts, you probably have to always signal success as long as the request is well-formed, but the UI then needs to hedge its representation: instead of saying to the user "Account created successfully!", it probably needs to say something like "A confirmation email has been sent to [that address] to help you finish setting up your account."

And then you'd send a verify-your-email message to that account if and only if that address is not already signed up.


I should just add: very special rules apply when you are talking about registering accounts as opposed to basically any other kind of REST. If you were building a microservice that kept track of cake recipes, you would probably follow more straightforward rules. But account registration necessarily drags in all kinds of extremely important security and privacy considerations that force your endpoint to be... circumspect to the point of dishonesty.

Related