0

I'm trying to let the user login using the username or email, I didn't know how to implement it, now I have the user logging in using it's email.

auth.js:

//LOGIN
router.post("/login", async (req, res) => {
    try {
      const user = await User.findOne({ email: req.body.email });
      !user && res.status(400).json("Wrong credentials!");
  
      const validated = await bcrypt.compare(req.body.password, user.password);
      !validated && res.status(400).json("Wrong credentials!");
  
      const { password, ...others } = user._doc;
      return res.status(200).json(others);
    } catch (err) {
      return res.status(500).json(err);
    }
  });

How can I let the user login using email or username with one input?

sultan.h
  • 331
  • 1
  • 4
  • 16

3 Answers3

1

It seems you're using Sequelize to query your database.

You can use the where clause and provide an Op.or to filter by email or username.

const { Op } = require("sequelize");

// Query
const user = await User.findOne({
  where: {
    [Op.or]: [
      {
        email: {
          [Op.like]: req.body.email,
        },
      },
      {
        username: {
          [Op.like]: req.body.username,
        },
      },
    ],
  },
})
Alex Ruheni
  • 989
  • 5
  • 6
1

You can identify whether it is email or userame.

const isEmail=/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(req.body.identifier)

Then you can use query accordingly.

const user = await User.findOne(
    isEmail ? ({ email: req.body.identifier }) : ({username: req.body.identifier})
);

This will make your query simpler and faster.

Avkash
  • 439
  • 4
  • 8
  • I'm getting this error "Type annotations can only be used in TypeScript files." – sultan.h Sep 19 '22 at 05:31
  • I am not sure! Is error occuring on any of above lines I mentioned? @sultan.h – Avkash Sep 19 '22 at 06:01
  • 1. I replaced test(req.body.identifier) with test(req.body.email) 2. I replaced ({ email: req.body.identifier }) : ({username: req.body.identifier}) with { email: req.body.email }) : ({username: req.body.username} 3. the error occurred on isEmail ? ({ email: req.body.email }) : ({username: req.body.username}) 4. I fixed it by disabling JavaScript › Validate but it didn't work I get "Request failed with status code 500" on my console. – sultan.h Sep 19 '22 at 06:34
  • SO the point of doing this is, you need to pass email or username in the query. So from frontend you will only get one, either email or username in the body. So if you are sending input in `req.body.email` then in both condition you need to fetch it like `isEmail ? ({ email: req.body.email }) : ({username: req.body.email})` , as `req.body.username` will give you undefined. – Avkash Sep 19 '22 at 07:44
0

You can try to get a user from both email and username. If its from the same input and you can't make the difference from your client app you can do something like that.

const user =
   (await User.findOne({ email: req.body.loginInput })) ||
   (await User.findOne({ username: req.body.loginInput })) 

But that would do 2 db queries for each user that want to sign in with username.

The best would be to use a reggex on your client app that recognize if its an email and then you could have 2 differents fields on you POST data.

lafusew
  • 161
  • 1
  • 9
  • please have a look here as the question is more clear https://stackoverflow.com/questions/73771949/how-to-know-if-the-input-is-email-or-username?noredirect=1#comment130267321_73771949 – sultan.h Sep 19 '22 at 11:56