DEV Community

briankarlsayen
briankarlsayen

Posted on

Login / Register authentication

Overview

This is a simple login authentication for backend. You need to basic understanding on how to use Express.js, Mongoose, and Node.js. I assumed that you already have an app that is connected to MongoDB so I won't explain on that and just focus on the login and register part.

You need to install the following libraries:

yarn add express jsonwebtoken bcrypt
Enter fullscreen mode Exit fullscreen mode

Technologies

In high level explanation:

  1. express.js - backend web application framework for Node.js
  2. jsonwebtoken - standard way of transmitting information between parties as a JSON object.
  3. bcrypt - is a password-hashing function.

The code

Register

Let's say we are registering a google account. There are rules that we need to follow, those rules should be met in order to successfully create and account. Here we call them error handling.

Let's check if the request is in proper type and length:

const {username, password, email} = req.body;
  if (!username || typeof username !== "string"){
    return res.json({status: 'error', error: 'Invalid username'})
  }
  if (!password || typeof password !== "string"){
    return res.json({status: 'error', error: 'Invalid password'})
  }
  if (password.length < 6){
    return res.json({status: 'error', error: 'Password too short. Should atleast be 6 characters'})
  }
  if (!email || typeof password !== "string"){
    return res.json({status: 'error', error: 'Invalid Email'})
  }
Enter fullscreen mode Exit fullscreen mode

Then check if it is unique:
User is the name of the mongoDB model.

const newUser = await User.findOne({username}).lean()
const newMail = await User.findOne({email}).lean()
if(newUser){
    return res.status(500).json({status: 'error', error: 'Username is already inuse'})
  }
  if(newMail){
    return res.status(500).json({status: 'error', error: 'Email is already inuse'})
  }
Enter fullscreen mode Exit fullscreen mode

After that we hash the password to be unreadable in the database:

const user = new User({
    username: username,
    password: await bcrypt.hash(password, 10),
    email: email
  })
Enter fullscreen mode Exit fullscreen mode

Then try to save the account in the database:

try {
    const saveUser = await user.save()
    res.status(200).json({status:'ok', message: 'Account succesfully made'})
  }
  catch(err){
    return res.status(400).json({msg: err.message})
  }
Enter fullscreen mode Exit fullscreen mode

When you've register an account you will notice that the password is different from what you've typed.

Login

You need first to create a secret token, it is like your housekey, use to prevent others from accessing your important things while making you able to access it.

JWT_SECRET = I'm am the key~~@-@~~E.
Enter fullscreen mode Exit fullscreen mode

Hashing is a one-way operation which means the server cannot decrypt the password. What you can do is to compare the hashed typed(password) and server password(user.password) to verify.

bcrypt.compare(password, user.password)
Enter fullscreen mode Exit fullscreen mode

jwt.sign is used to create a token that usually is stored in the localstorage to access the data.

const token = jwt.sign({ id: user._id, username: user.username}, JWT_SECRET)
Enter fullscreen mode Exit fullscreen mode

Login Fullcode

const {username, password} = req.body;
JWT_SECRET = I'm am the key~~@-@~~E.

  // check username, password, email exist
  if (!username || typeof username !== "string"){
    return res.json({status: 'error', error: 'Invalid username'})
  }
  if (!password || typeof password !== "string"){
    return res.json({status: 'error', error: 'Invalid password'})
  }
  if (password.length < 6){
    return res.json({status: 'error', error: 'Password too short. Should atleast be 6 characters'})
  }

  try {
    const user = await User.findOne({username}).lean()  
    if(!user){
      return res.status(500).json({status: 'error', error: 'Invalid username or password'})
    }
    if(await bcrypt.compare(password, user.password)){
      const token = jwt.sign({ id: user._id, username: user.username}, JWT_SECRET)
      return res.status(200).header('auth-token', token).send({token, status: 'ok'})
    }
    return res.status(500).json({status: 'error', error: 'Invalid username or password'})
  }
  catch(err){
    return res.status(500).json({msg: err.message})
  }
Enter fullscreen mode Exit fullscreen mode

Register Fullcode

const {username, password, email} = req.body;
  if (!username || typeof username !== "string"){
    return res.json({status: 'error', error: 'Invalid username'})
  }
  if (!password || typeof password !== "string"){
    return res.json({status: 'error', error: 'Invalid password'})
  }
  if (password.length < 6){
    return res.json({status: 'error', error: 'Password too short. Should atleast be 6 characters'})
  }
  if (!email || typeof password !== "string"){
    return res.json({status: 'error', error: 'Invalid Email'})
  }
  const newUser = await User.findOne({username}).lean()
  const newMail = await User.findOne({email}).lean()
  if(newUser){
    return res.status(500).json({status: 'error', error: 'Username is already inuse'})
  }
  if(newMail){
    return res.status(500).json({status: 'error', error: 'Email is already inuse'})
  }
  const user = new User({
    username: username,
    password: await bcrypt.hash(password, 10),
    email: email
  })
  try {
    const saveUser = await user.save();
    //res.send({user: user._id})
    res.status(200).json({status:'ok', message: 'Account succesfully made'})
  }
  catch(err){
    return res.status(400).json({msg: err.message})
  }
Enter fullscreen mode Exit fullscreen mode

Top comments (0)